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

Re: 8 -> 9 update changing things



On Tue, Jan 11, 2022 at 01:15:05PM +0100, Andrei POPESCU wrote:
> On Lu, 03 ian 22, 14:02:05, Roy J. Tellason, Sr. wrote:
> > In the one that was running to start with,  the command line shown to 
> > me in system monitor includes "daemonize=no".  I would guess that to 
> > be the problem,  but why is that in there?

You need to rewind quite a few years of history for a full answer to
this.

> In general it's recommended programs rely on systemd for running in 
> background instead of implementing their own code for that (re-inventing 
> the wheel and all that).
> 
> Of course, some programs (including PulseAudio) predate systemd and/or 
> need to run on systems / platforms where systemd (or something 
> compatible) is not even available, so they will continue to support both 
> methods.

Imagine that you're sitting down at a Unix workstation back in the 1980s
or 1990s.  There's no systemd, no dbus, no CORBA, nothing at all like
that.  You probably login via xdm, and you get an X11 session with a
single xterm and twm as your window manager.  That's it.  That's your
whole session.  Nothing else is running -- just the X server, the window
manager, and a single terminal.

Now, you'd like to run a few more things.  So you focus on the terminal
and you start running some commands:

xclock &
xbiff &
xterm -e top &
xterm &
xterm &

Now you've got some additional terminals with interactive shells in them,
and some programs that give you information.

If you'd like all of these programs to start next time you login, there
will be some kind of dot-file that you can edit, probably ~/.xsession.
You just put those commands in there, and then... whoops, you forgot to
put your window manager!  So, you login remotely, fix the ~/.xsession
file so that it ends with "exec twm" or whatever, and you're good to go.

Do you see how all of the commands that you wanted to run end with "&"
so that they will be placed in the background by the shell?  There's
nothing wrong with that at all, but it will become relevant in a moment.

Next, imagine that you're the system administrator of a Unix workstation
back in the 1980s or 1990s.  You'd like to run some programs at boot
time -- maybe one of those fancy Internet mail transport programs like
sendmail!

After reading manuals for a few hours, you manage to get sendmail installed
and configured, and now that it's time to run it, you put some command
like this into /etc/rc.local:

/usr/lib/sendmail &

And... it works, maybe.  You've applied your knowledge of the shell to
a system administration problem.  Only, maybe it doesn't work.  Maybe
your particular flavor of Unix runs /etc/rc.local with a shell where
background jobs are terminated after the shell exits.

So, if you're on one of those systems, you cobble together a workaround:

csh -cf '/usr/lib/sendmail &'

And this works!  But it's so ugly.

But hey, this idea of programs running automatically when the system boots
is starting to gain some traction.  People are doing it everywhere.
Literally hundreds of Unix sites around the country!

So, at some point, the people who write system software like sendmail
all decided to make the system administrator's life "easier", and they
added options to "daemonize" themselves.  Now the system administrator
wouldn't have to do all that crazy shell stuff.  They can simply write:

/usr/lib/sendmail -bd

And voila.  The sendmail daemon will fork a child process, and then the
parent will terminate.  The abandoned child will be re-parented by the
init daemon (process ID 1).  The abandoned child is the real daemon, and
it will continue running in the background, forever.  Or until it crashes.
But that's a next year problem!

For a decade or two, this became the norm across BSD-like systems.  Newly
written daemons all decided that they should either fork and abandon a
child process by default, or offer an option to do this.  It became the
new fad.  All the cool kids were doing it.

And then the problems started.

Maybe you didn't *want* the same instance of sendmail to run forever.  What
if you edited the configuration file, and wanted to reload the daemon with
the new configs?  How do you do that?

Well, obviously, you sit down at the console, login as root, and use commands
like "ps auxw | grep sendmail" to find the daemon.  Then when you've
found it, you can use a command like "kill -1 2345" to send a signal to
the daemon, telling it to reread the configs.

Of course, finding a running process this way is an art, not a science.
A human system administrator can do it.  It's not all that hard, right?
If Susan is sendiing mail right now, her sendmail process is going to
look different from the daemon that you're trying to locate in the haystack.
You'll be able to tell the difference and identify the correct process.
It just takes a few moments of careful attention and effort.

