Live data from Hacker News

fork() can fail

rachelbythebay.com

141–150 of 320 posts

Re: fork() can fail

#141

Earlier quoted context omitted.

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 li…

Rearranging the tree above CWD isn't a problem, CWD will follow along just fine (as in, be the same directory). Also, you're assuming AT_FDCWD won't be -1, which could be reasonable but isn't guaranteed afaik.

"Rearranging the tree above CWD isn't a problem, CWD will follow along just fine (as in, be the same directory)."

I was citing rearranging the tree is a potential issue with absolute directories, not with relying on CWD - that certainly could have been clearer.

"Also, you're assuming AT_FDCWD won't be -1, which could be reasonable but isn't guaranteed afaik."

Interesting point regarding guarantees. It's not -1 on any existing OS that I can find (it seems to be -100 on Linux and FreeBSD, -3041965 on Solaris, -2 on AIX), and shouldn't be for precisely this reason, but something to bear in mind if you are working on something more obscure that nonetheless has these functions.

Of course, you shouldn't be relying on reasonable behavior from functions passed a bad FD in general. It's just nice to have the additional defense when that does get missed.

Re: fork() can fail

#142

Earlier quoted context omitted.

while(1) {fork()}; is "better", as the version you mention will quit as soon as it is able to fork a new process.

Nope, it won't quit. In failure fork returns -1, what's still true... But the forked processes will quit as soon as they are created. Thus, it won't work anyway.

Parent said as soon as it is able to fork a new process, which still isn't quite right (it's the child that quits, as you say) but not the error you seem to be responding to.

Re: fork() can fail

#143

Somewhat OT, but in the same neighborhood: Standard file handles are another thing you should not assume are there (though I'm not sure how to test for it programmatically). We once had a user that, for whatever reason, tweaked their Unix installations to not pass an open stderr to processes - they just got stdin and stdout (that is, file handles 0 and 1, but not 2). If you wrote to stderr anywhere in your program, i…

Wow that's a really wild story, but I think it's also pretty different. fork() returning -1 is defined behavior, as is true for many functions. Whereas not having stderr open defies everything about the C standard I/O. (K&R B1, 7.5 & 7.6) Note however, that strictly speaking stderr does not have to be 2. It can be any number, but it has to be whatever the include file says it is, so if you don't specify the stream as…

> Note however, that strictly speaking stderr does not have to be 2. It

Nope. On POSIX systems stderr is defined as 2:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/st...

  > The following symbolic values in  define the file descriptors
  > that shall be associated with the C-language stdin, stdout, and stderr
  > when the application is started:
  > 
  > STDIN_FILENO
  >     Standard input value, stdin. Its value is 0.
  > STDOUT_FILENO
  >     Standard output value, stdout. Its value is 1.
  > STDERR_FILENO
  >     Standard error value, stderr. Its value is 2.

Re: fork() can fail

#144
Is there any clean way to use an Option/Maybe monad in C (or C++)? It should be a simple way to solve problems where error codes are valid inputs of other functions.

The simplest way I can think of is:

    struct maybe {
        bool isEmpty;
        void* value;
    }
Although I wonder if using C++ templates, classes and operator overloading is possible to make a more practical implementation (using void* does seem like a bad idea).

Re: fork() can fail

#145

Earlier quoted context omitted.

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.

I seem to remember Cygwin having all sorts of weird problems with fork behaviour, but I'm no C programmer let alone doing stuff on Windows, so I might be remembering incorrectly

Re: fork() can fail

#146
post #107

Earlier quoted context omitted.

But in C, a 0 in a pointer context is always considered the NULL pointer (even if the physical value of a NULL pointer isn't all zeros).

Additionally in a boolean context a null pointer is indistinguishable from "false" (meaning, zero). http://c-faq.com/null/ptrtest.html For practical purposes, the null pointer and the integer `0` are one and same.

"For practical purposes, the null pointer and the integer `0` are one and same."

For most practical purposes, which is why I said that it wasn't a terrible approximation. However, they can be distinguished on some architectures:

    intptr_t x = 0;
    void *p = 0;
    
    x == *(intptr_t*)(char*)&p;
I can easily construct fantasy scenarios (involving more than a bit of Doing It Wrong) where this would be relevant. I'm not convinced it couldn't ever be relevant without Doing It Wrong, if one in fact needed to work on that kind of a system.

Re: fork() can fail

#147
post #108

Earlier quoted context omitted.

Is this just using some vague connection to ride on one of your favorite hobby horses? Or does this have a connection to the article, and I missed it?

The problem is that C and POSXIX don't (idiomatically) provide rich enough data types force checking the error condition. The fact that the error is signaled by a random integer (-1) is horrible. In a language with stronger types and richer data structures, one can have a return type that is a disjunction of {failure, parent, child}, so you can never accidentally treat a failure as a PID. In a functional language thi…

You could return a pointer or null. That would successfully force the "did it succeed" check, but of course raises questions about memory management.

Tagged union is probably the best approach. It doesn't prevent skipping the check, but it at least makes "thing I am supposed to use" different than "thing I am supposed to check".

Re: fork() can fail

#148
post #6

Quietly goes to check the last piece of C I wrote containing a fork(): if (daemon && !test_mode) { int pid = fork(); if (pid == -1) { fatal_error("Failed to fork"); } if (pid != 0) { write_pid(pid_file, pid, !test_mode); exit(0); } } else { write_pid(pid_file, getpid(), !test_mode); } Phew!

I usually use switch with fork: if (daemon && !test_mode) { int pid; switch (pid = fork()) { case -1: /* Error */ fatal_error("Failed to fork"); case 0: /* In child */ break; default: /* In parent */ write_pid(pid_file, pid, !test_mode); exit(0); } } else { write_pid(pid_file, getpid(), !test_mode); }

Somewhat pedantically, I discovered a bug where a daemon (which did this very similar code) started killing random processes. The issue turned out to be that it was test run as root once and the pid_file was owned by root, group root. So the write_pid() function failed (silently) and the cleanup script always took the pid that was in pid_file and sent it a kill 9, which was now stuck. Sometimes kill 9 would return invalid pid, sometimes it would kill some process. Fixed by removing the pid_file, letting the daemon create it, and checking that the write succeeded.

Re: fork() can fail

#149

Earlier quoted context omitted.

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.

I think the point that the author was making, outside of any criticism to the API itself, is that the hapless programmer may not know that fork() could even return -1. The article is pointing out that possibility as documented by the API, not criticizing a failure of the API. Whether or not the API is faulty in this--and I tend to agree with you--is outside of the scope of the article, though only just.

I wasn't making any particular comment on the content of the article. It was certainly relevant to the discussion tangent the thread had wandered down.

Re: fork() can fail

#150
The kill -1 behaviour seems like a bug.

Sure, it's documented, but how often is it done on purpose? It seems like something that should at least be a separate function.

Post reply on HN