Является ли доступ только для чтения к вектору (vector :: operator [] и vector :: size ()) асинхронно-безопасным?

Моя программа должна иметь доступ только для чтения к содержимому vector<string> в обработчике сигнала для SIGINT, (Альтернативой является использование массива C-строк фиксированного размера с фиксированной длиной.) Программа предназначена для работы в среде POSIX.

Являются vector::operator[] а также vector::size() асинхронно-безопасный (или сигнально-безопасный)?

4

Решение

Ответ Angew правильный, учитывая C ++. Теперь, когда в вопросе упоминается среда POSIX, которая может обеспечить более сильные гарантии, на этот вопрос требуется другой ответ:

Если процесс многопоточный, или если процесс однопоточный и обработчик сигнала выполняется не в результате:

  • Вызов процесса abort(), raise(), kill(), pthread_kill(), или же sigqueue() генерировать сигнал, который не заблокирован

  • Ожидающий сигнал разблокируется и доставляется до того, как вызов, который разблокирован, возвращается

поведение не определено, если обработчик сигнала ссылается на любой объект, кроме errno со статической продолжительностью хранения, отличной от присвоения значения объекту, объявленному как volatile sig_atomic_tили если обработчик сигнала вызывает любую функцию, определенную в этом стандарте, кроме одной из функций, перечисленных в следующей таблице.

Источник: Открытая группа Базовые спецификации, выпуск 7
Стандарт IEEE 1003.1, издание 2013 г., 2.4.3

Это … все еще очень слабая гарантия. Насколько я могу понять это:

vector::operator[] не безопасно Фиксированные массивы не являются безопасными. Доступ к фиксированным массивам безопасен, если массив не является статичным.

Зачем? vector::operator[] точно не указано, как это должно быть реализовано, только предварительные условия и постусловия. Доступ к элементам массива возможен (если массив нестатический), это означает, что доступ к векторным элементам также безопасен, если вы создаете указатель (с vec.data() или же &vec[0]) до сигнализации, а затем доступ к элементам через указатель.

РЕДАКТИРОВАТЬ: Первоначально я пропустил это, потому что я не знал о sigaction функция — с signal вы можете получить доступ только к вашим локальным массивам в обработчике сигнала, но с sigaction Вы можете предоставить указатели на автоматические и динамические массивы. Тем не менее, совет по использованию как можно меньшего количества обработчиков сигналов здесь применим.

Итог: вы слишком много делаете в своих обработчиках сигналов. Попробуйте сделать как можно меньше. Одним из подходов является присвоение флага (типа volatile sig_atomic_t), и вернуться. Код может позже проверить, был ли флаг активирован (например, в цикле событий)

3

Другие решения

Нет, это не безопасно. С ++ 11 1,9 / 6:

Когда обработка абстрактной машины прерывается получением сигнала, значения объектов, которые
ни те, ни другие

  • типа volatile std::sig_atomic_t ни
  • незапираемые атомные объекты (29.4)

не указываются во время выполнения обработчика сигнала, и значение любого объекта не входит ни в один из этих
две категории, измененные обработчиком, становятся неопределенными.

5

Я считаю, что если вы знаете причина что доступ к вектору небезопасен, тогда вы можете обойти его. Обратите внимание, что доступ еще не гарантировано безопасно. Но он будет работать на всем, что не является Death Station 9000.

Обработчик сигнала прерывает выполнение программы так же, как обработчик прерывания, если вы программируете непосредственно на аппаратном уровне. Операционная система просто перестает выполнять вашу программу, где бы это ни было. Это может быть в середине чего-либо. Например, если к вашему вектору добавляются элементы, и он обновляет значение размера или копирует содержимое в новый, более длинный вектор, который может быть прерван сигналом. И тогда ваш обработчик сигнала попытается прочитать вектор, что приведет к катастрофе.

Вы можете получить доступ к вектору из обработчика сигнала, если он фактически постоянен. Если вы настроили все это при запуске программы и больше никогда не пишете, это безопасно. Обратите внимание, не безопасно использовать в соответствии с нормативными документами, но эффективно безопасно.

Это очень похоже на многопоточность на одноядерном процессоре.

Теперь, если вам нужно обновить вектор во время работы программы, вам нужно «заблокировать» обработчик сигнала от него, замаскировав сигнал или отключив обработчик перед обновлением вектора, чтобы гарантировать, что обработчик не будет работать во время работы. вектор находится в несогласованном состоянии.

1