How to check if stdout is closed

I have code that prints to stdout, in pseudo code it looks like

int main(){ //allocate data while(conditional){ char *string = makedata(); fprintf(stdout,"%s",string); } //cleanup } 

This works fine if the condition is switched to zero, but if I output the output, for example

 ./a.out |head -n10 >dumped 

Then the code never reaches the cleanup part, I don’t understand how to check if stdout is closed.

thanks

+6
source share
4 answers

Your stdout has not been closed, so checking for this will be useless. Your program received SIGPIPE and quit. SIGPIPE is delivered whenever your program writes to a handset on which there are no readers. In your example, this happens when the head completes, closing it with stdin.

SIGPIPE should be ignored if you want your program to continue. This code ignores SIGPIPE:

 (void)signal(SIGPIPE, SIG_IGN); 

If you do not want to change your program, you can arrange for something to continue reading from the channel, even after head closes the input. 1

 ./a.out | ( head -n10 >dumped ; cat > /dev/null ) 

1 : The shell example is valid for bash, maybe not for csh.

+5
source

It closes, killing the process with SIGPIPE .

If you want to continue when your output is ignored, configure the SIG_IGN handler for SIGPIPE and handle the error from fprintf (which will be delayed by buffering, so you cannot assume the data that was written actually reached the user).

+3
source

As Rob says in the comments on his answer, you don’t worry about stdout being closed; rather, you are worried that the other end of the pipe is closed. It may be pedantry, but it leads to a solution to your problem. Namely, you don't care if stdout is closed, but only if your printf succeeds. You should check the return value of printf: if it is -1, then the write failed.

As Simon Richter points out, you will never get printf return value unless you ignore SIGPIPE, because the result of writing to stdout when the other side of the channel was closed is that SIG_PIPE will be sent for processing. So you need to do something like:

  signal (SIGPIPE, SIG_IGN);  / * Careful: you now must check the return of * all * writes * /
   if (fprintf (stdout, ...) == -1) {
     / * handle the error * /
   }
+1
source

I have not tried this, but assuming you used the standard file descriptor for stdout, you can try fstat (1, & stat_structure) and check the return and error codes.

0
source

Source: https://habr.com/ru/post/901635/


All Articles