Я думаю, что есть две проблемы: setsid
находится не в том месте и выполняет буферизованные операции ввода-вывода в одном из переходных дочерних элементов:
if os.fork():
print "success"
sys.exit(0)
if os.fork():
os.setsid()
sys.exit()
У вас есть исходный процесс (дедушка, печатает «успех»), средний родитель и внук («lol.txt»).
Вызов os.setsid()
выполняется в среднем родителе после появления внука . Средний родитель не может влиять на сессию внука после его создания. Попробуйте это:
print "success"
sys.stdout.flush()
if os.fork():
sys.exit(0)
os.setsid()
if os.fork():
sys.exit(0)
Это создает новую сессию до появления внука. Затем средний родитель умирает, оставляя сеанс без лидера группы процессов, гарантируя, что любые вызовы, чтобы открыть терминал, будут неудачными, гарантируя, что никогда не будет никаких блокировок на входе или выходе терминала, или посылая неожиданные сигналы дочернему элементу.
Обратите внимание, что я также переместил success
к прародителю; нет никакой гарантии, что , какой дочерний элемент будет запускаться первым после вызова fork(2)
, и вы рискуете, что дочерний элемент будет порожден, и потенциально пытаетесь записать вывод в стандартную ошибку out или standard, до того, как средний родитель мог бы иметь возможность написать success
на удаленном клиенте.
В этом случае потоки закрываются быстро, но, тем не менее, смешивание стандартных потоков ввода-вывода между несколькими процессами неизбежно создает трудности: по возможности, держите все это в одном процессе.
Редактировать Я обнаружил странное поведение, которое не могу объяснить:
#!/usr/bin/python
import os
import sys
import time
print "Content-type: text/plain\r\n\r\npid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
sys.stdout.flush()
if os.fork():
print "\nfirst fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
sys.exit(0)
os.setsid()
print "\nafter setsid pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
sys.stdout.flush()
if os.fork():
print "\nsecond fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
sys.exit(0)
#os.sleep(1) # comment me out, uncomment me, notice following line appear and dissapear
print "\nafter second fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
Последняя строка, after second fork pid
, появляется только когда комментарий os.sleep(1)
закомментирован. Когда вызов остается на месте, последняя строка никогда не появляется в браузере. (Но в остальном весь контент печатается в браузере.)