I don't use fork() that often, but my own paranoia is why I always test for <= 0 instead of == 0. Some people think I'm weird for doing something like:
if len(some_list) <= 0:
# Test for empty list
But it's just my way of covering my ass in case the laws of physics change during execution, or just in case weird bugs exist like those found in this article.
Careful, in many cases C will happily automatically and silently coerce unsigned values to signed values for your check if the types differ. Some functions may be actually intentionally returning numbers that large indicating success and your program might be invoking error handling code assuming a failure.
There's no good substitute for reading the RETURN VALUE(S) section the manpage for every function and testing appropriately.
If you're not sure whether len() can return -1, and in turn what that value means, then you can't know that your code is any more correct.
In fact, this is going to be worse than a equals comparison because instead of having code that clearly doesn't handle a corner case you have code that lies about what values it can correctly handle. That makes it much harder to debug.
You only need 3 cases if you need to distinguish between the parent and the child. I can imagine designs where the parent and child are both going to exec the same program and so all you need to check on the fork is for success or failure.
"Thankfully that case will never happen because you can't be a child if there was an error. :)"
Uh, no. If there is an error, there will be no child process but the parent process will think it is the child.
From the fork man page, emphasis mine: "On success, the PID of the child process is returned in the parent, and 0 is returned in the child."
"Also the check as presumably written would never miss an error, it would just potentially assume valid return values were also errors."
That was already discussed as a possibility; I was addressing the other. In the case you describe the software would never work at all, even when fork successfully forks, because the child will always think there was an error and presumably fall over rather than getting things done. That's probably the better case, in terms of development progress, because it would be spotted and fixed right away. But hopefully fixed correctly, and not converted to the broken-but-working-when-fork-succeeds other variant that also uses "<= 0".
> just in case weird bugs exist like those found in this article
The article does not describe weird bugs - the behaviour it describes in fork() and kill() are by design, and well-documented. The real lesson here is to RTFM and understand what return values you get under what circumstances.