Является ли доступ только для чтения к вектору (vector::operator[] и vector::size()) асинхронно-безопасным?
Моя программа должна иметь доступ только для чтения к содержимому vector<string>
в обработчике сигнала для SIGINT
, (Альтернативой является использование массива C-строк фиксированного размера с фиксированной длиной.) Программа предназначена для работы в среде POSIX.
Являются vector::operator[]
а также vector::size()
асинхронно-безопасный (или сигнально-безопасный)?
3 ответа
Ответ Angew правильный, учитывая C++. Теперь, когда в вопросе упоминается среда POSIX, которая может предоставить более сильные гарантии, на этот вопрос требуется другой ответ:
Если процесс многопоточный, или если процесс однопоточный и обработчик сигнала выполняется иначе, чем в результате:
Вызов процесса
abort()
,raise()
,kill()
,pthread_kill()
, или жеsigqueue()
генерировать сигнал, который не заблокированОжидающий сигнал разблокируется и доставляется до того, как вызов, который разблокирован, возвращается
поведение не определено, если обработчик сигнала ссылается на любой объект, кроме
errno
со статической продолжительностью хранения, отличной от присвоения значения объекту, объявленному какvolatile sig_atomic_t
или если обработчик сигнала вызывает любую функцию, определенную в этом стандарте, кроме одной из функций, перечисленных в следующей таблице.
Это... все еще очень слабая гарантия. Насколько я могу понять это:
vector::operator[]
не безопасно Фиксированные массивы не являются безопасными. Доступ к фиксированным массивам безопасен, если массив не является статичным.
Зачем? vector::operator[]
точно не указано, как это должно быть реализовано, только предварительные условия и постусловия. Доступ к элементам массива возможен (если массив нестатичен), это означает, что доступ к векторным элементам также безопасен, если вы создаете указатель (с vec.data()
или же &vec[0]
) до сигнализации, а затем доступ к элементам через указатель.
РЕДАКТИРОВАТЬ: Первоначально я пропустил это, потому что я не знал о sigaction
функция - с signal
вы можете получить доступ только к вашим локальным массивам в обработчике сигнала, но с sigaction
Вы можете предоставить указатели на автоматические и динамические массивы. Тем не менее, совет по использованию как можно меньшего количества обработчиков сигналов здесь применим.
Итог: вы слишком много делаете в своих обработчиках сигналов. Попробуйте сделать как можно меньше. Один из подходов заключается в назначении флага (типа volatile sig_atomic_t
), и вернуться. Позже код может проверить, был ли флаг активирован (например, в цикле событий)
Нет, это не безопасно. С ++11 1,9/6:
Когда обработка абстрактной машины прерывается при получении сигнала, значения объектов, которые не являются ни
- типа
volatile std::sig_atomic_t
ни- незапираемые атомные объекты (29.4)
не указываются во время выполнения обработчика сигнала, и значение любого объекта, не входящего ни в одну из этих двух категорий, которое модифицируется обработчиком, становится неопределенным.
Я считаю, что если вы знаете причину, по которой доступ к вектору небезопасен, вы можете обойти его. Обратите внимание, что доступ по- прежнему не гарантированно безопасен. Но он будет работать на всем, что не является Death Station 9000.
Обработчик сигнала прерывает выполнение программы так же, как обработчик прерывания, если вы программируете непосредственно на аппаратном уровне. Операционная система просто прекращает выполнение вашей программы, где бы она ни находилась. Это может быть в середине чего-либо. Например, если к вашему вектору добавляются элементы, и он обновляет значение размера или копирует содержимое в новый, более длинный вектор, который может быть прерван сигналом. И тогда ваш обработчик сигнала попытается прочитать данные из вектора, что приведет к катастрофе.
Вы можете получить доступ к вектору из обработчика сигнала, если он фактически постоянен. Если вы настроили все это при запуске программы и больше никогда не пишете, это безопасно. Обратите внимание, не безопасно использовать в соответствии с нормативными документами, но эффективно безопасно.
Это очень похоже на многопоточность на одноядерном процессоре.
Теперь, если вам нужно обновить вектор во время работы программы, вам нужно "заблокировать" обработчик сигнала от него, замаскировав сигнал или отключив обработчик перед обновлением вектора, чтобы гарантировать, что обработчик не будет работать во время работы. вектор находится в несогласованном состоянии.