Search code examples
pythonunixforkdaemonpid

How to to get the pid of a daemon created by a double fork?


I've have a simple means to a daemon via a double fork:

    try:
        child = os.fork()
        if child > 0:
            sys.exit(0)
    except OSError:
        print("fork 1 failed")
        sys.exit(1)
    try:
        child = os.fork()
        if child > 0:
            sys.exit(0)
    except OSError:
        print("fork 2 failed")
        sys.exit(1)
    os.execvp(args[0], args) # what the daemon's supposed to be doing

Or alternatively, this is what I had before, but I suspect that it's not correct:

child = os.fork()
if not child:
    secondchild = os.fork()
    if not secondchild:
        os.execvp(args[0], args)
    else:
        os._exit(0)

I'd like to get back the process id of the daemon in the grandparent process that it gets disconnected from. Is this possible while still using os.fork() and os.execvp() (as opposed to threads, subprocesses, etc.)?


Solution

  • Using os.pipe:

    import os
    import sys
    
    try:
        r, w = os.pipe()
        print('grandparent {}'.format(os.getpid()))
        child = os.fork()
        if child > 0:
            grandchild_pid = int(os.fdopen(r).readline().strip())
            print('grand child pid: {}'.format(grandchild_pid))
            sys.exit(0)
    except OSError:
        print("fork 1 failed")
        sys.exit(1)
    try:
        print('parent {}'.format(os.getpid()))
        child = os.fork()
        if child > 0:
            # Pass child (grandchild)'s pid to parent.
            os.write(w, '{}\n'.format(child)) 
            sys.exit(0)
    except OSError:
        print("fork 2 failed")
        sys.exit(1)
    
    print('child {}'.format(os.getpid()))
    

    UPDATE

    Replace following line:

    os.write(w, '{}\n'.format(child))
    

    with:

    os.write(w, '{}\n'.format(child).encode())
    

    to make it work in Python 3.x.