1

I have ported my LSB-controlled daemon to systemd using a wrapper script that starts and stops the daemon. My systemd (multi-instance) service file uses Type=forking, ExecStart=..., ExecStop=..., and PIDFile=....

When starting, everything looks OK in systemd, but stopping always seems to fail. As in the LSB environment this worked fine, I suspected systemd (228) to do something bad.

Actually I found out that after a successful start the PIDfile is gone, so my wrapper script returns with exit code 1 (as the PID file could not be found where expected).

So does systemd really remove the PID file? The side effect is that systemd seems to kill my daemon hard after the wrapper-script returned an error.

0

2 Answers 2

1

Yes, systemd removes pidfiles when the service unit enters the 'dead' state. However, that happens after the service has been stopped (ExecStop finished and processes killed).

I would recommend not using wrapper scripts for ExecStop, because... well, that's what systemd does. Being a service manager, it knows what PID is your daemon (even if you don't use a pidfile) and it can natively send signals to stop the service.

3
  • Yes, this applies for new developments, but when you "port" existing services to systemd, you may want to go "the way of least resistance" (i.e.: not rewriting your service, just to make systemd happy).
    – U. Windl
    Commented Aug 21, 2020 at 7:07
  • SystemD cannot know for sure the PID of a forking service without a PID file, which is why this option exists. From the docs: "If [Type=forking]... it is recommended to also use the PIDFile= option, so that systemd can reliably identify the main process of the service."
    – qris
    Commented Sep 28, 2023 at 10:50
  • @qris: In most cases it can make a reasonable guess (since it only needs to consider PIDs within the service's own cgroup), especially if it's not the kind of service that'd spawn worker processes. If the cgroup only has one PID left, that's the main PID. Commented Sep 28, 2023 at 10:58
1

It seems systemd does not remove the PID file; instead my daemon does not create it due to an incompatibility with "good old init": After fork()ing my daemon's child process waits for the parent to exit like this:

while (getppid() != 1)
        sleep_for_5_ms();

Next the child would write the PID file.

As an strace showed, getppid() constantly returned 31940 which turned out to be the PID of systemd (systemd has another PID of 1, too). So systemd does some magic incompatible reparenting.

Maybe the problem is actually related to the fact that my service is running as a "user" service (and not as a "system" service) (I' still unsure about the differences). This question may be related: How can I run systemd as a process with pid 1 and with pid not 1?

Also useful is this: What is the difference between systemd's user and system services?

Actually the problem did go away after I had changed the service from a user service to a system service.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .