Search code examples
pythonforkdaemon

Python: Closing file descriptors when daemonizing a process


I have this code in my application:

def daemonize_process(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
'''
Fork the current process as a daemon (background process), redirecting
standard file descriptors

@param string stdin standard input file name
@param string stdout standard output file name
@param string stderr standard error file name
'''

# To transform a process in a daemon, it is necessary to fork, decouple from
# parent environment, fork again and close all opened file descriptors.

# do first fork
try:
    pid = os.fork()
    if pid > 0:
        # exit from first parent process
        # using os._exit() instead of sys.exit() in a child process after
        # a fork is recommended by Python API docs
        os._exit(0)
except OSError as e:
    sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
    sys.exit(1)

# decouple from parent environment
os.chdir("/")
os.umask(0)
os.setsid()

# do second fork
try:
    pid = os.fork()
    if pid > 0:
        # exit from second parent process
        # using os._exit() instead of sys.exit() in a child process after
        # a fork is recommended by Python API docs
        os._exit(0)
except OSError, e:
    sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
    sys.exit(1)

# close all file descriptors
import resource
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
    maxfd = 1024

for fd in range(0, maxfd):
    try:
        os.close(fd)
    except OSError:
        sys.stderr.write("error closing file: (%d) %s\n" % (e.errno, e.strerror))
        pass

# process is now daemonized, redirect standard file descriptors.
for f in sys.stdout, sys.stderr:
    f.flush( )
si = file(stdin, 'r')
so = file(stdout, 'a+')
se = file(stderr, 'a+', 0)
os.dup2(si.fileno( ), sys.stdin.fileno( ))
os.dup2(so.fileno( ), sys.stdout.fileno( ))
os.dup2(se.fileno( ), sys.stderr.fileno( ))

In daemonization code I have seen in the web, the file descriptors are not closed in the child process. Why should I do this? It seems to me I may want to keep working in the files I already was working before the fork-detach-fork process.

Thanks in advance.


Solution

  • Why close the file descriptors? Usually you can assume that the process launching your daemon knows what it's doing and will close its file descriptors before the exec().

    For example if you run from bash, the only open file descriptors you will get, are the standard ones, plus any redirection manually set in the shell.

    If a program leaves file descriptors open around, it's buggy. Anyway it is possible to open files using FD_CLOEXEC, so that they will automatically be closed on exec().