[systemd-devel] Need advice on daemon's architecture
Lennart Poettering
lennart at poettering.net
Mon Nov 4 06:42:00 PST 2013
On Sun, 03.11.13 13:42, Hoyer, Marko (ADITG/SW2) (mhoyer at de.adit-jv.com) wrote:
> > If you are using systemd intensively, then you may want to use Type=notify.
> >
> > With type=dbus, systemd will consider things ready when you take the name on
> > the bus, but this might not actually be the last thing you do to initialise
> > your daemon (although if this is the only interface for clients this is not a
> > problem!).
> >
> > You still might want to use sd_notify() instead. This can also pass through
> > some internal performance info to systemd which will show up on systemctl
> > status output which is kinda nice.
> >
> > Col
> >
> >
>
> Isn't the classical Linux way an option too?
Well, it is, but it is hard to get right and a lot of redundant code
involved.
> - the daemon does its initialization with the calling thread
> - once it is done with the initialization, it forks off a process that
> goes on with the daemons work (the main loop probably)
No, this is wrong. You really shouldn't do initialization in one process
and then run the daemon from a forked off second one. A lot of (library)
code is not happy with being initialized in one process and being
used in another forked off one. For example, any code involving threads
is generally allergic to this, since background threads cease to exist
in the forked off child. This is nearly impossible to work around
[1]. Or code involving file locks or even a lot of socket code doesn't
like it either. In general you should not assume that any library can
handle it, except for those cases where the library author explicitly
tells you that it is safe.
Actually, all systemd libraries (like libsystemd-journal or
libsystem-bus) and a couple of my other libraries (like libcanberra)
explicitly check for the PID changing and refuse operation in such
cases, simply because the effects of fork()ing are so nasty. Or to be
more explicit: if you initialize a "sd_journal" or "sd_bus" object in
one process and then try to execute any operation on it in a forked off
child process you will get -ECHILD returned which is how we indicate
this misuage.
So, what is the right way to do this? Fork off early, do the
initialization in the child, and signal the parent that you are done via
a pipe, so that the parent exits only after the child is done. This is
explained in daemon(7).
Or even better: don't bother at all, write your services without
forking, and use Type=dbus or Type=notify instead.
Lennart
[1] Yeah, and don't tell me pthread_atfork() is the solution for
this. It's not. It makes things even worse, since there's no defined
execution order defined for it. If you claim pthread_atfork() was a
solution and not a problem in itself, then you obviously have never
used it, or only in trivial programs.
--
Lennart Poettering, Red Hat
More information about the systemd-devel
mailing list