Согласно документации Python, вызов signal.signal может быть вызван только из основного потока, а обработчики сигналов будут выполняться в основном потоке. насколько я понимаю, если обработчик сигнала не сделает что-то действительно простое, что может быть защищено GIL Python, это означает, что я действительно ничего не могу сделать в основном потоке. Точнее, любой объект синхронизации, используемый в основном потоке, не может быть использован из обработчика сигнала, поскольку это будет означать, что при вызове обработчика сигнала мьютекс может быть уже заблокирован, а его повторная блокировка приведет к взаимоблокировке, и даже если мьютекс является повторно входящим, это приведет к несогласованности. Итак, мой подход следующий:
Код: Выделить всё
signal.signal(signal.SIGCHLD, handle_sigchld)
t = threading.Thread(target=run_main_loop)
t.start()
try:
t.join()
except KeyboardInterrupt:
stop_main_loop()
t.join()
В программе есть и другие потоки, а подпроцессы запускаются из потока основного цикла. Я ожидаю, что всякий раз, когда подпроцесс завершается, в основном потоке вызывается обработчик сигнала, который будет использовать некоторый метод синхронизации для уведомления потока основного цикла. Это работает на Mac, но в Linux обработчик сигнала вызывается только при выходе из потока. Я попытался отладить проблему с помощью strace, и SIGCHLD поступает правильно после завершения подпроцесса, но это происходит в потоке, в котором был запущен процесс, что может быть причиной того, что обработчик сигнала не вызывается в основном потоке.
В качестве обходного пути я запускаю подпроцесс следующим образом:
Код: Выделить всё
def start_subprocess():
subprocess.Popen(...)
# from the main loop's thread
t = threading.Thread(target=start_subprocess)
t.start()
t.join()
Теперь, проверяя strace, обработчик сигнала вызывается в основном потоке, предположительно потому, что потока, запустившего процесс, больше не существует.
Главный вопрос: что здесь происходит? Это ошибка в реализации Python или просто документация неясна? Есть ли более элегантный способ решения этой проблемы?
Побочный вопрос заключается в том, верно ли мое первоначальное предположение о том, что я не могу использовать одни и те же методы синхронизации потоков из обработчика сигнала и основного потока? Если нет, то почему?
Подробнее здесь:
https://stackoverflow.com/questions/798 ... plications