Systemd timeout because it doesn't detect daemon forking

6,630

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

Share:
6,630

Related videos on Youtube

Arkaik
Author by

Arkaik

Updated on September 18, 2022

Comments

  • Arkaik
    Arkaik over 1 year

    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.

  • Johan Myréen
    Johan Myréen over 6 years
    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.