Making a Linux Daemon

I just faced this problem at work and found a great little document that gave me the insight I needed. I'm posting it here for anyone else who is interested.

http://www.linuxprofilm.com/articles/linux-daemon-howto.html

Update
This page is currently the most popular on the site and it was well overdue for a refresh.

As stated in comments below the simplest way to do this in Linux is to use the daemon() system call. However, this function does not exist in System V based Unix distributions (ie, Solaris).

The basic concept that needs to happen is that your application forks itself and shuts down its standard input/output/error connections.

The C++ code I use for this is:

//! daemonize the currently running programming
//! Note: the calls to strerror are not thread safe, but that should not matter
//! as the application is only just starting up when this function is called
//! \param[in] dir which dir to ch to after becoming a daemon
//! \param[in] stdinfile file to redirect stdin to
//! \param[in] stdoutfile file to redirect stdout from
//! \param[in] stderrfile file to redirect stderr to
void System::daemonize(const string &dir = "/",
               const std::string &stdinfile = "/dev/null",
               const std::string &stdoutfile = "/dev/null",
               const std::string &stderrfile = "/dev/null")
{
  umask(0);

  rlimit rl;
  if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
  {
    //can't get file limit
    throw std::runtime_error(strerror(errno));
  }

  pid_t pid;
  if ((pid = fork()) < 0)
  {
    //Cannot fork!
    throw std::runtime_error(strerror(errno));
  } else if (pid != 0) { //parent
    exit(0);
  }

  setsid();

  if (!dir.empty() && chdir(dir.c_str()) < 0)
  {
    // Oops we couldn't chdir to the new directory
    throw std::runtime_error(strerror(errno));
  }

  if (rl.rlim_max == RLIM_INFINITY)
  {
    rl.rlim_max = 1024;
  }

  // Close all open file descriptors
  for (unsigned int i = 0; i < rl.rlim_max; i++)
  {
    close(i);
  }

  int fd0 = open(stdinfile.c_str(), O_RDONLY);
  int fd1 = open(stdoutfile.c_str(),
      O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
  int fd2 = open(stderrfile.c_str(),
      O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);

  if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
  {
    //Unexpected file descriptors
    throw runtime_error("new standard file descriptors were not opened as expected");
  }
}

By removing the references to std::string and throw this code is easily converted to C code.

The book "Advanced Programming in the UNIX Environment" covers in depth how to deamonize a process, why you would want to and what happens under the hood. I keep it as a desk reference and highly recommend it.

The hardback version:

Advanced Programming in the UNIX(R) Environment (2nd Edition) (Addison-Wesley Professional Computing Series)

And paperback is now available too:

Advanced Programming in the UNIX Environment: Paperback Edition (2nd Edition) (Addison-Wesley Professional Computing Series)

Comments

A bit complex

Using the daemon() system call would eliminate 3/4 of the program.

If it exists...

The daemon() system call would have been a good choice at the time that I posted that comment, good point. However, it is a nonstandard call and may or may not exist on the platform you are writing for.

Linux Daemon how-to document gone!

Ah well.. looks like that how-to write a Daemon article is toast. Anybody have a copy of their own - there was a PDF originally as well. Looking to create some Daemons using C on embedded Linux.

Thanks muchly.

Thank you

Linux Rules!
Thank you.

how to restart a daemon after it terminates in source code

I am trying to find a way to restart (respawn) the daemon after it dies, is there a way to do this in the daemon source code?

Thanks
Mike

Respawning a killed Daemon

Well. I am not aware of a way of doing this in the Daemon's source code itself. I don't think it is even possible because if you application is dead, there is nothing much it can do to revive itself. :-) What can be done instead is to have an entry for your Daemon in /etc/inittab specifying the "respawn" option. This way, init will take care of respawning your Daemon if it is killed.

Re: Respawning a killed Daemon

As a partial solution, you can install signal handlers in your daemon to respond to some signals. (SIGTERM maybe). But there is nothing much you can do about SIGKILL. So, /etc/inittab is a complete solution.