Предоставляются ли гарантированные сигналы POSIX в частично инициализированную нить?
В большинстве реализаций потоков POSIX требуется некоторая инициализация во вновь создаваемом потоке, прежде чем он находится в состоянии согласованности, способном запускать код приложения. Это может включать блокировку блокировки в структуре потока, инициализацию "регистра потока" в реализациях, которые используют один, инициализацию локальных данных потока (либо TLS на уровне компилятора, либо данные, зависящие от потока POSIX) и т.д. Я не могу найти четкое убедитесь, что вся эта инициализация будет закончена, прежде чем поток сможет получать любые сигналы; ближайший я могу найти в 2.4.3:
В следующей таблице определяется набор функций, которые должны быть безопасны для асинхронных сигналов. Таким образом, приложения могут без ограничений запрещать их функции:
...
Предположительно, некоторые из этих функций (по крайней мере fork
, которые должны проверять глобальное состояние, установленное функцией pthread_atfork
), зависят от того, что поток находится в согласованном, инициализированном состоянии.
Меня беспокоит то, что я читал большую часть источника glibc/nptl и не могу найти явной синхронизации, чтобы предотвратить обработку сигнала вновь созданным потоком до его полной инициализации. Я бы ожидал, что поток, вызывающий pthread_create
, блокирует все сигналы перед вызовом clone
, а для нового потока их разблокировать после завершения инициализации, но я не могу найти какой-либо код для этого эффекта и не вижу его в strace
.
Ответы
Ответ 1
(Я не думаю, что это реальный ответ, но он большой для комментария)
Это очень интересный вопрос. Я просмотрел код glibc для pthread_create
, чтобы увидеть, как он себя ведет, и если я не полностью упустил что-то, похоже, не существует какого-либо особого поведения, чтобы остановить это (например, блокировать все сигналы до clone
и разблокировать их в дочернем элементе после некоторой настройки {после записи времени создания потока и С++ улавливается все обработчик исключений, что происходит даже в коде C}).
Я ожидал найти комментарий, в котором упоминалась бы возможность этой ситуации и, возможно, даже упоминание того, что POSIX сказал (или упоминание о том, что он не сказал, что делать).
Возможно, вы всегда должны переносить pthread_create
в код для блокировки и восстановления сигналов и запускать все функции потока с помощью разблокированного вызова.
Это может быть очень большой сайт в pthreads (или glibc или мое понимание кода).
Ответ 2
спецификация POSIX pthread_create
предоставляет это мне в виду:
Состояние сигнала нового потока должно быть инициализировано следующим образом:
- Маска сигнала наследуется от создающего потока.
- Набор ожидающих нового потока должен быть пустым.
Но у меня недостаточно опыта, чтобы сказать, что все это происходит в различных реализациях.
Ответ 3
pthread_create - это блокирующий вызов. Существует нет (нового) потока для отправки сигнала перед вызовом, и есть поток для отправки сигнала после вызова, таким образом, идентификатор потока возвращается вызовом.
Поэтому я бы пришел к выводу, что поток должен быть действительным и инициализирован в это время...