How does systemd
handle the death of the children of managed processes?
Suppose that systemd
launches the daemon foo
, which then launches three other daemons: bar1
, bar2
, and bar3
. Will systemd
do anything to foo
if bar2
terminates unexpectedly? From my understanding, under Service Management Facility (SMF) on Solaris foo
would be killed or restarted if you didn't tell startd
otherwise by changing the property ignore_error
. Does systemd
behave differently?
Edit #1:
I've written a test daemon to test systemd
's behavior. The daemon is called mother_daemon
because it spawns children.
#include <iostream>
#include <unistd.h>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
cout << "Hi! I'm going to fork and make 5 child processes!" << endl;
for (int i = 0; i < 5; i++)
{
pid_t pid = fork();
if (pid > 0)
{
cout << "I'm the parent process, and i = " << i << endl;
}
if (pid == 0)
{
// The following four lines rename the process to make it easier to keep track of with ps
int argv0size = strlen(argv[0]);
string childThreadName = "mother_daemon child thread PID: ";
childThreadName.append( to_string(::getpid()) );
strncpy(argv[0],childThreadName.c_str(),argv0size + 25);
cout << "I'm a child process, and i = " << i << endl;
pause();
// I don't want each child process spawning its own process
break;
}
}
pause();
return 0;
}
This is controlled with a systemd
unit called mother_daemon.service
:
[Unit]
Description=Testing how systemd handles the death of the children of a managed process
StopWhenUnneeded=true
[Service]
ExecStart=/home/my_user/test_program/mother_daemon
Restart=always
The mother_daemon.service
unit is controlled by the mother_daemon.target
:
[Unit]
Description=A target that wants mother_daemon.service
Wants=mother_daemon.service
When I run sudo systemctl start mother_daemon.target
(after sudo systemctl daemon-reload
) I can see the parent daemon and the five children daemons.
Killing one of the children has no effect on the parent, but killing the parent (and thus triggering a restart) does restart the children.
Stopping mother_daemon.target
with sudo systemctl stop mother_daemon.target
ends the children as well.
I think that this answers my question.
Best Answer
It doesn't.
The main process handles the death of its children, in the normal way.
This is the POSIX world. If process A has forked B, and process B has forked C, D, and E; then process B is what sees the
SIGCHLD
andwait()
status from the termination of C, D, and E. Process A is unaware of what happens to C, D, and E, and this is irrespective of systemd.For A to be aware of C, D, and E terminating, two things have to happen.
service-manager
.exit()
. Services that foolishly, erroneously, and vainly try to "dæmonize" themselves do this.(One can get clever with
kevent()
on the BSDs. But this is a Linux question.)