Daemonizing Processes and System Log

If you write software for embedded applications, sooner or later you will end up writing a daemon.

In my work I see many embedded applications, but very often the programmer write and debug all the program in foreground, and then forgets to implement a simple daemonize function.

The consequence is that when the application is started from the init scripts instead that from a command shell, it locks up the entire boot sequence of the system.

Also, when writing a background application, all the messages should be redirected to the system log… don’t reinvent the wheel rewriting a new logging system!

Here I’ll show a sample daemonize() function, and how to use the syslog() library function.

Daemonizing

To daemonize a process, the following steps are required (in debatable order):

  • Redirect all standard file descriptors to /dev/null, as you don’t want to keep some pty open for standard input/output/error.
      if ((i = open("/dev/null", O_RDONLY)) != 0) {
        dup2(i, 0);
        close(i);
      }
    ...
    
  • Get a new session id for the running process.

      setsid();
    
  • Fork! This will duplicate the current process, you can then terminate the parent and leave the detached child running.

      pid = fork();
    

This procedure will work on Linux systems, through some minor change may be necessary to completely detach the process on other Unixes.

Also, you should be sure that the current directory is in a safe place. A chdir() to “/” may be a good idea.

Syslog

When detaching the process, you lose all the standard file descriptors where you used to write your precious runtime info messages. After all, the terminal from where you started the daemon may not even exist anymore!

So, this is how you can use the system log to pass messages to the system in a clean way… remember this is part of the standard library!

  • Open a connection to the system loger daemon, you have to specify an identifier string (usually the process name), an option mask (chain options with the | operator) and the logging facility (LOG_DAEMON for generic system daemons).

    openlog(argv[0], LOG_PID, LOG_DAEMON);
  • To write a message to the logger daemon, use the syslog function, specifying the message level (see the syslog man page) and the message itself with a printf-like syntax.

    syslog(LOG_INFO, "syslog test: %d", i);
  • When you are over, close the connection to the system logger with a closelog call.

    closelog();

That’s it! For all the details, check out the syslog man page.

Complete Example

This is a complete example application who daemonize, write 10 messages on the system log, one each second, and then terminate.

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

static void daemonize (void)
{
  int i;
  pid_t pid;

  if ((i = open("/dev/null", O_RDONLY)) != 0) {
    dup2(i, 0);
    close(i);
  }
  if ((i = open("/dev/null", O_WRONLY)) != 1) {
    dup2(i, 1);
    close(i);
  }
  if ((i = open("/dev/null", O_WRONLY)) != 2) {
    dup2(i, 2);
    close(i);
  }

  setsid();

  pid = fork();

  if (pid < 0) {
    perror("fork");
    exit(1);
  } else if (pid) { /* parent */
    exit(0);
  } else { /* child */
  }
}

int main (int argc, char ** argv)
{
  int i;

  openlog(argv[0], LOG_PID, LOG_DAEMON);

  printf("About to daemonize...\n");
  
  syslog(LOG_INFO, "daemonize");
  daemonize();

  for (i = 0; i < 10; i++) {
    syslog(LOG_INFO, "syslog test: %d", i);
    sleep(1);
  }

  syslog(LOG_INFO, "exit");
  closelog();

  return 0;
}

Compile it with:

gcc -o exampled exampled.c

Happy forking!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s