68

I am trying to understand how can I make my program a daemon. So some things which I came across are in general, a program performs the following steps to become a daemon:

  1. Call fork().

  2. In the parent, call exit(). This ensures that the original parent (the daemon's grandparent) is satisfied that its child terminated, that the daemon's parent is no longer running, and that the daemon is not a process group leader. This last point is a requirement for the successful completion of the next step.

  3. Call setsid(), giving the daemon a new process group and session, both of which have it as leader. This also ensures that the process has no associated controlling terminal (as the process just created a new session, and will not assign one).

  4. Change the working directory to the root directory via chdir(). This is done because the inherited working directory can be anywhere on the filesystem. Daemons tend to run for the duration of the system's uptime, and you don't want to keep some random directory open, and thus prevent an administrator from unmounting the filesystem containing that directory.

  5. Close all file descriptors.

  6. Open file descriptors 0, 1, and 2 (standard in, standard out, and standard error) and redirect them to /dev/null.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>

int main (void)
{
    pid_t pid;
    int i;
    
    /* create new process */
    pid = fork ( );  
    if (pid == -1)  
        return -1;  
    else if (pid != 0)  
        exit (EXIT_SUCCESS);  

    /* create new session and process group */  
    if (setsid ( ) == -1)  
        return -1;  

    /* set the working directory to the root directory */  
    if (chdir ("/") == -1)  
        return -1;  

    /* close all open files--NR_OPEN is overkill, but works */  
    for (i = 0; i < NR_OPEN; i++)  
        close (i);  

    /* redirect fd's 0,1,2 to /dev/null */  
    open ("/dev/null", O_RDWR);  
    /* stdin */  
    dup (0);  
    /* stdout */  
    dup (0);  
    /* stderror */  
    
    /* do its daemon thing... */  
    
    return 0;  
}

Can some one give me a link to existing source code of some program like Apache so that I can understand this process in more depth?

Rachid K.
  • 4,490
  • 3
  • 11
  • 30
Registered User
  • 5,173
  • 16
  • 47
  • 73
  • 2
    You can get Apache sources [here](http://httpd.apache.org/download.cgi). – nmichaels Mar 21 '11 at 21:51
  • 7
    Perhaps [daemon(3)](http://linux.die.net/man/3/daemon) might be helpful. It says basically that the needed functionality is already implemented. – Vlad Mar 21 '11 at 21:53
  • @nmichaels thanks for your message actually I am looking for only those lines which make it a daemon.Apache not specifically.So if some where online will be easy than downloading entire source. – Registered User Mar 21 '11 at 21:53
  • @Vlad I had seen daemon3 but I want to understand from complete basic. – Registered User Mar 21 '11 at 21:54
  • 2
    Related to http://stackoverflow.com/questions/3095566/linux-daemonize – ninjalj Mar 21 '11 at 22:33
  • Note that according to their manpages, both setsid() and chdir() can't fail here, so you don't need to check their respective return values. – Philip Mar 22 '11 at 09:36
  • In addition to what `daemon` does, I usually drop privileges to some user and group using `setgid` and `setuid`. If you want to look into what `daemon` does, I would look into the source – Jens Munk May 22 '16 at 09:37
  • 2
    The above post is almost 100% copy-paste from book [Linux System Programming, 2nd Edition - Talking Directly to the Kernel and C Library](http://shop.oreilly.com/product/0636920026891.do) by [Robert Love](https://en.wikipedia.org/wiki/Robert_Love) (pages 173, 174). It would be nice if @RegisteredUser had mentioned that. – patryk.beza Aug 07 '16 at 09:53
  • In 2004, Devin Watson wrote a good article on this subject: "Linux Daemon Writing HOWTO". It has been archived on, at least, a couple of sites: [archive.org as of 2006-06-03](http://web.archive.org/web/20060603181849/http://www.linuxprofilm.com/articles/linux-daemon-howto.html) and [bibalex.org as of 2006-06-03](http://web.archive.bibalex.org/web/20060603181849/http://www.linuxprofilm.com/articles/linux-daemon-howto.html) – Makyen Nov 18 '16 at 19:26

3 Answers3

23

If you are looking for a clean approach please consider using standard api- int daemon(int nochdir, int noclose);. Man page pretty simple and self explanatory. man page. A well tested api far outweigh our own implementation interms of portability and stability.

deadbeef
  • 621
  • 6
  • 20
  • 1
    I'm glad that this is an *answer* now, instead of being hidden in the comments. Perhaps you could flesh it out a little – link to the standard (or even better, a link to a tutorial or example). – RJHunter May 22 '16 at 10:34
  • 2
    @deadbeef That answer is much better than the plain [_link only_ answers](http://meta.stackoverflow.com/questions/323508/what-to-do-with-broken-but-highly-upvoted-link-only-answers) that were present before. But though it's also quite close to a _link only_ (anyway I would consider the given link much more stable). I would try to enhance the answer, giving a short code sample (especially since there's none in the linked man page), or citing the synopsis. – πάντα ῥεῖ May 23 '16 at 17:33
  • 2
    Note that [daemon](http://man7.org/linux/man-pages/man3/daemon.3.html) function is **not** POSIX compliant. – patryk.beza Aug 07 '16 at 09:56
  • 2
    On https://www.freedesktop.org/software/systemd/man/daemon.html#SysV%20Daemons it is written that "the BSD `daemon()` function should not be used, as it implements only a subset of these [15] steps." – oli_arborum Feb 15 '17 at 08:10
2

In Linux, it can be easily done using:

int main(int argc, char* argv[])
{
    daemon(0,0);
    while(1)
    {
        sleep(10)
        /*do something*/
    }

    return 0;
}
jww
  • 97,681
  • 90
  • 411
  • 885
Alok Prasad
  • 622
  • 7
  • 12
0

Concerning the part which closes the file descriptors, under Linux, the GLIBC's deamon() service merely redirects file descriptors 0, 1 and 2 to /dev/null using dup2(). Here is the code snippet of daemon() in GLIBC 2.34 (file misc/daemon.c):

    if (!noclose) {
        struct stat64 st;

        if ((fd = __open_nocancel(_PATH_DEVNULL, O_RDWR, 0)) != -1
            && (__builtin_expect (__fstat64 (fd, &st), 0)
            == 0)) {
            if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0
#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
                && (st.st_rdev
                == makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR))
#endif
                ) {
                (void)__dup2(fd, STDIN_FILENO);
                (void)__dup2(fd, STDOUT_FILENO);
                (void)__dup2(fd, STDERR_FILENO);
                if (fd > 2)
                    (void)__close (fd);

Closing all the possible opened file descriptors using the NR_OPEN constant (typically equal to 1024) is not reliable as the limit on the number of opened file descriptors can be changed with setrlimit(RLIMIT_NOFILE, ...).
The currently opened file descriptors are present as symbolic links names in /proc/pid/fd directory. Here is the content of this directory from my current shell:

$ ls -la /proc/$$/fd
total 0
dr-x------ 2 xxx xxx  0 sept.   4 09:32 .
dr-xr-xr-x 9 xxx xxx  0 sept.   4 09:32 ..
lrwx------ 1 xxx xxx 64 sept.   4 09:32 0 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:32 1 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:32 2 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:41 255 -> /dev/pts/2

Hence, a service function opening this directory for the current process could be used to close only the actually opened file descriptors:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void close_opened_fds(void)
{
  DIR *dp;
  char proc_fd_dirname[256];
  int my_fd;
  struct dirent *d;
  int fd;

  // Open /proc/<mypid>/fd directory
  snprintf(proc_fd_dirname, sizeof(proc_fd_dirname), "/proc/%d/fd", getpid());
  dp = opendir(proc_fd_dirname);
  if (!dp) {
    return;
  }

  // Get the file descriptor associated to the preceding open
  my_fd = dirfd(dp);

  while((d = readdir(dp))) {

    // Skip '.' and '..' directories
    if (d->d_name[0] == '.') {
      continue;
    }

    fd = atoi(d->d_name);

    // Close the file except if it is the fd of the opened directory
    if (fd != my_fd) {
      close(fd);
    }

  }

  closedir(dp);

}
Rachid K.
  • 4,490
  • 3
  • 11
  • 30