1

I have a pipe which I opened with FILE *telnet = popen("telnet server", "w". If telnet exits after a while because server is not found, the pipe is closed from the other extreme.

Then I would expect some error, either in fprintf(telnet, ...) or fflush(telnet) calls, but instead, my program suddenly dies at fflush(telnet) without reporting the error. Is this normal behaviour? Why is it?

  • Does your program check the return value of `fflush` and print an error when appropriate? If not, then failing to print an error message is "normal behavior". – William Pursell Feb 27 '20 at 21:37
  • I check fprintf is returning >= 0. fflush() is returning 0 before telnet exits, and after telnet exits a call to fflush() simply doesn't return (I have `printf("c\n"); if (fflush(telnet)) {printf("a\n"); getchar(); return -1;} printf("b\n"); getchar();`, and only `c` gets printed); it acts as if exit() was called instead. – alx - recommends codidact Feb 27 '20 at 21:43
  • 3
    Are you getting a `SIGPIPE`? – William Pursell Feb 27 '20 at 21:45
  • 3
    If you write to a pipe when there's no process at the other end of the pipe to read the data, you get a SIGPIPE signal to let you know, and the default behaviour for SIGPIPE is to exit (no core dump, but exit with prejudice). You can set the handler to `SIG_IGN` in which case your writing operation should fail with an error, rather than terminating. Or you can set up more elaborate signal handling. – Jonathan Leffler Feb 27 '20 at 21:47
  • @WilliamPursell Probably. I am not handling signals, so I can't know, but makes sense. The terminal doesn't show anything. – alx - recommends codidact Feb 27 '20 at 21:49
  • @JonathanLeffler If that's expected, I don't care if my program is being exited; I was just concerned that I didn't know the reason, but I'm fine with it then. – alx - recommends codidact Feb 27 '20 at 21:51
  • Or you can open the socket to the server yourself instead of going through telnet, and then you'll get errors returned from `write()` as you expect, with no need to deal with signals at all. – Nate Eldredge Feb 27 '20 at 21:52
  • @NateEldredge That was my first attempt, but libtelnet is very difficult for me to understand, and I need it working in a few days. That library doesn't have a manual or something, and the examples are very unclear to me. In the future, when I have time, I'll try to understand libtelnet to improve my program by using it and sockets, but not now. – alx - recommends codidact Feb 27 '20 at 21:55

1 Answers1

2

Converting (expanded) comments into an answer.

If you write to a pipe when there's no process at the other end of the pipe to read the data, you get a SIGPIPE signal to let you know, and the default behaviour for SIGPIPE is to exit (no core dump, but exit with prejudice).

If you examine the exit status in the shell, you should see $? is 141 (128 + SIGPIPE, which is normally 13).

If you don't mind that the process exits, you need do nothing. Alternatively, you can set the signal handler for SIGPIPE to SIG_IGN, in which case your writing operation should fail with an error, rather than terminating the process. Or you can set up more elaborate signal handling.

Note that one of the reasons you need to be careful to close unused file descriptors from pipes is that if the current process is writing to a pipe but also has the read end of the pipe open, it won't get SIGPIPE — but it might get blocked because it can't write more information to the pipe until some process reads from the pipe, but the only process that can read from the pipe is the one that's trying to write to it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278