[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#727708: systemd and upstart, a view from a daemon upstream



Firstly: a warning note.  Throughout this exercise I have been
persistently typing "upstart" when I mean "userv" and "userv" when I
mean "upstart".  If something I say make no sense, please try reading
it the other way :-).  (At least it gave me some extra bugs to
experience debugging...)

I have spent a while with the systemd and upstart reference manuals,
and written and tested integration for both systems for userv.
I didn't tackle OpenRC because AFAICT it has no reference manual.

Both systems seemed to have the key facilities I would have expected,
and I think (with minor enhancements) should be able to replace
sysvinit at least on Linux, and allow us to do away with unsupervised
(double-)forking daemons.

It's clear that systemd is a lot more sophisticated - or, to put it
another way, a lot more complex.  It took longer with systemd to see
the wood for the trees.

We have already discussed here the merits of systemd's daemon
readiness protocol.  I won't go into that again.  As I say, I
concluded that I wasn't willing to take any of the three plausible
routes to providing that in userv.

Conveniently, though, userv could be set up to use socket activation.
So this allowed me to experiment with that.  I did the upstart
integration with raise(SIGSTOP) and the systemd integration with
socket activation.

In both cases I invented a new command line option to specify the
startup protocol.  userv already had an option to request non-daemonic
startup, so this was a good fit.


In terms of the amount of code in uservd itself:

 * The upstart SIGSTOP readiness protocol was utterly trivial: exactly
   the one line raise(SIGSTOP), plus the command-line option handling.

   This was trivial to debug in an ad-hoc fashion, on my netbook which
   is running squeeze and sysvinit.

 * I had to write about 50 lines of environment-laundering code.  This
   is particularly because systemd's choice of environment variables
   for socket activation have very generic names: LISTEN_FDS and
   LISTEN_PID.

   systemd's theory AFAICT is that LISTEN_PID will prevent any process
   other than the intended one from honouring the LISTEN_* variables.
   That's of course not true of any other program which might already
   be using these variable names for a different purpose.

   I chose to also launder UPSTART_*, which is what made the
   environment laundering process more complicated.  If I had only
   wanted to unsetenv the two systemd variables it would have been
   much shorter, and arguably that would have been sufficient.

 * socket activation according to the systemd protocol was very short;
   the actual code to extract the socket fd was a mere 6 loc (I ignore
   LISTEN_PID, in violation of the nominal systemd protcol).
   Laundering the environment could be cut down to around 4 loc.  Plus
   command-line option handling, of course.

   I didn't attempt to debug this on my local workstation.  Doing so
   would probably have involved pratting about with socat plus a
   wrapper script to massage the environment etc.

   I didn't implement socket activation according to the upstart
   protocol but I expect it would be nearly as easy.  UPSTART_FDS is a
   bit more tricky because one has to tokenise it but userv only ever
   has one socket so actually that would be a trivial sanity check.

So overall my conclusions at this level are:

 * socket activation is an attractive implementation target for an
   upstream daemon author.

 * upstart's SIGSTOP protocol is an attractive implementation target
   for an upstream daemon author.

 * systemd's readiness protocol is an unattractive implementation
   target for an upstream daemon author.  I think this is an important
   weakness, if it remains unaddressed.


Reply to: