Live data from Hacker News

fork() can fail

rachelbythebay.com

61–70 of 320 posts

Re: fork() can fail

#61
post #14

Earlier quoted context omitted.

When you see chdir, or any notion of the current working directory being used for anything: run as fast as you can. (or refactor if it's not too late). Things I've seen because of software relying on it.. Sometimes it's just directories/files it creates popping up all over the place, sometimes it's 'just' crashing, but yes sometimes it starts to erase and all hell really breaks loose.

If you can't rely on current working directories then you have to specify any file locations absolutely? That doesn't seem like a good idea because then your code quickly turns into a hot mess if you ever have to change where stuff lives. This is such a stupid problem I run into a lot. Both alternatives (doing things with absolute paths vs doing things entirely with relative paths) seem to have a lot of downsides. Ov…

As agwa and I mentioned in sibling comments, there are the ...at() functions, which let you specify actions on paths relative to a specific directory you have a file descriptor for. This not only avoids issues like the above (failing to open the directory and then failing to check for failure will mean you're passing -1 into unlinkat, which would simply fail) but will also keep you talking about the same place if links are moved around somewhere up the tree from where you are working.

Re: fork() can fail

#62
post #57
post #7

This reminds me of one of the most epic bugs I've ever run into: mkdir("/foo", 0700); chdir("/foo"); recursively_delete_everything_in_current_directory(); Running as root, this usually worked fine: It would create a directory, move into it, and clean out any garbage left behind by a previous run before doing anything new. Running as non-root, the mkdir failed, the chdir failed, and it started eating my home directory…

Could you have not just checked to see if you actually created the directory and/or check to make sure you moved into the directory before proceeding with your destructive function? (Defensive Programming 101 really).

They could have, but then they wouldn't have a great 'epic bug' story to share! Missing the basics is part of what leads to mistakes like this, and I'd wager that after getting bit by that they are much more careful today.

Also, don't rely on implicit state (the "current directory") for a destructive command, pass the dependency in:

recursively_delete_directory("/foo")

Re: fork() can fail

#63
post #14

Earlier quoted context omitted.

When you see chdir, or any notion of the current working directory being used for anything: run as fast as you can. (or refactor if it's not too late). Things I've seen because of software relying on it.. Sometimes it's just directories/files it creates popping up all over the place, sometimes it's 'just' crashing, but yes sometimes it starts to erase and all hell really breaks loose.

The real problem with chdir is when that code ends up refactored into a library and ends up used in a multithreaded program. Then you've got an ugly bug.

That's yet another real problem with chdir, on top of the 10 other real problems with chdir, of which we've mentioned a couple here.

Re: fork() can fail

#64

Earlier quoted context omitted.

Yep. For that problem, there's vfork.

Which is great, albeit easy to use wrong; but it's not portable, unfortunately.

It's portable enough: Linux, Darwin, and the BSDs all support it. Darwin also supports posix_spawn natively. Even Cygwin supports it, although Cygwin's vfork is currently just an alias for fork.

Re: fork() can fail

#65
post #51

Earlier quoted context omitted.

This isn't really fork() failing per se -- but rather a failed program/script that did not understand the well defined and clearly documented behavior of fork().

The man page says, "On failure, -1 is returned in the parent, no process is created, and errno is set appropriately." So if fork is behaving as documented, returning -1 is because of "fork failing".

True -- I guess fork() has failed at that point. I was more getting at the article's authors scenarios of careless scripts treating -1 as a valid pid (which should always be > 0), which would be a failure of the script instead.

Re: fork() can fail

#66
post #20

If a function be advertised to return an error code in the event of difficulties, thou shalt check for that code, yea, even though the checks triple the size of thy code and produce aches in thy typing fingers, for if thou thinkest "it cannot happen to me", the gods shall surely punish thee for thy arrogance. [0] [0]: http://www.lysator.liu.se/c/ten-commandments.html

Counterexample: pthread_mutex_unlock. That function returns an error code, but it cannot possibly fail in a well-formed program. Checking for an error for mutex unlock is pointless: what would you do in response?

Re: fork() can fail

#67
post #29
post #7

This reminds me of one of the most epic bugs I've ever run into: mkdir("/foo", 0700); chdir("/foo"); recursively_delete_everything_in_current_directory(); Running as root, this usually worked fine: It would create a directory, move into it, and clean out any garbage left behind by a previous run before doing anything new. Running as non-root, the mkdir failed, the chdir failed, and it started eating my home directory…

In those times I wish I could use the emacs lisp way: (let (dir "/foo") (create-directory dir) (with-current-directory dir (delete-all-files-recursively))) Factor recognized the value of dynamically scoped variables: http://concatenative.org/wiki/view/Factor/FAQ/What's%20Facto... A lot of code became much simpler because of that decision.

  $ mkdir /tmp/foo && cd /tmp/foo && touch bar.txt

Re: fork() can fail

#68
post #57

Earlier quoted context omitted.

Could you have not just checked to see if you actually created the directory and/or check to make sure you moved into the directory before proceeding with your destructive function? (Defensive Programming 101 really).

They could have, but then they wouldn't have a great 'epic bug' story to share! Missing the basics is part of what leads to mistakes like this, and I'd wager that after getting bit by that they are much more careful today. Also, don't rely on implicit state (the "current directory") for a destructive command, pass the dependency in: recursively_delete_directory("/foo")

Very true.

Reminds me of a time when I was working on a package system for an in-house linux os build and carelessly had my fakeroot directory set wrong in my configurations, which ended up treating my local root / directory as the root of the fakeroot, which is as bad as it sounds. Running the script over-wrote my entire /etc directory among other important and un-recoverable things...

Gladly, it was a development system so nothing crucial was lost. Needless to say, I am way more careful today in-part due to this mishap (and hours of setting up a new dev system!)

Re: fork() can fail

#69
post #51
post #29

Earlier quoted context omitted.

In those times I wish I could use the emacs lisp way: (let (dir "/foo") (create-directory dir) (with-current-directory dir (delete-all-files-recursively))) Factor recognized the value of dynamically scoped variables: http://concatenative.org/wiki/view/Factor/FAQ/What's%20Facto... A lot of code became much simpler because of that decision.

This isn't really fork() failing per se -- but rather a failed program/script that did not understand the well defined and clearly documented behavior of fork().

Psst - it's "per se"...

Re: fork() can fail

#70
post #65

Earlier quoted context omitted.

The man page says, "On failure, -1 is returned in the parent, no process is created, and errno is set appropriately." So if fork is behaving as documented, returning -1 is because of "fork failing".

True -- I guess fork() has failed at that point. I was more getting at the article's authors scenarios of careless scripts treating -1 as a valid pid (which should always be > 0), which would be a failure of the script instead.

Well, it's a failure of the script and the POSIX API - it is unfortunate that a pid_t inhabited by -1 means "failure" in one case and "everything" in another. It is certainly not fork, narrowly, to blame.
Post reply on HN