#2467 closed enhancement (wontfix)

In daemon mode nginx completes detaching before the service is ready

Reported by: cryptonector@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version:
Keywords: Cc:
uname -a: all platforms and operating systems
nginx -V: all versions

Description

This affects all versions, and is a very common problem in daemons of all kinds.

This makes tests that start nginx racy, and the workaround is to loop over polling a health end-point, sleeping between polling. The workaround makes tests slower. Similar considerations can affect actual production services.

The bug is here: https://github.com/nginx/nginx/blob/a64190933e06758d50eea926e6a55974645096fd/src/os/unix/ngx_daemon.c#L26 where ngx_daemon() calls exit(0) immediately on the parent-side of fork(). Instead the parent should block waiting for the child to indicate that it has opened all the sockets it will listen on and called listen() on all of them.

Examples of how to implement this (prefix https to all of these -- I can't as otherwise my ticket gets rejected as spam!):

  • github.com/heimdal/heimdal/blob/master/lib/roken/detach.c
  • github.com/stefanberger/swtpm/blob/master/src/swtpm/daemonize.c
  • src.illumos.org/source/search?full=&defs=daemonize*&refs=&path=&hist=&type=&xrd=&nn=1&si=defs&searchall=true&si=defs
  • github.com/openvswitch/ovs/blob/master/lib/daemon-unix.c#L441
  • fossies.org/linux/darkstat/conv.c#L225
  • github.com/emikulic/darkhttpd/blob/master/darkhttpd.c#L2688

There are many many more to be found.

Change History (2)

comment:1 by cryptonector@…, 22 months ago

Notice that the daemonization code in Heimdal is in a library that supports Windows and POSIX, and has a friendly license.

This pattern is very common nowadays, and on some systems it is absolutely necessary. For example, in SMF (Solaris, Illumos) the service should daemonize in this way so that dependent services don't start until after the dependency is ready rather than merely starting.

comment:2 by Maxim Dounin, 22 months ago

Resolution: wontfix
Status: newclosed
Type: defectenhancement

This was discussed excessively in this thread (in Russian):

https://mailman.nginx.org/pipermail/nginx-ru/2017-November/060604.html

In particular, this message might be interesting, it contains some summary and a proof-of-concept patch:

https://mailman.nginx.org/pipermail/nginx-ru/2017-November/060628.html

In general, this is how most daemons are written in Unix for a long time, including how the daemon(3) library function is expected to be used. While trying to implement synchronization and only exit from the parent process when the daemon is fully up and running might be beneficial, this is not what can be expected from normal daemons.

For nginx, the only difference is the PID file, which might not be already created when the parent process exits. It is, however, not expected to be used right after the nginx start in practical cases.

Considering the above, implementing synchronization during demonization is believed to be an overkill, and the patch referenced above is therefore not committed.

If the particular use case requires using nginx PID file immediately after nginx startup, waiting for it to appear is believed to be trivial. The same approach can and should be used for all daemons unless they are specifically known to create PID files before exiting.

Note: See TracTickets for help on using tickets.