У меня есть код, который fork()
s вызывает setsid()
в дочернем элементе и запускает некоторую обработку. Если любой из дочерних процессов завершает работу (waitpid(-1, 0)
), я убиваю все группы дочерних процессов:
child_pids = []
for child_func in child_functions:
pid = fork()
if pid == 0:
setsid()
child_func()
exit()
else:
child_pids.append(pid)
waitpid(-1, 0)
for child_pid in child_pids:
try:
killpg(child_pid, SIGTERM)
except OSError as e:
if e.errno != 3: # 3 == no such process
print "Error killing %s: %s" %(child_pid, e)
Однако иногда вызов killpg
завершается ошибкой с сообщением «операция не разрешена»:
Error killing 22841: [Errno 1] Operation not permitted
Почему это могло происходить?
Полный рабочий пример:
from signal import SIGTERM from sys import exit from time import sleep from os import * def slow(): fork() sleep(10) def fast(): sleep(1) child_pids = [] for child_func in [fast, slow, slow, fast]: pid = fork() if pid == 0: setsid() child_func() exit(0) else: child_pids.append(pid) waitpid(-1, 0) for child_pid in child_pids: try: killpg(child_pid, SIGTERM) except OSError as e: print "Error killing %s: %s" %(child_pid, e)
Который дает:
$ python killpg.py Error killing 23293: [Errno 3] No such process Error killing 23296: [Errno 1] Operation not permitted
killpg
. Кроме того, можете ли выkill
дети, даже если вы не можетеkillpg
их? (Я понимаю, что это не решение, это просто помогает диагностировать.) - person abarnert   schedule 21.09.2012waitpid
делает это крайне маловероятным): нет ничего, что заставляло быsetsid
выполняться до того, как вы вызоветеkillpg
. Обычный способ избежать этого состояния гонки, установив группу процессов как в дочернем, так и в родительском, предотвратитsetsid
, поэтому вам, вероятно, придется использовать явную синхронизацию. - person jilles   schedule 21.09.2012