s6
Software
skarnet.org
The s6-background-watch program
s6-background-watch spawns an auto-backgrounding daemon that writes a pidfile.
It reads the pidfile then transmits the signals it receives to the corresponding
process. It dies when the corresponding process dies, with an
approximation of
its exit code.
s6-background-watch is meant as a workaround to auto-backgrounding
daemons. (Not a solution, because the solution is to fix
the daemon so it runs without backgrounding itself!) It should be run on the
command line of a run script, right before the invocation of the auto-backgrounding
daemon.
s6-background-watch only works on Linux (or any systems implementing
prctl with PR_SET_CHILD_SUBREAPER)
and the BSDs (or any system implementing
procctl with PROC_REAP_ACQUIRE or
kevent
with EVFILT_PROC and NOTE_EXIT fflag). Most modern systems will implement one of these.
Interface
s6-background-watch [ -t timeout ] [ -d notif ] pidfile prog...
- s6-background-watch spawns prog... as a child.
- prog... is expected to fork. The child process is supposed to be
long-lived, i.e. the child the daemon that is to be supervised.
- The parent is expected to write the child's pid to the pidfile file.
- The parent is expected to exit 0 when the child is ready.
- Once the parent has exited, s6-background-watch reads pidfile to get
the pid of the daemon.
- s6-background-watch transmits all the signals it receives to the daemon.
Non-catchable signals, such as SIGKILL, will obviously not work, so, don't do this.
- s6-background-watch exits when the daemon exits, with an
approximation of the
daemon's exit code. (In most cases it will be the exact same exit code.)
Options
- -t timeout, --timeout-ready=timeout
- If the parent daemon has not exited after timeout milliseconds,
kill it and exit. By default, there is no timeout, s6-background-watch will wait as
long as needed.
- -d notif, --notification-fd=notif
- Write a newline to file descriptor notif when the parent has
exited 0 and s6-background-watch has successfully read pidfile. This
is useful when the daemon follows the convention that the child is ready when
the parent exits: use the -d option in conjunction with the
notification-fd file, and s6-supervise
will accurately report the daemon's readiness.
Exit codes
- 100
- Bad usage.
- 111
- System call failed. This is generally a temporary error,
or indicates a problem with the underlying system.
- 112
- Functionality not supported. You cannot run
s6-background-watch on this OS, because it lacks the necessary features.
- 128+n
- The parent daemon was killed with signal n.
In particular, 137 can happen if the -t option has been given and
the parent daemon times out: s6-background-watch kills it with SIGKILL.
- n
- The child daemon exited with code n.
Notes
s6-background-watch acts as a proxy between s6-supervise
and the forking daemon. It stays in the foreground, keeping s6-supervise happy; and it
keeps track of the daemon as best as it can, transmitting it signals. It is a better
iteration of s6-fghack, which is obsolescent. However, it
is not perfect, because it cannot be:
- s6-svc -k, i.e. SIGKILL, is very bad.
It will kill s6-background-watch without killing the backgrounded daemon, and
all links to the daemon are lost. If the service restarts, it will probably fail,
because the previous instance of the daemon is still alive. You may be able to
mitigate that with the use of a lock-fd file.
- The race condition inherent to pidfiles is there: between the moment
the daemon writes its pidfile and the moment s6-background-watch reads it and
attempts to track it, the daemon could have died and another pid taken its place.
The design of s6-background-watch makes this race window minimal (the system has
to loop over the whole pid space between the moment the pidfile is written and
the moment s6-background-watch reads it, which is right afterwards, so
it's not as bad as most uses of pidfiles, but the race theoretically still exists.
- In order to detect the death of a process that isn't a direct child,
which isn't a functionality guaranteed by POSIX, OS-specific mechanisms have to
be used, and not all the supported OSes have such mechanisms. If the OS has no usable
mechanism for this, s6-background-watch will immediately exit with an error message.