3 ms·
> the behavior is clearly documented Disagree - the unfortunate interaction with kill is not clearly documented. Do you implement error checking when calling
by MaulingMonkey 7y ago
> the behavior is clearly documented
Disagree - the unfortunate interaction with kill is not clearly documented.
Do you implement error checking when calling printf, unlike every C codebase I've ever encountered which uses it? If not, you've implicitly acknowledged some error cases just aren't worth handling, or useful to handle. The question is then - when is it important?
PSAs like this one make it clear where the documentation may not have: Error handling fork() is important, and unlike error handling malloc where free(nullptr)ing later is a safe noop, kill(-1)ing later is an unsafe hazard that must be avoided. Additionally, it's frequently the case that the documentation is poor and would not help you even when you do bother to read it. Here's me previously ranting that the vast majority of documentation about atoi fail to clearly and adequately call out that atoi("a") is undefined behavior and citing my sources: https://news.ycombinator.com/item?id=14861447 https://news.ycombinator.com/item?id=14861447
> so how could someone fall under the impression that this wasn't the case?
Continuing past my atoi example...
Maybe they looked at alternative, poorer documentation. Maybe they looked at poor example code that didn't bother with error handling. Maybe they looked at decent documentation that failed to adequately stress the importance of error checking (EDIT: I'd argue this includes your wikipedia example). Hell, maybe they looked at great documentation - about a specific platform's implementation of fork, which perhaps makes fork() failing fatal to the calling process and thus "infalliable". Maybe they looked at the documentation for their favorite language's wrapper of fork, which throws an exception instead.
Maybe they didn't look at the documentation at all.
Maybe they learned of fork through word of mouth when the internet was down on a system without manpages. "Can fork ever fail?" "Hmm... I've never seen it fail." "Good enough for me!"
Perhaps this lack of knowledge can only come about by foolishness - but human nature and statistics mean at least one of your generally smart coworkers has probably fallen prey to such foolishness.
- wahern 7y ago> Do you implement error checking when calling printf, unlike every C codebase I've ever encountered which uses it? There's a reason that Unix sends EPIPE to a process when writing to a broken pipe, and why the default handler for SIGPIPE is to terminate the process. Interestingly, the Rust runtime blocks SIGPIPE, which was a naive and dumb thing to do [1], but which is now impossible to undo. Similarly, in C the fail flag for FILE objects is persistent to permit alternative error management strategies. This is even carried over into Go, AFAIU. Basically, it's okay to leave a series of I/O statements unchecked so long as you check at the end of the block or transaction, or at the very least at close time. The printf case is a bad example because the inconvenience of checking for failure on every call has already been accounted for. I don't think I've ever seen C code that fails to check fork for an error condition, though I'm usually only ever reading my code and the code of widely used open source projects. [1] Considering how much Rust touts the ease of FFI and integration with C and C++ projects.
- tedunangst 7y agoFWIW the go runtime ignores sigpipe on sockets, but not stdout.
- MaulingMonkey 7y ago> There's a reason that Unix sends EPIPE to a process when writing to a broken pipe, and why the default handler for SIGPIPE is to terminate the process. As an author and consumer of cross platform software I can't rely on that - no SIGPIPE on windows - not to mention it's a pretty coarse hammer. Return value + errno is the way to go if I actually care about the exact behavior. One can wrap the call and panic/abort/terminate, but most people don't bother to do that, nor can I particularly blame them for not bothering (especially when I generally don't either.) > I don't think I've ever seen C code that fails to check fork for an error condition, though I'm usually only ever reading my code and the code of widely used open source projects. I'd be curious if git blame shows they had that error handling from day 1, or if it was generally added in response to heisenbugs. My money is on the latter, but perhaps you're generally exposed to better codebases than I am.
- wahern 7y ago> As an author and consumer of cross platform software I can't rely on that - no SIGPIPE on windows - not to mention it's a pretty coarse hammer. But shell programming and process pipelines aren't common on Windows. Rust shouldn't have changed the default behavior. SIGPIPE serves a critical role on Unix by ensuring that processes don't keep running when their consumers disappear. > Return value + errno is the way to go if I actually care about the exact behavior. One can wrap the call and panic/abort/terminate, but most people don't bother to do that, nor can I particularly blame them for not bothering (especially when I generally don't either.) Fortunately in Rust you're usually forced to handle the failure condition. The problem is with FFI to existing libraries that implicitly rely on default Unix semantics. > I'd be curious if git blame shows they had that error handling from day 1, or if it was generally added in response to heisenbugs. My money is on the latter, but perhaps you're generally exposed to better codebases than I am. Admittedly, I don't hang in the "I copied this code from Stack Exchange" or "IDE code completion is essential" crowds. When programming in C I always have the POSIX and C standards handy, even though I've memorized much of it already. I try to do the same for other languages, to the extent it's possible. Someone else linked to an earlier comment of theirs where they complained that the POSIX spec for fork was only the 8th hit on Google. Perhaps their problem was having a habit of Googling the usage for a core Unix API rather than using the freely available and eminently readable specs, which can be kept locally. I have well over USD $1000 of ISO specifications on my hard drive, and as far as specifications go the POSIX and C specifications stand out for their concision and clarity. This is true even when pitting them against the documentation for languages like Perl, Python, Go, or Rust.