The use case is to daemonize AFTER the parent process creates child processes using multiprocessing.Process(..., daemon=False).
multiprocessing.Process(..., daemon=False)
import os import sys import multiprocessing as mp from daemon import daemon def f(rank, name): print(f"[{rank}:{os.getpid()}] f(): stdin, __stdin__ = ({sys.stdin.closed}, {sys.__stdin__.closed})") # FIXME: workaround # if sys.stdin and sys.__stdin__ and sys.__stdin__.closed: # sys.__stdin__ = sys.stdin with daemon.DaemonContext(umask=0o022, chroot_directory=None, working_directory=os.getcwd(), stdout=sys.stdout, stderr=sys.stderr, ) as ctx: print(f"[{rank}:{os.getpid()}] f(): stdin, __stdin__ = ({sys.stdin.closed}, {sys.__stdin__.closed})") if __name__ == '__main__': p = mp.Process(target=f, args=(0, 'f'), daemon=False) p.start() p.join()
The script fails with the following error:
[0:16906] f(): stdin, __stdin__ = (False, True) Process Process-1: Traceback (most recent call last): File "/home/ml/farleylai/miniconda3/envs/sinet37/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap self.run() File "/home/ml/farleylai/miniconda3/envs/sinet37/lib/python3.7/multiprocessing/process.py", line 99, in run self._target(*self._args, **self._kwargs) File "test.py", line 35, in f stderr=sys.stderr, File "/home/ml/farleylai/miniconda3/envs/sinet37/lib/python3.7/site-packages/daemon/daemon.py", line 273, in __init__ detach_process = is_detach_process_context_required() File "/home/ml/farleylai/miniconda3/envs/sinet37/lib/python3.7/site-packages/daemon/daemon.py", line 821, in is_detach_process_context_required if is_process_started_by_init() or is_process_started_by_superserver(): File "/home/ml/farleylai/miniconda3/envs/sinet37/lib/python3.7/site-packages/daemon/daemon.py", line 797, in is_process_started_by_superserver stdin_fd = sys.__stdin__.fileno() ValueError: I/O operation on closed file
This is because multiprocessing.Process() by default closes stdin and replaces with /dev/null but __stdin__ remains closed (according to cpython). However, python-daemon checks __stdin__ in is_process_started_by_superserver instead of stdin with sys.__stdin__.fileno() preventing daemonization. One workaround is to restore __stdin__ with stdin if it is the case but not sure if it is the way to go:
multiprocessing.Process()
stdin
/dev/null
__stdin__
python-daemon
is_process_started_by_superserver
sys.__stdin__.fileno()
if sys.stdin and sys.__stdin__ and sys.__stdin__.closed: sys.__stdin__ = sys.stdin with daemon.DaemonContext(...):100: ....
Thank you for the report.
This is because multiprocessing.Process() by default closes stdin and replaces with /dev/null
If I understand correctly, that places the described use case in conflict with the fundamental purpose of python-daemon. If the controlling terminal is already closed, it's too late to attempt Unix-style daemonisation.
Metadata Update from @bignose: - Issue tagged with: more-info
If the use case can be better described, please open a new issue saying how it's intended to work with python-daemon.
In the absence of further information, I'm closing this report. Thanks!
Metadata Update from @bignose: - Issue close_status updated to: Insufficient data - Issue status updated to: Closed (was: Open)