:: Re: [Dng] Why daemontools is so coo…
Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Steve Litt
Ημερομηνία:  
Προς: dng
Αντικείμενο: Re: [Dng] Why daemontools is so cool
On Sun, 29 Mar 2015 11:15:49 +0200
marc <marcxdv@???> wrote:

> > No need to mix doubleforking and PID tracking on your
> > program. That should be the duty of whatever daemonizes and manages
> > your program. You know, like Daemontools or s6.
>
> So there is a very good reason for a deamon to handle its
> own backgrounding: The sensible convention is it that it
> should only background at the instant where it is ready to
> service requests: If there is a long initialisation phase
> it should stay in the foreground - so that things that
> depend on it in turn do not get started too soon. A more
> detailed description of this problem I wrote up a while ago
> at welz.org.za/notes/on-starting-daemons.html.
>
> More fundamentally: If an application has problems calling the
> a daemonize() or fork_parent() function or the handful of system
> calls that make up this, then maybe this a limitation of the
> development environment or language - if calling these this is
> regarded to be hard then one wonders how reliable the rest of the
> program is.
>
> regards
>
> marc


This is one of the many reasons I enjoy being on the Dng list. While
the Debian-User guys wring their hands over how to use NetworkManager,
we're discussing stuff like this.

First, congrats on writing the excellent resource
http://welz.org.za/notes/on-starting-daemons.html . Nice! I never
thought about half that stuff before reading your resource.

As best I can interpret the trystart() and doit() functions in
daemontools' supervise.c, daemontools' supervise executable forks, the
parent records the PID of the child, and the child does an execve() on
the directory's ./run script. There's no *double*fork because
daemontools specifically does *not* want to separate the service
(daemon, whatever you want to call it) from its parent supervise
command. It wants supervise to have control of the daemon at all times.

Your resource clarifies the fact that there are many distinct reasons
for having the daemon "in the background", including:

1) Out of sight, out of mind
2) User can't easily accidentally kill it
3) No resources wasted by terminals and the like
4) Backgrounding can serve as a signal that your daemon is ready to
service requests
5) Stay foreground long enough to show error messages

All 5 are, of course, exactly right. 1-3 really just define
"backgrounding" as "no interactive terminal". #5 would show
initialization messages on the terminal presumably during boot, and
that's a good thing. #4 opens up a big old can of worms when it
comes to dependencies ...

Let's say my home-grown magic_sync daemon requires my home-grown
sync_exchanged daemon to be completely functional, and sync_exchanged
has extensive setup before it's ready to exchange. magic_sync shouldn't
be run until sync_exchanged is not only running, but ready to service
requests. So what you're saying is for sync_exchanged to background
itself when ready to handle requests, with suitable plumbing so that
sync_exchanged's init and service PIDs are identical.

My point is that being background is not the only possible sentinel for
"ready to service requests". sync_exchanged could write a sentinel file
to indicate that. Or it could have a tiny additional executable that
does nothing but query the daemon for readiness to service. Or it could
offer a task doable only when ready to service. An example of the
latter is that all my network-requiring daemons try pinging 8.8.8.8
before becoming daemons. Being background is one sentinel, but there
are many others.

Now let's look at how daemontools handles all of this...

Daemontools manages a foreground program, because that's the way you
can absolutely, positively, nonambiguously track the PID, without
artifacts like PID files that can go stale or get erased, and without
all sorts of guesswork from parsing ps ax or /proc. Whatever
daemontools does, no individual terminal is required, and the service
is out of sight, out of mind unless you specifically look at the log
file, and the user can't easily accidentally kill it.

Daemontools reveals all error messages via its logging mechanism,
assuming you write the ./run and log/run scripts right, and doing so is
trivial.

That leaves the sentinel function. I think you and I agree that a
daemon's "ready to service requests" sentinel must be written by the
daemon's programmer, whether it be backgrounding, or a sentinel file,
or a test. And it must be documented.

But of course, we know that few programmers deliberately program in a
sentinel, and almost none document it. Most of the time, either the
distro or the computer's user/admin must question those sentinels
himself. In the case of daemontools, it's usually as simple as making a
no-block test that succeeds if the dependency is servicing requests.
For instance, to test a network and make sure it blocks for only 1
second, you could use:

ping -c1 -W1 8.8.8.8

If a daemon depends on a functional nfs, you could try a mount of
something harmless that you know for sure exists.

As you mention in your resource, these are much better than the usual
"is it running". You suggest waiting til ready to background,
daemontools works best by performing tests like I talk about in this
email, but they both get the job done.

In the context of your resource, what I like about daemontools is that,
assuming the daemon is capable of running in the foreground, and for
debugging purposes it sure should be, daemontools can manage and keep
out of sight, out of mind *any* computer program, even if the original
author didn't bother to put in any kind of sentinel.

And by the way, daemontools includes a program called fghack, which
sometimes can place a no-forground-possible executable like apache2,
nginx or nfsd, into the foreground, although its PID tracking isn't
nearly as good under that circumstance.

SteveT

Steve Litt                *  http://www.troubleshooters.com/
Troubleshooting Training  *  Human Performance