Start background process/daemon from CGI script

后端 未结 10 1178
北恋
北恋 2020-12-10 02:02

I\'m trying to launch a background process from a CGI scripts. Basically, when a form is submitted the CGI script will indicate to the user that his or her request is being

10条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-10 02:51

    I think there are two issues: setsid is in the wrong place and doing buffered IO operations in one of the transient children:

    if os.fork():
      print "success"
      sys.exit(0)
    
    if os.fork():
      os.setsid()
      sys.exit()
    

    You've got the original process (grandparent, prints "success"), the middle parent, and the grandchild ("lol.txt").

    The os.setsid() call is being performed in the middle parent after the grandchild has been spawned. The middle parent can't influence the grandchild's session after the grandchild has been created. Try this:

    print "success"
    sys.stdout.flush()
    if os.fork():
        sys.exit(0)
    os.setsid()
    if os.fork():
        sys.exit(0)
    

    This creates a new session before spawning the grandchild. Then the middle parent dies, leaving the session without a process group leader, ensuring that any calls to open a terminal will fail, making sure there's never any blocking on terminal input or output, or sending unexpected signals to the child.

    Note that I've also moved the success to the grandparent; there's no guarantee of which child will run first after calling fork(2), and you run the risk that the child would be spawned, and potentially try to write output to standard out or standard error, before the middle parent could have had a chance to write success to the remote client.

    In this case, the streams are closed quickly, but still, mixing standard IO streams among multiple processes is bound to give difficulty: keep it all in one process, if you can.

    Edit I've found a strange behavior I can't explain:

    #!/usr/bin/python
    
    import os
    import sys
    import time
    
    print "Content-type: text/plain\r\n\r\npid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
    sys.stdout.flush()
    
    if os.fork():
        print "\nfirst fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
        sys.exit(0)
    
    os.setsid()
    
    print "\nafter setsid pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
    
    sys.stdout.flush()
    
    if os.fork():
        print "\nsecond fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
        sys.exit(0)
    
    #os.sleep(1) # comment me out, uncomment me, notice following line appear and dissapear
    print "\nafter second fork pid: " + str(os.getpid()) + "\nppid: " + str(os.getppid())
    

    The last line, after second fork pid, only appears when the os.sleep(1) call is commented out. When the call is left in place, the last line never appears in the browser. (But otherwise all the content is printed to the browser.)

提交回复
热议问题