So Daemonize uses sys.exit in the parent process after the fork. The intention is likely that this will cause the parent process to immediately end.
However, this is not actually the case:
The parent python process raises SystemExit instead, which returns control flow outside of the Daemonize call if an exception handler for SystemExit is present. This means that code can continue to execute in the parent process after the Fork. Strange, but something a programmer can avoid with careful coding.
However, if the parent process has passed file descriptors of sockets/pipes/etc. to keep_fds that it intends for the client to use, when the parent process exits, the parent process will garbage collect many of these client objects and these garbage collection routines will then attempt to do clean-ups. These clean-ups may involve sending shutdown notices over the sockets/pipes. This corrupts the child process. We noticed this when we changed a client library to properly implement garbage collection.
I suggest that, instead of callingsys.exit(0), that Daemonize reset the signal handlers to the system default handlers (away from the python default handlers that raise exceptions) and then call os.kill on itself with SIGTERM (or SIGKILL). This would prevent Python garbage collection routines in the parent from having the ability to interfere with the child process.
So Daemonize uses
sys.exit
in the parent process after the fork. The intention is likely that this will cause the parent process to immediately end.However, this is not actually the case:
keep_fds
that it intends for the client to use, when the parent process exits, the parent process will garbage collect many of these client objects and these garbage collection routines will then attempt to do clean-ups. These clean-ups may involve sending shutdown notices over the sockets/pipes. This corrupts the child process. We noticed this when we changed a client library to properly implement garbage collection.I suggest that, instead of calling
sys.exit(0)
, that Daemonize reset the signal handlers to the system default handlers (away from the python default handlers that raise exceptions) and then callos.kill
on itself with SIGTERM (or SIGKILL). This would prevent Python garbage collection routines in the parent from having the ability to interfere with the child process.