#45 Failed to daemonize due to multiprocessing closing stdin by default
Closed: Insufficient data by bignose. Opened by farleylai.

The use case is to daemonize AFTER the parent process creates child processes using 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:

    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 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.

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)

Metadata