Page MenuHomePhabricator

More correctly daemonize under unix
Needs RevisionPublic

Authored by eadler on Apr 28 2016, 5:50 AM.
Referenced Files
F11625166: D15812.diff
Tue, Mar 21, 5:17 PM
Unknown Object (File)
Feb 12 2023, 9:12 PM
Unknown Object (File)
Jan 15 2023, 6:32 PM
Unknown Object (File)
Jan 15 2023, 6:32 PM
Unknown Object (File)
Nov 23 2022, 8:51 PM
Unknown Object (File)
Nov 10 2022, 11:12 AM
Unknown Object (File)
Nov 9 2022, 10:28 AM
Unknown Object (File)
Oct 28 2022, 9:15 AM


Group Reviewers
Blessed Reviewers

Missing the setsid step causes child processes to set a SIGHUP when the session is exited.

Daemonization is weird and complicated under unix. To correctly daemonize the following steps should be taken in order

  1. explicitly set umask since the inherited umask is unknown
  2. call fork() and exit in the parent. This forces the child to have a process group ID which is not the same as the process id (thus ensuring we're not the process group leader).
  3. calls setsid() (this is now safe since we're not the process group leader). This forces us to become the PGL of a new session, and ensures we have no controlling terminal.
  4. At this point in highly portable programs it is typical to fork() yet again to prevent the child from being a session leader. This is known as the 'double fork daemonize' method.
  5. change the cwd to / to ensure that if the working directory is removed from underneath it the daemons continue to work. This also allows for the filesystem to unmounted.
  6. close open file descriptors (and possibly reopen 0,1,2).

In C without error checking this looks like

int pid = fork();
if (pid != 0)
int pid = fork();
if (pid != 0)
open("/dev/null", O_RDWR);
Test Plan

ran the daemons

note well: I wrote this all after 1:00am so something is probably wrong.

also note: I suspect the 'TODO' to learn how to unix works is hard

Diff Detail

rPHU libphutil
eax/betterdaemon (branched from master)
Lint Passed
Tests Skipped
Build Status
Buildable 11965
Build 15046: Run Core Tests
Build 15045: arc lint + arc unit

Event Timeline

eadler retitled this revision from to More correctly daemonize under unix.
eadler updated this object.
eadler edited the test plan for this revision. (Show Details)
eadler added a reviewer: epriestley.
eadler edited edge metadata.

I suspect this TODO is hard.

How can I reproduce the actual problem this causes? Something like this?

  • Add a horrible fatal to didReceiveReloadSignal().
  • Launch daemons.
  • Close terminal.
  • Observe daemons die, since they unnecessarily received and processed a SIGHUP which they should not have received?

We also fork in PhabricatorAphlictManagementWorkflow in a similar way and probably want to use similar logic there, although that process doesn't do anything special with SIGHUP.

epriestley edited edge metadata.

(See comment above.)

This revision now requires changes to proceed.Jun 5 2016, 10:16 PM