#python #linux #libc
#python #linux #libc
Вопрос:
Я хочу изящно освободить некоторый дорогостоящий системный ресурс в своем коде с помощью обработчика событий. Проблема в том, что обработчик событий зарегистрирован в разветвленном подпроцессе (да, я должен поместить обработчик событий туда в подпроцесс, поскольку ресурс выделяется после fork), и я хочу, чтобы подпроцессы завершались, когда родительский процесс умирает. Однако код работает не так, как я ожидал.
Вот доступный для выполнения пример:
import time
import os
import signal
PRCTL=None
# get prctl from libc
def getPRCTL():
global PRCTL
if PRCTL is None:
import ctypes
PRCTL = ctypes.CDLL("libc.so.6")["prctl"]
return PRCTL
def dieWithParent():
prctl = getPRCTL()
prctl(1, signal.SIGTERM) # 1 = PR_SET_PDEATHSIG
def foo():
print "In foo."
def handler(signo, frame):
print "Handler is activated."
signal.signal(signal.SIGTERM, handler)
time.sleep(10) # in case sub-process terminates first.
if __name__ == '__main__':
dieWithParent()
pid = os.fork()
if 0 == pid:
foo()
else:
print "Subprocess spawned."
print "dying..."
Код выполняет следующее:
- прикажите ОС превратить родительский сигнал матрицы в SIGTERM;
- разветвляйте подпроцесс;
- если дочерний процесс, зарегистрируйте обработчик сигналов и дождитесь завершения родительского процесса.
На моей платформе вывод
$ python main.py
In foo.
Subprocess spawned.
dying...
Кажется, обработчик не активирован.
Что-то не так с моим кодом или пониманием?
Конфигурация на моем поле
2.6.18-238.el5 x86_64 Python 2.6
Любые подсказки будут высоко оценены, спасибо!
Ответ №1:
из prctl
PR_SET_PDEATHSIG (начиная с Linux 2.1.57) Устанавливает для сигнала смерти родительского процесса вызывающего процесса значение arg2 (либо значение сигнала в диапазоне 1..maxsig, либо 0 для очистки). Это сигнал, который вызывающий процесс получит, когда его родитель умрет. Это значение очищается для дочернего элемента fork(2) и (начиная с Linux 2.4.36 / 2.6.23) при выполнении двоичного файла set-user-ID или set-group-ID.
таким образом, вы, по сути, гарантируете, что ваш родитель умирает вместе со своим родителем, но ничего не говорите о своем дочернем процессе.
если вы добавите:
dieWithParent()
после того, как вы разветвляете, он ведет себя правильно
Ответ №2:
Если это попытка написать демон, вам следует посмотреть двойное разветвление.
Например: http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix /