File descriptors redirecting is stuck

python, sys

Solution

You are mixing Python file handles with the operating system file descriptors, this is asking for trouble.

While you are correct on using `os.dup2()` to redirect `sys.stdout` (because direct assignment may not completely work, if other modules acquired a reference to it), you should open files at the operating system level with `os.open()`.

Here's the daemonization code we use at my workplace:

if os.fork() > 0:
    os._exit(0)
os.setsid()
sys.stdin.flush()
sys.stdout.flush()
sys.stderr.flush()
null = os.open(os.devnull, os.O_RDWR)
os.dup2(null, sys.stdin.fileno())
os.dup2(null, sys.stdout.fileno())
os.dup2(null, sys.stderr.fileno())
os.close(null)

If you want to redirect stdout to some file, just use a different file name instead of the predefined constant `os.devnull`.

Problem

In the daemon class example, which I implement, is used descriptors redirecting. ``` sys.stdout.flush() sys.stderr.flush() si = file(self.stdin, 'r') so = file(self.stdout, 'a+') se = file(self.stderr, 'a+', 0) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) # This line doesn't work os.dup2(se.fileno(), sys.stderr.fileno()) ``` `os.dup2(so.fileno(), sys.stdout.fileno())` is not working. It doesn't raise errors. The code after this line is not executed. I simplified this example to the class contains only the problem area: ``` class Deamon(object): def __init__(self, pidfile, stdout='/dev/null'): self.pidfile = pidfile self.stdout = stdout def get_stdout(self): so = file(self.stdout, 'a+') os.dup2(so.fileno(), sys.stdout.fileno()) print 'executed' ``` After `os.dup2(so.fileno(), sys.stdout.fileno())` code just stuck. Why is it happening? Edit (with @C2H5OH code implementation): ``` try: pid = os.fork() if pid > 0: # exit first parent sys.exit(0) except OSError, e: sys.stderr.write( 'fork #1 failed: %d (%s)\n' % (e.errno, e.stderror) ) sys.exit(1) os.chdir("/") os.setsid() os.umask(0) try: pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) except OSError, e: sys.stderr.write( "fork #2 failled: %d (%s)" % (e.errno, e.strrerror) ) sys.exit(1) # redirect standart file descriptors os.setsid() sys.stdin.flush() sys.stdout.flush() sys.stderr.flush() dev_null = os.open(os.devnull, os.O_RDWR) os.dup2(dev_null, sys.stdin.fileno()) print 'executed 1' os.dup2(dev_null, sys.stdout.fileno()) print 'executed 2' os.dup2(dev_null, sys.stderr.fileno()) os.close(dev_null) # write pidfile # FIXME: file is not writes! atexit.register(self.delpid) pid = str(os.getpid()) file(self.pidfile, 'w+').write("%s\n" % pid) ``` In the `stop` method I have try-out of `self.pidfile` existing: ``` def stop(self): print file(self.pidfile, 'r') ``` This is raise an error: IOError: [Errno 2] No such file or directory: '/tmp/deamon-example.pid' The problem is still in there.

Original source