3

I'm currently developping a systemd daemon. The problem I'm facing is that the daemon is killed 1m30s after beeing launched because the forking is not detected.

I'm using the int daemon(int nochdir, int noclose) function to daemonize the process.

int main()
{
    openlog("shutdownd", LOG_PID, LOG_DAEMON);

    if(daemon(0, 0) != 0)
    {
        syslog(LOG_ERR, "Error daemonizing process : %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    syslog(LOG_NOTICE, "Daemon started !\n");

    pthread_create(&threads[0], NULL, &alimThread, NULL);
    pthread_create(&threads[1], NULL, &extinctThread, NULL);
    pthread_create(&threads[2], NULL, &blinkThread, NULL);

    while(1)
    {
    }

    syslog(LOG_NOTICE, "Daemon stopped !\n");
    exit(EXIT_SUCCESS);
}

Here is the service file /etc/systemd/system/shutdownd.service

[Unit]
Description=Shutdown Daemon
After=syslog.target

[Service]
Type=forking
PIDFile=/var/run/shutdownd.pid
ExecStartPre=/bin/rm -f /var/run/shutdownd.pid
ExecStartPre=/usr/bin/shutdownd-exportGpio.sh
ExecStart=/usr/bin/shutdownd
Restart=on-abort

[Install]
WantedBy=multi-user.target

The daemon function is supposed to fork the process and detach it from the terminal, I also close file desciptors and change the working directory to /.

However systemd seems to don't detect the forking as it kill my running daemon after 1m30s.

Sep  8 13:52:50 raspberrypi systemd[1]: shutdownd.service: PID file /var/run/shutdownd.pid not readable (yet?) after start: No such file or directory
Sep  8 13:52:50 raspberrypi shutdownd[293]: Daemon started !
Sep  8 13:52:50 raspberrypi shutdownd[293]: [Extinct] Value changed to 0
Sep  8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep  8 13:52:50 raspberrypi shutdownd[293]: [Alim] Value changed to 0
Sep  8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep  8 13:53:46 raspberrypi shutdownd[293]: [Alim] Value changed to 1
Sep  8 13:53:46 raspberrypi shutdownd[293]: Toogle : ON
Sep  8 13:53:48 raspberrypi shutdownd[293]: Toogle : OFF
[...]
Sep  8 13:54:16 raspberrypi shutdownd[293]: [Extinct] Value changed to 1
Sep  8 13:54:16 raspberrypi shutdownd[293]: ON
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Start operation timed out. Terminating.
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Unit entered failed state.
Sep  8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Failed with result 'timeout'.

Does anyone as a clue about why systemd doesn't detect the forking ?

Do I have to explicitly call fork() in my code?
In this case I'll have to code the daemonize function by myself which is not so difficult but totally useless and redundant since a c function already exists for that purpose.

6

Do not do that.

At all. Any of it, either through a library function or rolling your own code. For any service management system. It has been a wrongheaded idea since the 1990s.

Your dæmon is already running in a service context, invoked that way by a service manager. Your program should do nothing in this respect. Stop writing your program that way at all.

And do not use the forking readiness protocol. Your program is multithreaded and will almost certainly not function correctly if you try to add the forking readiness protocol to it, as enacting the protocol correctly means forking after all initialization has been done, including starting up all of the threads. Almost nothing actually uses the forking readiness protocol in the wild. Use another protocol.

Further reading

  • Thank you for the clear answer. If I follow you well, a process should be daemonized ONLY when called from command line. If it's called by a service manager all the required actions (detach from terminal, close descriptors, fork process ...) are automatically done. Also forking protocol should only be used when initializations have to be done before the forking. – Arkaik Oct 31 '17 at 13:46
  • Type=forking is used to tell systemd that the daemon is an old school forking daemon. Type=forking should be used if daemon() is called; it should not be used if the service executable does not fork. But I fully agree with JdeBP that you should leave it to systemd to daemonize the process, and useType=forking only for legacy daemons. Returning to your original problem: I think systemd is detecting that the program forked and the parent exited, but I suspect systemd is still waiting for the PIDFile to appear. Systemd does not write this file, the daemon should write it. – Johan Myréen Oct 31 '17 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.