Systemd – Why ‘The Process Must Not Fork’ for Simple Type Services

forksystemd

I want to write my own systemd unit files to manage really long running commands1 (in the order of hours). While looking the ArchWiki article on systemd, it says the following regarding choosing a start up type:

Type=simple (default): systemd considers the service to be started up immediately. The process must not fork. Do not use this type if other services need to be ordered on this service, unless it is socket activated.

Why must the process not fork at all? Is it referring to forking in the style of the daemon summoning process (parent forks, then exits), or any kind of forking?


1 I don't want tmux/screen because I want a more elegant way of checking status and restarting the service without resorting to tmux send-keys.

Best Answer

The service is allowed to call the fork system call. Systemd won't prevent it, or even notice if it does. This sentence is referring specifically to the practice of forking at the beginning of a daemon to isolate the daemon from its parent process. “The process must not fork [and exit the parent while running the service in a child process]”.

The man page explains this more verbosely, and with a wording that doesn't lead to this particular confusion.

Many programs that are meant to be used as daemons have a mode (often the default mode) where when they start, they isolate themselves from their parent. The daemon starts, calls fork(), and the parent exits. The child process calls setsid() so that it runs in its own process group and session, and runs the service. The purpose is that if the daemon is invoked from a shell command line, the daemon won't receive any signal from the kernel or from the shell even if something happens to the terminal such as the terminal closing (in which case the shell sends SIGHUP to all the process groups it knows of). This also causes the servicing process to be adopted by init, which will reap it when it exits, avoiding a zombie if the daemon was started by something that wouldn't wait() for it (this wouldn't happen if the daemon was started by a shell).

When a daemon is started by a monitoring process such as systemd, forking is counterproductive. The monitoring process is supposed to restart the service if it crashes, so it needs to know if the service exits, and that's difficult if the service isn't a direct child of the monitoring process. The monitoring process is not supposed to ever die and does not have a controlling terminal, so there are no concerns around unwanted signals or reaping. Thus there's no reason for the service process not to be a child of the monitor, and there's a good reason for it to be.

Related Question