C/C++ How to catch errors when writing in C [popen() issue]

OP
PMc

PMc

No problem from my side. My issue is solved, bottomline: there is no reliable error reporting for writes to a pipe, and the program itself may disappear seemingly at random. The only hint is then a returncode 141 (128 + SIGPIPE). So when a more verbose message is desired, one has to catch SIGPIPE - which is the most simple solution for the problem, and works (maybe somewhat late due to buffering, but the lastest at pclose()).
Lots of more complex approaches are possible, and there are lots of opinions about them. Have fun. ;)
 
Jose I think it boils down to implementation. Solaris, down at the kernel level has been fully preemptible for a while, lots of work winds up on what I'll call "kernel threads". Device interrupts, instead of running in the context of the current thread/process would do minimal work to service hardware then queue that work up. The queued work winds up getting done by a thread of some sort.
I think a lot of FreeBSD has migrated to similar patterns (see the grand bikesheds with Matt Dillion around the 4.x to 5.x transition).
I have heard that the Solaris thread implementation was the gold standard, but I didn't get to use it much, unfortunately. I'm a Java puke from a long time back. Ironically, the early JVMs only ran on Windows, and even after there was a Solaris version, it was far less performant than the Windows version. Windows threads are another thing altogether, too. I think I remember they're fairly lightweight, but it's been a long time.

Threads at/up to the user level I think become a different story. User programs inherently block, waiting on something a lot of time. Wait for something on a socket before they do something (pretty much every webserver out there, no?), then after they are done, they go back and wait for more. So I think "user threads" wind up being a bit heavier than kernel threads simply because they have to carry a lot more context with them.
I think the original motivation for threads was GUIs. You have multiple windows doing different things and potentially depending of what's going on in a different window, and having to respond to arbitrary events coming from user clicks and such.
"Interprocess communications" or talking with another thread, a lot I think depends on what the communications is.
Look at a pipe: effectively socket communications. Thread 1 writes to a socket, Thread 2 reads from the socket. The kernel can arbitrate between the two threads. Reader doesn't unblock until Writer has completed a write.
...
Multiple threads, yes you can get it wrong very quickly and wind up losing at the end (performance), but properly designed software utilizing threads is not inherently bad.
This is another reason why threads are on the outs (the other being the fact that they're not as lightweight as advertised.) Turns out it's hard to get locking right, and the race conditions, deadlocks, etc. that you can cause with threads can be nasty to troubleshoot.
 
  • Like
Reactions: mer

zirias@

Developer
No problem from my side. My issue is solved, bottomline: there is no reliable error reporting for writes to a pipe, and the program itself may disappear seemingly at random. The only hint is then a returncode 141 (128 + SIGPIPE). So when a more verbose message is desired, one has to catch SIGPIPE - which is the most simple solution for the problem, and works (maybe somewhat late due to buffering, but the lastest at pclose()).
Lots of more complex approaches are possible, and there are lots of opinions about them. Have fun. ;)
This is a very weird response. I literally explained you the program does not "disappear at random". It receives a SIGPIPE, and the default handling of that signal is termination.

I also don't see what you mean by "lots of opinions". Yes, you can handle SIGPIPE, and you should be aware this is the only thing you can ever get from the OS by design, and when you will get it (might even be "never" if you just stop writing soon enough) depends on an implementation detail: the size of the pipe buffer. So, that's not a good way to handle the error, and I'm pretty sure that's not an opinion but general agreement about good software design: handle errors where they occur, don't handle symptoms that might hit you some undefined time later.
 
OP
PMc

PMc

This is a very weird response. I literally explained you the program does not "disappear at random".
Yeah, thank You for the explanation. Anyway, I prefer to base my decisions on observed reality, rather than on arguments about how reality might be perceived.
The observed reality is that there are (at least) two cases:
  • we write a small amount of data, it fits into the buffer, pclose() cannot deliver the buffer and returns with error. We can recognize this and report the proper whereabouts of the failure
  • we write a large amount of data and get killed. If then nobody bothers to collect the distinct returncode, we can at best notice that the program has disappeared - for some yet unknown reason (at the place of the observer). This is the "bad thing".
Which of the two cases apply, depends on external factors, i.e. it is random (at the place of the observer).

Yes, you can handle SIGPIPE, and you should be aware this is the only thing you can ever get from the OS by design, and when you will get it (might even be "never" if you just stop writing soon enough) depends on an implementation detail: the size of the pipe buffer.
"never" is not the case. pclose() will either return an error, or the signal will be delivered (or both); it cannot return successfully.

So, that's not a good way to handle the error
Anything else, like monitoring SIGCHLD or whatever, translates for me to "babysit other parties' business", and such does not happen here (because it usually unfolds to a neverending approach). I usually believe that the other parties do as good as they can, so to recognize there mere fact and location of a mishap should be enough.
 

zirias@

Developer
Ok, I seriously regret now that I tried to help. And no, pclose() doesn't fail because of "failed" writes to a pipe, it just returns the exit status of the shell, which is of course a failure status if it couldn't execute any command.

But it seems you prefer to "jump to conclusions" and think POSIX works the way you personally assume, ignoring e.g. manpages:
pclose() cannot deliver the buffer and returns with error.
 
OP
PMc

PMc

Ok, I seriously regret now that I tried to help.
Too bad. But Your idea was that popen() is the problem, which it apparently isn't.
And no, pclose() doesn't fail because of "failed" writes to a pipe, it just returns the exit status of the shell, which is of course a failure status if it couldn't execute any command.
That's good enough for me.
 

zirias@

Developer
But Your idea was that popen() is the problem, which it apparently isn't.
Not sure whether you don't understand or you don't want to understand. Of course it is the problem.*) It leaves you no control whatsoever necessary to get the interesting error conditions, like, for example, failure to even start your external program. This kind of stubbornness is just plain ridiculous.

*) edit, my exact wording was "popen() isn't the only issue here", which in the context means, you have to do more than just replace popen() in order to handle every possible error condition correctly. Still the first thing you have to do is to get rid of popen().
 
Top