Live data from Hacker News

Moving beyond fork() + exec()

lwn.net

261–270 of 358 posts

Re: Moving beyond fork() + exec()

#261
post #198

Earlier quoted context omitted.

I don't think fork() mandates overcommit. OpenBSD doesn't seem to even allow overcommit or have an OOM killer, memory allocations that exceed available capacity fail immediately even if the memory is not touched.

Let's say you have 1GB RAM. You're running program that occupies 600 MB. Now this program wants to launch second small program that occupies 1 MB. You're doing fork + exec. If you're overcommiting, fork will not reserve another 600 MB, and exec immediately after fork will cause total system usage to be 601 MB. If you're not overcommiting, that fork will fail, because total memory consumption will be 1200 MB which is…

I think that on Unixes without overcommit, people allocate massive amounts of swap so that fork never fails.

Re: Moving beyond fork() + exec()

#262

Earlier quoted context omitted.

Yeah this seems like a promising discussion.

It has been for decades at this point. thiago's blog posts which introduced me to the topic over a decade ago (and is still one of the best explainers) points out that posix_spawn was introduced in POSIX.1-2001: https://web.archive.org/web/20120718152158/http://www.maciei...

Yeah fair enough.

Re: Moving beyond fork() + exec()

#263
post #253

Earlier quoted context omitted.

Why not?

Because it comes with a lot of overhead and, unless for some reason you really need every of those processes to have their own address space, set of privileges, file descriptors, etc., there's no point in wasting resources repeatedly setting those up only to tear them down milliseconds later. Running the same workloads in an nginx-style process pool usually works better.

I see what you mean now. I agree, a sustained workload of creating many processes very quickly is probably not a great idea. But it's also useful to be able to spawn that process pool (and any number of other use cases like that) efficiently.

Re: Moving beyond fork() + exec()

#264
post #254
post #66

Earlier quoted context omitted.

Should bash link in every program the user might want? Load them up as dynamic libraries?

Node, Python, PowerShell, and the rest do (almost) just that. launchd and systemd famously strived to remove as much shell from the start up process as possible because it was harming boot times and introducing unpredictability.

I don't know Node or PowerShell very well, but I'm not sure what you mean by this with respect to Python.

Re: Moving beyond fork() + exec()

#265
post #26

The elegance of the fork() + exec() model is that every kind of configuration can be done after the fork using all the usual APIs. Every attempt to replace it with a combined call that I have seen so far seemed fundamentally poorer because it needs to add all configuration options as parameters to the call and then do this in away that you can extend it later and does not become a mess.

I agree with it, although still the fork is expensive like they mention. There is clone with some flags, although that does not really solve it.

I think one problem is that it is already how it is; making an entirely new operating system (that is not Linux, not GNU, and not POSIX) would solve it, but that is not the case here, so it would need to be done as it is.

One possibility would be a new function that creates a new empty child process, but the parent process specifies what system calls the child process executes, and can stop if specifying that exec or exit is (successfully) called by the child process, or if the parent process gives it the program memory to execute directly instead of using a file (since that use is also useful). The new function can still have some of the clone flags available. (I don't actually know how much better it would work.)

There are other possibilities as well.

The existing methods can also remain available for when they are helpful, but functions such as popen might be changed to use the new method.

Re: Moving beyond fork() + exec()

#266
post #172

Earlier quoted context omitted.

> The things you can do between fork and exec are sometimes underestimated. Off the top of my head, you can call dup2(), you can set a process group id, probably a few other things. What do you mean underestimated? You can do anything between fork and exec; there are no limitations.

That's not true. Just one example, if you do anything with threads you are pretty screwed. For example if another thread holds a mutex at the time of fork(2), and you also want that mutex.

Did you mean over-estimated?

Re: Moving beyond fork() + exec()

#267

I just ran into this recently, where I had an obscure bug caused by needing to close more file descriptors in the forked process. "I want a clone of the current process" is just way less common in my experience than "I want a completely new process". It feels crazy that we don't have a way to directly express the latter thing, and can only approximate it by cloning and then fixing things up in post.

[deleted]

Re: Moving beyond fork() + exec()

#268
post #198

Earlier quoted context omitted.

I don't think fork() mandates overcommit. OpenBSD doesn't seem to even allow overcommit or have an OOM killer, memory allocations that exceed available capacity fail immediately even if the memory is not touched.

Let's say you have 1GB RAM. You're running program that occupies 600 MB. Now this program wants to launch second small program that occupies 1 MB. You're doing fork + exec. If you're overcommiting, fork will not reserve another 600 MB, and exec immediately after fork will cause total system usage to be 601 MB. If you're not overcommiting, that fork will fail, because total memory consumption will be 1200 MB which is…

> If you're not overcommiting, that fork will fail, because total memory consumption will be 1200 MB which is more than 1GB. That somewhat restricts program design.

Does this accounting apply to vfork as well?

Re: Moving beyond fork() + exec()

#269
post #186
post #69

Earlier quoted context omitted.

Even with copy-on-write, fork() still has to pay the setup cost for COW. If the parent process has a lot of busy threads (e.g. Java), you can end up doing a lot of unnecessary COW before exec() fires.

Isn't that what vfork tried to address? No COW, the child starts in its parents address space and only gets its own after calling exec.

Yes, the next sentence in TFA is:

> Attempts (such as vfork()) have been made over the years to optimize for this case, but the pattern still is more expensive than it could be.

Basically vfork do a "stop the world".

Re: Moving beyond fork() + exec()

#270
post #65

Earlier quoted context omitted.

Fork/exec is great if you actually want the traditional copy of your process for some reason. For launching something totally new, like the example in the article of some tool calling git, I think it does make a ton of sense to make something new. Especially since I suspect that is by far the more common case. I suspect “I want a clone of me“ is relatively rarely used at this point.

Relatively rarely, but in some performance sensitive use cases. Mine happens to be fuzzers, where a very cheap fork-like primitive would be a really big win.

Android and chrome both benefit greatly from fork exec as part of their zygote model iirc. It substantially reduces the memory cost and latency of spawning new apps and tabs.
Post reply on HN