BlueBird BlueBird - 26 days ago 8
C Question

error in executing system function with STDOUT_FILENO closed

I have an strange issue. I am not very good in C language. I am trying to create a daemon to execute my bash script based service in Linux. To make it easy I have made the code simple. Below is my code.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>

int main(int argc, char* argv[])
{
pid_t process_id = 0;
pid_t sid = 0;
process_id = fork();
if (process_id < 0)
{
printf("fork failed!\n");
exit(1);
}
if (process_id > 0)
{
printf("daemon creatd with process id %d \n", process_id);
exit(0);
}

umask(0);
sid = setsid();
if(sid < 0)
{
fprintf(stderr, "Return error\n");
exit(1);
}

chdir("/");
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);



int status = system("ls");

openlog("slog", LOG_PID|LOG_CONS, LOG_USER);
syslog(LOG_INFO, "Returned status is %d", status);
closelog();

return (0);
}


As you can see, the above program will execute the
system
function to execute the
ls
command and output the exit code to system log.

After I compile the program and run, in the logs I can see the status code is 512. But If I comment out the following line,

close(STDOUT_FILENO);


then it works perfect and I can see in the log the status code is 0,

What I might be doing wrong?

UPDATE

My program is pretty big and I am not using
ls
in real environment. i made the program simple to reproduce the issue what I am facing. Also, to see the status of program, I am not looking at the output but the status code in the syslog.

Answer

In case it is not clear from other comments and answers, ls writes its output to stdout. If it can not write to stdout it terminates and (apparently) sets an status code of 512 (non-zero in any case).

The child process will inherit stdout from the parent, so if you do not close stdout in the parent, the child will have a stdout to write to and the command will succeed. If you close stdout, then the child has nowhere to write its output and the error occurs.

So, although ls is just an example for this question, your actual child process is writing to stdout which results in the same problem.

The simplest way around this, and assuming that you do not want the child's output, is to redirect the child's stdout on the command line:

int status = system("ls >/dev/null 2>&1");

This will redirect stdout and stderr to /dev/null, effectively throwing away the child's output while still giving it somewhere to write to.

Comments