A computer program can't do that.

So, what happens when your operating system introduces this brand new
shiny "init system" that tries to unify the way daemons are started
and controlled?  We're solidly into the 1990s by now, or maybe the 2000s,
and most systems are using a variant of the "System V init" software with
"rc scripts".

Basically, these things are shell scripts that take a mandatory argument
like "start" or "stop".  The idea is that you (the system administrator)
can write one of these shell scripts and have it either start or stop
the daemon.  Then you drop it in a special directory, and the operating
system will run it with the argument "start" at boot time, and again
with the argument "stop" at shutdown time.  Or you can run it yourself
at any time you like, if you want to restart the daemon.

But... all of the daemons are still using that faddish "-bd" style code
from the 1980s.  How do you write a shell script to stop a daemon that is
really an abandoned child process?  You'd have to find its process ID
somehow.  How are you going to do that?  Your script doesn't have the
brain power of a human being, so it can't sift through the output of "ps".

People who write programs like sendmail came up with an answer to that:
they told the daemon to write its PID into a file in a known location
on the disk.  So in an "rc script" for sendmail, you can put code like
this:

case $1 in
  start) /usr/lib/sendmail -bd ;;
  stop)  kill `cat /var/lib/sendmail.pid` ;;
esac

The idea of the "PID file" became the new norm.

But what happens if sendmail crashes on its own?  Maybe it has a bug!
(In real life, sendmail had so many bugs that it's amazing people used
it for so long.)

If the sendmail daemon that was started at boot time (and wrote its PID
into that PID file) crashes, then the PID is freed for reuse by the
adoptive parent process.  You can't have a bunch of zombies walking around!
So, the PID goes back in the pool, and eventually, some other program
will use it.

Now you've got a PID file that contains the PID of some entirely different
program, which has nothing do with sendmail.  Maybe it's your boss's
window manager!  It could be anything!

This is why PID files are terrible.

But they're necessary!  Because all of the daemons put themselves in
the background!  Because that's such a stylish thing to do!

As it turns out, having daemons put themselves into the background was
in fact a *terrible* idea.  It breaks everything else, and creates an
ecosystem of workarounds.

In the late 1990s and early 2000s, when System V init/rc was running
rampant through the increasingly popular Linux communities, some other
folks realized the issue, and started working on alternative init systems.

If you'd like more details on this, I recommend JDEBP's web site.  You
can start at <http://jdebp.info/FGA/system-5-rc-problems.html>.

In a nutshell, the alternatives to sysvinit all start out with the
premise that a daemon should *not* abandon a child in the background.
The daemon should simply run like a normal program, only terminating
when it's told to do so, or when it encounters a fatal condition.  Then,
the init system can manage it like any normal program.  The init system
will immediately know when it terminates, and can restart it if the
system administrator desires.  Or, if the admin wants to restart it,
the init system knows exactly which process ID to send a signal to.
There's no "stale PID file" problem, because PIDs aren't written to files.
Process IDs are held by the parents.  Everything works so much better.

But... we've still got all of these old system programs like sendmail
that have -bd options.  Or worse, some of them may create and abandon
a child process by default!  How do we deal with this mess?

In some cases, you simply stop using the -bd option, or its equivalent.
In other cases, maybe you have to patch the daemon to offer a new
option which says *don't* create a child process -- just run normally.

That's what you're seeing here with Pulse Audio.

> > In the one that was running to start with,  the command line shown to 
> > me in system monitor includes "daemonize=no".  I would guess that to 
> > be the problem,  but why is that in there?

This is a program whose default behavior was to create a child process,
and an option was added to tell it not to do that.  Since systemd is
one of the new alternative init systems that want normal daemons, it's
using that option to force normal behavior.

Maybe in a few more years, or decades, all of the old "daemonize by
default" programs will have gone away, or will have changed their default
behavior to the more sensible "don't daemonize by default" choice.
Until that happens, you're going to continue to see a chaotic mix of
programs that behave in different ways, with different options to
control them.

Welcome to Unix.


Reply to: