Live data from Hacker News

fork() can fail

rachelbythebay.com

311–320 of 320 posts

Re: fork() can fail

#311
Is there a test command that asks the operating system to run a program but cause the nth fork to fail? I would be more diligent about writing code that handles rare errors if I could create test cases. Writing code that I cannot test feels wrong.

Re: fork() can fail

#312
post #292

Earlier quoted context omitted.

Yeah --- but at least it's fairly obvious how to add platform-specific extensions that won't conflict with future standards.

And extensions to let us specify failure-case or other behavior of those extensions, and so on. But at that point, we're already heading down the road of implementing a tiny DSL for "the program that posix_spawn() should run after creating the new process but before exec()ing the new executable". Why not simply write that code in the host language? You could specify a thunk of code to be sent to the new process and e…

Yes, you end up with a tiny DSL for specifying transformations to make to a child process: they key difference is that the kernel can execute this DSL much more efficiently than it can code written in the host language: fork closes over the entire world, and posix_spawn doesn't have to do that.

Re: fork() can fail

#313
post #202

Earlier quoted context omitted.

I wonder if it would be worthwhile to forego the notion of a CWD for processes entirely.

You'd have to use absolute paths everywhere, but that probably doesn't hurt that much in programs or scripts. The CWD seems most useful in interactive shells, I guess. A fun thing is PowerShell on Windows where you have two CWDs, one from the process and another one from the shell which had is own VFS handling (e.g. the registry is a place that has no representation in the normal file system). Cmdlets use one of them…

> You'd have to use absolute paths everywhere

Ever heard of PATH_MAX and ENAMETOOLONG? You will if you're using absolute paths everywhere. Sigh

Re: fork() can fail

#314

Earlier quoted context omitted.

Exceptions disrupt the program flow at any place, including constructors and destructors. It's not easy to guarantee that you deallocate on destructors exactly the resources that were allocated at the constructor when both of them can stop their execution at any time. Finally clauses are technically enough, but each allocation needs the same level of attention non-memory resources (e.g. connections, files) get on oth…

I'm going to answer for C++, since as far as I know it's the only major language with exceptions and RAII. Correct me if I'm misunderstanding your post. > It's not easy to guarantee that you deallocate on destructors exactly the resources that were allocated at the constructor when both of them can stop their execution at any time. I disagree; let's take this one case at time to keep it simple: 1. Destructors: within…

"It is idiomatic C++ that a destructor should not throw;...which is practically guaranteed to be exception-free..."

"Should not", "practically". Your confidence is overwhelming. :-)

Exception safety in C++ may not be quite as much of a black art as it once was (say, before std::unique_ptr), but it is still something the programmer has to do, actively.

"If releasing a resource cannot fail, destructors (and finally clauses in languages lacking RAII-style resource management) cannot fail."

Yupper.

I'm probably unqualified to have an opinion on this, but I believe that the entire hatred for checked exceptions in Java comes from that general piece of idiocy and specifically from JDBC's urge to possibly throw a SQLException from close(). (Just what the hell is anyone supposed to do with that?)

Re: fork() can fail

#315
post #209

When I was young and really didn't understand Unix, my friend and were summer students at NBS (now NIST), and one fine afternoon we wondered what would happen if you ran fork() forever. We didn't know, so we wrote the program and ran it. This was on a PDP-11/45 running v6 or v7 Unix. The printing console (some DECWriter 133 something or other) started burping and spewing stuff about fork failing and other bad things,…

For several years I was a sysadmin for the University of Texas computer sciences department. (This was much later than your story, though.) If I remember correctly, the operating systems class was usually taught in the spring and they got to exploring processes sometime in late March or early April. And for about two weeks, none of our generally available systems would have an uptime of more than a couple of days.

Sure, you could get in and kill a fork-bomb before it did anything bad. But two or three on the same machine? And when you've got a couple hundred machines? It was easier to just reboot and let the victims who were inconvenienced handle explaining to the guilty how what they did was bad.

Then there were the guys who would log into one machine in a lab, fork-bomb it, move to the next machine over and make a change to their program, fork-bomb that machine, and expect to iterate that process until they passed the assignment. Leaving a wake of pitifully flailing workstations behind. Ahh, good times.

Re: fork() can fail

#316
If you have set a non-root user's process limits correctly, sending SIGKILL to all of that user's processes is likely a perfectly fine response to their fork() failing.

If you haven't limited the number of processes a given non-root user can start to some value the machine can handle, sending SIGKILL to all of the user's processes is probably not going to do anymore damage.

If a program running as root doesn't correctly handle fork() failing, someone needs to be taken out back and beaten with a stick. Maybe the person who wrote the program, maybe the person who ran it as root. But somebody.

Re: fork() can fail

#317

Earlier quoted context omitted.

Not after exit(0) returns, no. Instead, you're going to want it after some programmer removes exit(0) six months from now.

smart-ass comment: you should put two breaks in for when some programmer removes one of them six months from now. ;) edit: i know it's not totally analogous since removing the exit and not noticing there's no break is a lot more likely than just randomly removing a break, but the "let's prevent someone clumsy from screwing this code up in the future" argument always makes me laugh a little.

Of course, you can always take it too far. Two breaks is too far, obviously (I'm pretty sure you agree with me on that).

Is a break after an exit too far? It may well be, but it's less clearly too far than two breaks are.

Re: fork() can fail

#318

Earlier quoted context omitted.

You can criticise both, and more importantly criticise C for its inability to create sensible APIs: in a good design, fork() would have exclusive domains for a PID, an Error and a Child result and you couldn't confuse an error for a pid.

> criticise C for its inability to create sensible APIs Where in the C manual is kill() described again?

[deleted]

Re: fork() can fail

#319
post #209

When I was young and really didn't understand Unix, my friend and were summer students at NBS (now NIST), and one fine afternoon we wondered what would happen if you ran fork() forever. We didn't know, so we wrote the program and ran it. This was on a PDP-11/45 running v6 or v7 Unix. The printing console (some DECWriter 133 something or other) started burping and spewing stuff about fork failing and other bad things,…

"which he had to repair by hand with ncheck and icheck, because this was before the days of fsck and that's what real programmers did"

No, real programmers were writing fsck.

:)

Re: fork() can fail

#320

Earlier quoted context omitted.

You're missing my point. It's not about undefined state -- it's about sane defaults and APIs that make things that crashes/bad things harder to achieve. Kill's -1 is an example of this -- having a separate killall api is defaulting to a non-fatal situation. Apple's UITableView's is another -- it's so easy for them to rebuild themselves yet instead it crashes on an inconsistency.

If a developer fails to check the return value of a function that can fail, all bets are off. There is no sane default that can safely hide a developer mistake. Granted, the specific kill() API could have been designed better, but since it's very well established by decades of history, the burden of understanding it lies with the developer.

Because nothing ever changes with computers over time? You're being myopic. It's not about fork->kill. It's about how computers work in general, and why this 'blame the programmer' mindset is just dumb.

As you admitted, the API could have been designed better. That's my point. Things that break things for users, especially those that take down entire systems, should be difficult or require more awareness to do, such as by naming it killall() like suggested in this thread. The human factors approach recognizes that operators aka programmers aka humans will not just make errors, but predictability so. We can incorporate those predictions into our domain and change design patterns to match.

There are many known patterns of errors that programmers make: edge case errors such as off-by-one, null dereferencing, etc.

Using the return value from a function is a common pattern generally. Having a return value that mixes an actual result (PID) along with an error code (-1) is problematic in that they're both integers so there's no obvious handler for the error case, and thus this cascade can happen. Then you add the fact that fork() rarely fails and that compounds the issue in hiding it into obscurity.

Generally when a system is maxed out of resources all kinds of things break and fail in weird ways; it just so happened that this particular cascade was super bad and needlessly so because of API design choices that have never been addressed.

Post reply on HN