4

Creating daemons in Linux is quite complex issue, but it's very well documented in daemon(7) manual. Thankfully there is python-daemon module for Python 2 and 3 that implement PEP3143, so I'm using it.

Here comes the question: when I was playing with python-daemon module I was surprised that daemon's PPID is not 1. Why?


Simple example:

import daemon
import time
import os

with open('/tmp/test.log', 'w') as logfile:
    c = daemon.DaemonContext(stdout=logfile)
    with c:
        print('In daemon...')
        for i in range(10):
            print('My PID is {}, PPID is {}'.format(os.getpid(), os.getppid()))
            time.sleep(2)

Content of test.log after 20 seconds from starting the above script (I recommend tail -f /tmp/test.log):

In daemon...
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736
My PID is 31397, PPID is 1736

It turned out that process with PID 1736 is /lib/systemd/systemd:

patryk@mycomp:/tmp$ ps -fq 1736
UID        PID  PPID  C STIME TTY          TIME CMD
patryk    1736     1  0 kwi12 ?        00:00:00 /lib/systemd/systemd --user

Recently I was implementing daemons in C (on the same machine with systemd installed) and AFAIR all daemons had PPID = 1. All manuals I came across mention that daemon's PPID is always 1.

Does systemd changed it? Does systemd process awaits for all processes – including daemons? Is it daemon's correct behavior?


Related questions:

patryk.beza
  • 4,125
  • 5
  • 34
  • 49

2 Answers2

3

The short answer is: It doesn't matter.

The important thing is that all daemons have a parent process like init that will reap children when they die, by calling wait(). Otherwise the process will become a zombie when it exits.

There's nothing particularly special about having a parent PID of 1. The manual page you linked to says this process is PID 1 for old, SysV-style daemons, but doesn't say so for new SystemD-style daemons. init always runs as PID 1, and traditionally it was the parent of daemons. But it doesn't need to be so.

systemd --user manages user services. Thus, it makes sense why this process becomes your daemon's parent process when you run it (as a user).

One must be careful when reading documentation about *nix, a platform that's been around for decades. Things change and manuals become obsolete, or can be interpreted in the wrong context. SystemD brings major change to a lot of things about the Linux platform.

Jonathon Reinhart
  • 116,671
  • 27
  • 221
  • 298
  • It is also incidental that `init` gets PID 1: because it is the first user-space process that the kernel runs, and it never exits while the system is online. The PID 1 is not special for any other reason; similarly, the PID of `systemd` is not special. – bignose Feb 11 '19 at 20:09
0

All manuals I came across mention that daemon's PPID is always 1.

Those manuals are incorrect; a daemon gets whatever parent is going to manage detached processes.

If that happens to be the init process, and if init happens to have PID 1, then that'll be the daemon's PPID; but both of those are arbitrary, not definitional. Manuals should not imply otherwise.

The init process only typically gets PID 1 (and apparently there are no exceptions to this) because, arbitrarily, the first user-space process gets assigned PID 1, and that happens to be init, which then never exits while the host is online. There's nothing special about PID 1 otherwise.

The systemd process will, likewise, get whatever arbitrary PID is assigned for the timing of its start-up.

Other process managers, such as runit, will similarly get an arbitrary PID when they start up.

Can you post a bug report to those manuals that are getting it wrong?

bignose
  • 24,957
  • 12
  • 70
  • 100
  • I don't think it's quite as arbitrary as you say. The Linux kernel mentions in several places that `init` is PID 1: *"We need to spawn init first so that it obtains pid 1"* ([`init/main.c`](https://github.com/torvalds/linux/blob/v4.20/init/main.c#L405)), *"init really needs pid 1"* ([`kernel/pid.c`](https://github.com/torvalds/linux/blob/v4.20/kernel/pid.c#L182)), *"there is always at least one task in the system (init, pid == 1)"* ([`kernel/cgroup/cgroup.c`](https://github.com/torvalds/linux/blob/v4.20/kernel/cgroup/cgroup.c#L1386)). – Jonathon Reinhart Feb 11 '19 at 21:19