Brent Kandetzki
Brent Kandetzki

Reputation: 3

redirecting daemon output when already redirected to /dev/null

I have created a program that has the option to be started as a daemon, as well as the option to redirect output to a file. Everything works as expected unless the application is started with it's output already directed to /dev/null. This is a problem because the application is being started by another application where the output is redirected to /dev/null.

Starting the application like this will work as expected, with all output written to the file.

./my_daemon -d -f/tmp/logfile

However, starting the application like this will create the log file, but it will be empty.

./my_daemon -d -f/tmp/logfile &> /dev/null

The program is:

sintn main(sintn osn_argc, charn *opacn_argv[])
{
  sintn sn_i;
  charn *pcn_log_file = NULL;
  boolean q_daemonize;
  sintn sn_log_file = -1;
  pid_t t_pid = 0;
  pid_t t_sid = 0;

  printf("Enter Main\n");

  //check for parameters
  for (sn_i = 1; sn_i < osn_argc; sn_i++)
  {
     if (opacn_argv[sn_i][0] == '-')
     {
        switch(opacn_argv[sn_i][1])
        {
           case 'd':
           case 'D':
              q_daemonize = TRUE;
              break;

           case 'f':
           case 'F':
              pcn_log_file = &opacn_argv[sn_i][2];
              break;

           default:
              printf("Unknown parameter '%s'\n", opacn_argv[sn_i]);
        }
     }
  }

  if (q_daemonize == TRUE)
  {
     t_pid = fork();// fork a new child process

     if (t_pid < 0)
     {
        printf("Fork failed!\n");
        exit(1);
     }

     if (t_pid > 0)// its the parent process
     {
        printf("Forked: pid of child process %d \n", t_pid);
        exit(0); //terminate the parent process succesfully
     }

     umask(0);//unmasking the file mode

     t_sid = setsid();//set new session
     if(t_sid < 0)
     {
        exit(1);
     }

     close(STDIN_FILENO);

     if (pcn_log_file != NULL)
     {
        sn_log_file = open(pcn_log_file, O_CREAT | O_APPEND | O_WRONLY, S_IRWXU | S_IRWXG | S_IRWXO );
     }

     if (sn_log_file >= 0)
     {
        dup2(sn_log_file, STDOUT_FILENO);
        dup2(sn_log_file, STDERR_FILENO);
     }
     else
     {
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
     }
  }


  printf("Starting Application\n");
  v_BRIDGE_process();
  printf("Application Exit\n");

  printf("Exit Main\n");

  if (q_daemonize == TRUE)
  {
     if (sn_log_file >= 0)
     {
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        close(sn_log_file);
     }
  }

  return EXIT_SUCCESS;
}

Upvotes: 0

Views: 1284

Answers (1)

abligh
abligh

Reputation: 25139

After daemonizing and doing the dup2 bit and setting up stdout and stderr correctly, you run into this bit of code:

if (q_daemonize == TRUE)
  {
     if (sn_log_file >= 0)
     {
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        close(sn_log_file);
     }
  }

which promptly closes the file descriptors you've been so careful to attach to your log file with dup2.

I'm presuming the purpose here is clear-up. Firstly, you can just delete this, as a process exiting will clean up its own FDs. Secondly, this is causing a problem as your printf statement above will not have been flushed to the file descriptor for stdout as stdio is buffered. If you fflush stdout, it will probably work, but the better strategy is simply to exit and let stdio's own exit handlers close the file.

Upvotes: 1

Related Questions