Writing a daemon in C (or daemonize a process) for absolute newbie

Published: by

  • Categories:

A daemon is a computer program that runs in the background. In a Unix environment, the parent process of a daemon is often (but not always) the init process (PID=1).

Basically you have to do 6 steps:-

  • Fork off the parent process
  • Change file mode mask (umask)
  • Open any logs for writing
  • Create a unique Session ID (SID)
  • Change the current working directory to a safe place
  • Close standard file descriptors
  • Enter actual daemon code

Few terms may be new to you:-

  • FORK - This is basically used to create a child process. After the fork() call is made, we differentiate the parent and child processes by the return value of fork().
  • UMASK - Its used to set file permissions. umask(0) means you have full read, write, execute access..

While writing the daemon, make sure you open the log files and be very verbose in that because as we dont have direct interaction, it can be sometimes very hard do find the bug.

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

int main(void) {

		/* Our process ID and Session ID */
		pid_t pid, sid;

		/* Fork off the parent process */
		pid = fork();
		if (pid < 0) {
				exit(EXIT_FAILURE);
		}
		/* If we got a good PID, then
		   we can exit the parent process. */
		if (pid > 0) { // Child can continue to run even after the parent has finished executing
				exit(EXIT_SUCCESS);
		}

		/* Change the file mode mask */
		umask(0);

		/* Open any logs here */        

		/* Create a new SID for the child process */
		sid = setsid();
		if (sid < 0) {
				/* Log the failure */
				exit(EXIT_FAILURE);
		}

		/* Change the current working directory */
		if ((chdir("/")) < 0) {
				/* Log the failure */
				exit(EXIT_FAILURE);
		}

		/* Close out the standard file descriptors */
//Because daemons generally dont interact directly with user so there is no need of keeping these open
		close(STDIN_FILENO);
		close(STDOUT_FILENO);
		close(STDERR_FILENO);

		/* Daemon-specific initialization goes here */

		/* An infinite loop */
		while (1) {
		   /* Do some task here ... */

		   sleep(30); /* wait 30 seconds */
		}
   exit(EXIT_SUCCESS);
}