Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to check if a stdout is closed

Tags:

c

unix

I got some 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 conditional is toggled to zero, but if I pipe the output like

./a.out |head -n10 >dumped

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

Thanks

like image 629
monkeyking Avatar asked Nov 16 '11 16:11

monkeyking


2 Answers

Your stdout hasn't been closed, so checking for that will be useless. Your program has received a SIGPIPE and exited. A SIGPIPE is delivered whenever your program writes to a pipe on which there are no readers. In your example, that happens when head exits, closing its stdin.

You should ignore SIGPIPE if you want your program to continue. This code will ignore SIGPIPE:

(void)signal(SIGPIPE, SIG_IGN);

If you don't want to modify your program, you can arrange that something continues to read from the pipe, even after head closes its input. 1

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

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

like image 191
Robᵩ Avatar answered Oct 06 '22 18:10

Robᵩ


It is closed by killing the process with SIGPIPE.

If you want to go on when your output is being ignored, then set up a SIG_IGN handler for SIGPIPE, and handle the error from the fprintf (which will be delayed by buffering, so you cannot assume data that has been written has actually reached the user).

like image 27
Simon Richter Avatar answered Oct 06 '22 19:10

Simon Richter