1. 46
  1.  

  2. 23

    I spent close to 8 weeks over winter researching an article exactly along this line, and so it was with some panic that I read this attempt at characterizing the issue. Gladly for that effort, this paper omits the majority of inseparably related considerations and relies too heavily on narrative for its conclusion.

    Fork is a nuanced beast – it most certainly is a filthy hack and I set to write (as they have) how much I hated it, but the truth isn’t quite as absolute as presented here. Fork is deeply baked into UNIX, much in the same way processed beach dirt is baked into all our CPUs. Straight removal from any particular application isn’t possible for many reasons, not least since it regularly plays a dual role as a communication mechanism (including in brand new designs like systemd) that require deep rearchitecting to remove.

    It has also deeply influenced surrounding UNIX APIs. For example, it is not possible to fully transition into a Linux container namespace without a double fork, or fully detach from a parent process on any UNIX (that I know of) without the same. Consider just that alone – how the classic daemonize() would be implemented without fork(), and what new and exotic interfaces / bending of process management rules would be needed to provide an equivalent interface. No suggestion of ‘removing’ fork is worth taking seriously without addressing problems like these.

    The UNIX incantation of fork was a hack that borrowed its name from an only slightly more formalized concept (through a series of Chinese whispers), all of which predated the actualization of, and were hopelessly inadequate at addressing the problem they set out to solve – Conway’s fork predates the arrival of contemporary SMP architecture by more than 20 years.

    1. 7

      I think it is reasonable to say, for example, all uses of fork that can be replaced by posix_spawn, should be.

      1. 7

        That doesn’t really address many of the listed complaints. The problem, as stated, is that fork requires duplicating state which makes microkernels impossible, etc. How is posix spawn defined to work?

        All process attributes, other than those influenced by the attributes set in the object referenced by attrp as specified above or by the file descriptor manipulations specified in file_actions, shall appear in the new process image as though fork() had been called to create a child process and then a member of the exec family of functions had been called by the child process to execute the new process image.

        1. 2

          For sure! That’s already pretty mandatory in many kinds of apps with huge heaps, but this paper advocated removing the OS interface entirely, i.e. resort to slow and racy emulation like Cygwin

          1. 2

            Well, the paper also pointed out that in 2016, 1304 Ubuntu packages used fork, but only 41 used posix_spawn. This is indeed an extremely sad state of affair, and I sympathize with the author that education is to blame.

            1. 4

              I suspect this is because for many classes of application fork() is actually fine, and is also a much simpler interface than posix_spawn.

              1. 2

                A lot of the criticism of “fork” is justified, but a lot also reminds me of what I saw in Linux kernel code years ago - many efforts to “clean up” code by people who did not understand the tradeoffs and had nothing valuable to contribute.

              2. 2

                glibc should just add __attribute__((deprecated)) to the declaration of fork() and we can revisit in 10 years.

                1. 3

                  and we can revisit in 10 years.

                  And see that not much has changed….

          2. 4

            Back then, there was fork on UNIX vs spawn on VMS vs language-based or thread-like that Brinch Hansen was doing. My research showed spawn did things like set privileges, allow CPU/RAM metering, etc. Basically, the kind of stuff clouds added to Linux decades later. So, at least they’d argue spawn was better. Language-based methods are coming back with less overhead and more flexibility than UNIX or VMS process model. Worse isolation but hardware attacks are making me wonder how much it matters. fork is objectively worse than many ancient and new designs. It’s legacy cruft now.

            Compared to systems then and shortly after, it does look like fork was a hacked together design driven primarily by hardware considerations of their underpowered machine. Maybe combined with their preference for minimalism. We know that quite a few things are in there solely due to them being on a PDP-11, though. So, that should be a strong consideration for any other design element that seems unnecessarily limited or prone to problems. My favorites being lack of prefix strings and incoming data flowing toward stack pointer rather than away from it (eg MULTICS).

            1. 6

              were hopelessly inadequate at addressing the problem they set out to solve

              And yet, 40 years later, it is the basis for 90% of the infrastructure software in the world. I’d like to create something that “hopelessly inadequate”.

              1. 3

                It’s fair to say most infrastructure uses fork, if you mean to start up, but the majority of modern client/server infrastructure software thankfully does not rely on it for data plane processing – any software due to be exposed to Internet-sized traffic by necessity must use event-driven IO or some form of threading (or a mixture of both), all of which are competing multiprocessing paradigms, and required to achieve anything close to sensible performance on modern hardware.

                The UNIX model was conceived at a time when the intended notion of a ‘client’ was literally an electronic typewriter attached to a fixed number of serial lines. I hope you can imagine the horror on the face of its designers were you to explain how this model was expected to cope with any subset of humans anywhere on the planet at any random moment demand one process to be dedicated to each of them.

                1. 3

                  I just wanted to point out that the “hopelessly inadequate” UNIX fork/exec design was a hugely successful design. Not only is it still the basis for a wide range of widely used software, but it was designed in a way that evolution to things like rfork and clone was practical.

                  BTW: “event driven” software seems to me to have been motivated by the shortage of programmers able to understand multi-process/multi-thread design more than anything else.

                  1. 5

                    That’s what I call the COBOL and VB6 argument. A lot of people used it. It’s still around. So, it was a great design. Alternatively, they spread for business, social, and ecosystem reasons as much as for design. Then, design can’t take credit for popularity. Popularity can’t excuse the bad or outdated elements of design.

                    Same with fork. In this case, UNIX got wildly popular with a huge ecosystem. It trains people to use available features like fork. It doesn’t tell them about lots of old and new ways to do the job better. So, they use the thing that they were taught to which is there and works well enough. When running into its problems, they use some other non-UNIX-like approach such as monolithic, multi-threaded apps or event-driven design.

                    1. 4

                      But those were very succesful designs. If they have become outdated, it’s good to try to understand what made them work so well for so long. Programmers have a really bad attitude about this. You are not going to find civil engineers who sneer at Roman Aquaducts or aviation engineers who think the DC3 was the product of stupid people who just didn’t get it. This is why programmers keep making the same errors.

                      1. 4

                        Civil engineers would behave the same way if the difference between Roman Aquaducts and modern aquaducts was as invisible as the difference between pieces of software is. It’s not that programmers are a different kind of people: it’s that noticing the differences, and hence needing explanations for the differences, requires much more effort.

                        Seeing the ancient aquaduct immediately reminds you of the materials they had to work with, minor general historical knowledge tells you of the inferior technology/tools they had to work with and minor specific historical subject knowledge (of science, physics, civil engineering) tells you of the lack of knowledge they had to work with. That makes the primitive nature of the Roman Aquaduct comprehensible and even impressive.

                        Seeing a COBOL program doesn’t demonstrate any reason why it should seem so primitive. Knowledge of general history tells you the world was pretty much the same 40 years ago, which doesn’t explain anything. Even with knowledge of the history of computing it remains easy to underappreciate the vast lack of knowledge, experiences and experiments (such as COBOL itself) that they had to work with and that we’ve been able to learn from.

                        So I don’t think blaming ‘programmers’ as lacking historical sensitivity is helpful or fair. Which doesn’t mean that we shouldn’t try to find ways of increasing the historical sensitivity of our craftsfolk, because it would indeed be really helpful if more of them learned from mistakes of the past or perhaps even restored something accidentally lost.

                    2. 3

                      Tell that to nginx, which does both.

                      1. 1

                        Well, event programming is embedded in web programming just as fork/excec is embedded in unixes. If you want a widely used web server, you don’t have much choice. But I take back what I wrote which was unintentionally snotty about event driven programming. lo siento.

                2. 3

                  Are the problems with fork() not mostly implementation issues? I get what you’re saying, but the existence of e.g. spawn() suggests that the concept is sound.

                3. 12

                  This looks like something that was written just so Microsoft can have something to reference when they for the umpteenth time have to explain why CreateProcessEx is slow as balls on their systems.

                  1. 4

                    I doubt MS commissioned a research paper to defend against one argument made about their OS.

                    Besides, the very view that process spawning should be very cheap is just a trade-off. Windows prioritizes apps designed around threads rather than processes. You can argue one approach is superior than the other, but it really reflects different priorities and ideas about how apps are structured.

                    1. 7

                      Besides, the very view that process spawning should be very cheap is just a trade-off. Windows prioritizes apps designed around threads rather than processes.

                      Windows was a VMS clone and iteration designed by the same guy, Dave Cutler. The VMS spawn command was a heavyweight one with a lot of control over what the resulting process would do. Parallelism was done by threading, maybe clustering. Unlike sebcats’ conspiracy, it’s most likely that the VMS lead that became Windows lead just reused his VMS approach for same reasons. That the remaining UNIX’s are doing non-forking, monolithic designs in highest-performance apps corroborates that he made the right choice in long term.

                      That is not to say we can’t improve on his choice carefully rewriting CreateProcessEx or using some new method in new apps. I’ve been off Windows for a while, though. I don’t know what they’re currently doing for highest-performance stuff. Some lean programmers are still using Win32 API based on blog articles and such.

                      1. 3

                        That the remaining UNIX’s are doing non-forking, monolithic designs in highest-performance apps corroborates that he made the right choice in long term.

                        Assuming that you believe the highest performing apps should be the benchmark for how everyone writes everything – which I don’t agree with. Simplicity and clarity are more important for all but a small number of programs.

                        1. 3

                          I think that’s important, too. Forking fails that criteria as not being most simple or clear method to do parallelism or concurrency. It would loose to things like Active Oberon, Eiffel’s SCOOP, Cilk for data-parallel, and Erlang. Especially if you add safety or error handling which makes code more complex. If heterogenous environments (multicore to clusters), Chapel is way more readable than C, forks or MPI.

                        2. 4

                          despite all the bloat in Linux, process creation in Linux is a lot faster than process creation in Windows. Rob Pike was right, using threads is generally an indication that process creation and ipc is too slow and inconvenient and the answer is to fix the OS. [ edited to maintain “no more than one ‘and yet’ per day” rule]

                          1. 3

                            Which led to faster designs than UNIX before and right after UNIX by using approaches that started with a better, concurrency-enabled language doing threads and function calls instead of processes and IPC. Funny you quote Rob Pike given his approach was more like Hansen (1960’s-1970’s) and Wirth’s (1980’s). On a language level, he also said a major inspiration for Go was his experience with Oberon-2 workstation doing rapid, safe coding. You including Rob Pike just corroborates my opinion of UNIX/C being inferior and/or outdated design from different direction.

                            Back to process creation, its speed doesn’t matter outside high availability setups. The processes usually get created once. All that matters is speed of handling the computations or I/O from that point on. Processes don’t seem to have much to do with that on modern systems. They prefer close to the metal with lots of hardware offloading. The designs try to bypass kernels whether Windows or UNIX-like. Looking back, both mainframe architectures and Amiga’s used hardware/software approach. So, their models proved better than Windows or UNIX in long term with mainframes surviving with continued updates. Last press release on System Z I saw claimed over 10 billion encrypted transactions a day or something. Cost a fortune, too.

                            1. 1

                              The threads/function call design is good for some things and bad for others. The memory protection of fork/exec is very important in preventing and detecting a wide range of bugs and forcing design simplication. Oberon was, like much of Wirth’s work, cool but too limited. I think Parnas’ “Software Jewels” was inspired by Oberon.

                              As for performance, I think you are 100% wrong and have a funny idea of “better”. System Z is clearly optimized for certain tasks, but as you say, it costs a fortune. You should have to write JCL code for a month as penance.

                              1. 2

                                “The memory protection of fork/exec is very important in preventing and detecting a wide range of bugs and forcing design simplication.”

                                Those programs had all kinds of security bugs. It also didn’t let you control privileges or resource usage. If security is goal, you’d do a design like VMS’s spawn which let you those things or maybe a capability-oriented design like AS/400. Unless you were on a PDP-11 aiming to maximize performance at cost of everything else. Then you might get C, fork, and the rest of UNIX.

                                “As for performance, I think you are 100% wrong and have a funny idea of “better”. System Z is clearly optimized for certain tasks”

                                The utilization numbers say I’m 100% right. It comes from I/O architecture, not just workloads. Mainframe designers did I/O differently than PC knowing mixing computation and I/O led to bad utilization. Even at CPU level, the two have different requirements. So, they used designs like Channel I/O that let computation run on compute-optimized CPU’s with I/O run by I/O programs on dedicated, lower-energy, cheaper CPU’s. Non-mainframes usually ditched that since cost was main driver of market. Even SMP took forever to reach commodity PC’s. The shared architecture had Windows, Mac, and UNIX systems getting piles of low-level interrupts, having one app’s I/O drag down other apps, and so on. The mainframe apps responded to higher-level events with high utilization and reliability while I/O coprocessors handled low-level details.

                                Fast forward to today. Since that model was best, we’ve seen it ported to x86 servers where more stuff bypasses kernels and/or is offloaded to dedicated hardware. Before that, it was used in HPC with the API’s splitting things between CPU’s and hardware/firmware (esp high-performance networking). We’ve seen the software side show up with stuff like Octeon processors offering a mix of RISC cores and hardware accelerators for dedicated, networking apps. Inline-Media Encryptors, RAID, and Netezza did it for storage. Ganssle also told me this design also shows up in some embedded products where the control logic runs on one core but another cheaper, lower-energy core handles I/O.

                                Knockoffs of mainframe, I/O architecture have become the dominant model for high-performance, consistent I/O. That confirms my hypothesis. What we don’t see are more use of kernel calls per operation on simple hardware like UNIX’s original design. Folks are ditching that in mass in modern deployments since it’s a bottleneck. Whereas, mainframes just keep using and improving on their winning design by adding more accelerators. They’re expensive but their architecture isn’t in servers or embedded. Adding a J2 core for I/O on ancient node (180nm) costs about 3 cents a CPU. Intel added a backdoor, err management, CPU to all their CPU’s without any change in price. lowRISC has minion cores. I/O-focused coprocessors can be as cheap as market is willing to sell it to you. That’s not a technical, design problem. :)

                                1. 2

                                  Since cores are so cheap now (we’re using 44-core machines, and I expect the count to keep going up in the future), why are we still using system calls to do IO? Put the kernel on its own core(s) and do IO with fast disruptor-style queues. That’s the design we seem to be converging toward, albeit in userspace.

                                  1. 1

                                    Absolutely true that the hugely expensive hardware I/O architecture in IBM mainframes work well for some loads if cost is not an issue. A Komatsu D575A is not better or worse than a D3K2 - just different and designed for different jobs.

                                    1. 2

                                      I just quoted you something costing 3 cents and something that’s $200 on eBay for Gbps accelerators. You only focused on the hugely, expensive mainframes. You must either agree the cheaper ones would work on desktops/servers or just have nothing else to counter with. Hell, Intel’s nodes could probably squeeze in a little core for each major subsystem: networking, disk, USB, and so on. Probably cost nothing in silicon for them.

                                      1. 1

                                        call intel.

                                        1. 2

                                          Nah. Enjoying watching them get what they deserve recently after their years of scheming bullshit. ;) Also, ISA vendors are likely to patent whatever I tell them about. Might talk to SiFive about it instead so we get open version.

                            2. 1

                              Windows NT was VMS-inspired, but I didn’t think Dave Cutler had any influence over Windows prior to that. Wasn’t CreateProcess available in the Win16 API?

                              I suspect the lack of fork has more to do with Windows’s DOS roots, but NT probably would have gained fork if Microsoft had hired Unix developers instead of Cutler’s team.

                              1. 1

                                Windows NT was VMS-inspired, but I didn’t think Dave Cutler had any influence over Windows prior to that. Wasn’t CreateProcess available in the Win16 API?

                                You could have me on its prior availability. I don’t know. The Windows API article on Wikipedia says it was introduced in Windows NT. That’s Wikipedia, though. I do know that Windows NT specifically cloned a lot from VMS via Russinovich’s article.

                                1. 2

                                  I think was mistaken; looking at the Windows 95 SDK (https://winworldpc.com/product/windows-sdk-ddk/windows-95-ddk), CreateProcess was at the time in Win32 but not Win16. I guess that makes sense – what would CreateProcess do in a cooperatively multitasked environment?

                                  Most of what I know about NT development comes from the book Showstoppers.

                          2. 2

                            Any source on performance issues with CreateProcessEx? A quick search didn’t yield anything interesting. Isn’t CreateProcessEx very similar to the posix_spawn API which the authors describe as the fast alternative to fork/exec in the paper?

                            1. 2

                              Alternatively they could just implement fork(). It’s nowhere near as hard as they’re making it out to be.

                              1. 3

                                fork is a bad API that significantly constrains OS implementation, so it is very understandable why Microsoft is reluctant to implement it.

                                1. 3

                                  Meh, says you but if you already have a process abstraction it’s not really that much harder to clone a memory map and set the IP at the point after the syscall than it is to set up a new memory map and set the IP at the start address. I don’t buy that it “significantly” constrains the implementation.

                                  1. 8

                                    Effort isn’t the argument here, but the semantics of it. fork is a really blunt hammer. For example, Rust has no bindings to fork in stdlib for various reasons, one being that many types (e.g. file handles) have state attached to their memory representation not known to fork and that state becomes problematic in the face of fork. This is a problem also present in programs written in other programming languages, also C, but generally glossed over. It’s not a problem for “plain old data” memory, but once we’re talking about copying resource handles, stuff gets messy.

                                    1. 1

                                      Can you elaborate? FILE* responds to being forked just fine. What Rust file metadata needs to be cleaned up after fork()?

                                      1. 2

                                        Files are the simplest case. They are just racy in their raw form and you need to make sure everyone closes them properly. You can work against that by using RAII and unique pointers (or Ownership in Rust), but all those guarantees break on fork(). But even files with fork have a whole section in POSIX and improper handling may be undefined.

                                        It gets funnier if your resource is a lock and your memory allocator has locks.

                                        Sure, all this can be mitigated again, but that adds ton of complexity. My point is: fork may seem clean and simple, but in practice is extremely messy in that it does not set up good boundaries.

                                        1. 1

                                          Files are the simplest case. They are just racy in their raw form and you need to make sure everyone closes them properly. You can work against that by using RAII and unique pointers (or Ownership in Rust), but all those guarantees break on fork().

                                          There are no close() races on a cloned file descriptor across forked processes, nor are there file descriptor leaks if one forked process does not call close() on a cloned file descriptor.

                                          It gets funnier if your resource is a lock and your memory allocator has locks.

                                          How so? malloc() and fork() work fine together.

                                2. 1

                                  But one of the main issue with fork that the authors describe is that it gets really slow for processes that use a large address space because it has to copy all the page tables. So I don’t see how implementing fork would help with performance?

                                  1. 0

                                    Nobody calls fork() in a loop. An efficiency argument isn’t relevant.

                                    1. 2

                                      In shell scripts usually most of the work is done by external programs. So shells use fork/exec a lot.

                                      1. 0

                                        But not “a lot” to the point where progress is stalled on fork/exec.

                                      2. 1

                                        I mean, the parent comment by @sebcat complains about process creation performance, and you suggest that implementing fork would help with that, so you do argue that it is efficient. Or am I reading your comment wrong?

                                        1. 1

                                          Ah okay, I see. I was under the impression that he was referring to the case where people complain about fork() performance on Windows because it is emulated using CreateProcessEx() (which he may not have been doing). My point was that If they implemented fork() in the kernel, they wouldn’t have to deal with those complaints (which are also misled since CreateProcessEx / fork() performance should never be relevant).

                                        2. 1

                                          A loop isn’t necessary for efficiency to be come relevant. Consider: most people abandoned CGI because (among other reasons) fork+exec for every HTTP request doesn’t scale well (and this was after most implementations of fork were already COW).

                                          1. 1

                                            I can’t blame you, but that’s an excessively literal interpretation of my statement. By “in a loop,” I mean that the program is fork+exec bound, which happens on loaded web servers, and by “nobody” I mean “nobody competent.” It isn’t competent to run a high trafficked web server using the CGI model and expect it to perform well since process creation per request obviously won’t scale. CGI was originally intended for small scale sites.

                                      3. 1

                                        The bureaucracy at large, slow and old corporations partly explains this. This paper maybe took 6 months - 1 year. Adding fork() (with all the formalities + technical details + teams involved) would take 5-10 years IMHO.

                                        Much easier to just include it as “yet another app”, e.g. WSL:

                                        When a fork syscall is made on WSL, lxss.sys does some of the initial work to prepare for copying the process. It then calls internal NT APIs to create the process with the correct semantics and create a thread in the process with an identical register context. Finally, it does some additional work to complete copying the process and resumes the new process so it can begin executing.

                                        https://blogs.msdn.microsoft.com/wsl/2016/06/08/wsl-system-calls/

                                        1. [Comment removed by author]

                                    2. 8

                                      This paper is in the recent trend of lightweight academic articles based on sneering at things that work. The dismissal of Linux clone is particularly bad:

                                      This syscall underlies all process and thread creation on Linux. Like Plan 9’s rfork() which preceded it, it takes separate flags controlling the child’s kernel state: address space, file descriptor table, namespaces, etc. This avoids one problem of fork: that its behaviour is implicit or undefined for many abstractions. However, for each resource there are two options: either share the resource between parent and child, or else copy it. As a result, clone suffers most of the same problems as fork (§4–5).

                                      No it doesn’t - precisely because you can select not to duplicate. I also like this

                                      The performance advantage of the shared initial state created by fork is less relevant when most concurrency is handled by threads, and modern operating systems deduplicate memory. Finally, with fork, all processes share the same address-space layout and are vulnerable to Blind ROP attacks

                                      For sure, let’s use threads in the exact same address space to avoid ROP attacks.

                                      The most interesting thing in the paper was that fork takes 1/2 millisecond on the machines they measured. Too slow by 10x.

                                      1. 6

                                        I agree that there was a very negative tone in the paper, and I found it quite off-putting and unprofessional. Among the scathingly negative phrases that caught my attention:

                                        • “fork is a terrible abstraction”
                                        • “fork is an anachronism”
                                        • “fork is hostile… breaking everything…”
                                        • “fork began as a hack”
                                        • “we illustrate the havoc fork wreaks”
                                        • “this is a deceptive myth”
                                        • “multi-threaded programs that fork are plagued with bugs”
                                        • “it is hard to imagine a new proposed syscall with these properties being accepted by any sane kernel maintainer”
                                        • “caused fork semantics to subvert the OS design”
                                        • “get the fork out of my OS”
                                        1. 1

                                          I hate to say it, but all those statements are either introductions to claims or much milder if you don’t cut off the whole sentence. I won’t go through all, but just some examples:

                                          • “We catalog the ways in which fork is a terrible abstraction for the modern programmer to use, describe how it compromises OS implementations, and propose alternatives.”

                                            • If you believe something is terrible, it’s fine to say it like that.
                                          • “fork began as a hack”

                                            • And the chapter that is called like that describes exactly that: how fork was ad-hoc implemented, using quotes by Richie himself. It’s a hack and not structured innovation implemented with farsight. That’s okay, but that’s what we call a hack.
                                          • “fork is hostile to user-mode implementation of OS functionality, breaking everything from buffered IO to kernel-bypass networking. Perhaps most problematically, fork doesn’t compose—every layer of a system from the kernel to the smallest user-mode library must support it.”

                                            • A technology or API being “hostile” to uses is standard terminology. And they go on to explain why they believe it to be hostile.
                                          • “At first glance, fork still seems simple. We argue that this is a deceptive myth, and that fork’s effects cause modern applications more harm than good.”

                                            • It is indeed the case that fork has a lot of rules to maintain around it and they are also right that fork is still tought as simple.
                                          • “We illustrate the havoc fork wreaks on OS implementations using our experiences with prior research systems (§5). Fork limits the ability of OS researchers and developers to innovate because any new abstraction must be special-cased for it.”

                                            • They rightfully claim that every abstraction needs to take into account that at any point in time, the process could be forked and the whole machinery is doubled. If something impacts almost all research in a field, strong wording is probably okay. “wreak havoc” is also not unheard of in professional settings.

                                          Like, I’m fine with you no agreeing with their reading, but unprofessional, I would not agree with.

                                          1. 2

                                            Like, I’m fine with you no agreeing with their reading, but unprofessional, I would not agree with.

                                            You omitted the most salacious phrase, “get the fork out of my OS”. This sort of wording has no place in a professional paper.

                                            The remaining phrases I would categorize as more scathing than salacious. This wording is appropriate for a newsgroup or mailing list, but in an academic paper, these statements are hyperbolic, and could be replaced by more objective phrasing, without sacrificing meaning or impact.

                                            1. 2

                                              I took those phrases as tongue-in-cheek, but can agree that if you’re writing an article which may inspire strong opinions perhaps you should be mindful of how others might read it. I wouldn’t go as far as saying it’s unprofessional, however.

                                              You omitted the most salacious phrase, “get the fork out of my OS”. This sort of wording has no place in a professional paper.

                                              This is a good pun and I will defend to the death the authors’ right to use it in any context :)

                                        2. 2

                                          As a result, clone suffers most of the same problems as fork (§4–5).

                                          No it doesn’t - precisely because you can select not to duplicate.

                                          The only issue I see that clone clearly solves is the security problem from share-everything. How does it help with multithreading, performance (or ease-of-use in vfork mode), picoprocesses, heterogeneous hardware?

                                          For sure, let’s use threads in the exact same address space to avoid ROP attacks.

                                          I think the argument here is more like this:

                                          • If you need it to be fast, use threads (most people already do this)
                                          • If you need it to be secure, use a proper new process instead of forking from a prototype

                                          The authors also argue that there might be better Copy-on-Write primitives than fork.

                                          1. 1

                                            How does it help with multithreading, performance

                                            It’s pretty fast - especially compared to actually existing alternatives.

                                            picoprocesses, heterogeneous hardware

                                            It’s not intended to address those problems.

                                            1. 1

                                              It’s pretty fast - especially compared to actually existing alternatives.

                                              In the paper, they show that posix_spawn is consistently faster at creating processes than fork, so I’m not sure what you mean?

                                              1. 1

                                                Posix_spawn is vfork/exec.

                                        3. 2

                                          My personal problem with windows not implementing fork: it doesn’t able to implement fork only call. In using python that means that multiprocessing standard module is just broken on windows systems (you can have work around, but basically it just don’t work).

                                          Other thing is that not having fork means multiprocess concurrency is just inefficient as hell, with only threading at your disposition and threading means just race condition as hell.

                                          1. 2

                                            Other thing is that not having fork means multiprocess concurrency is just inefficient as hell, with only threading at your disposition and threading means just race condition as hell.

                                            IPC is as racy as you make it, just across process boundaries. Message passing remains the most sane starting place, whether you are using threads or processes.

                                          2. 1

                                            I like what Redis does with fork(). :-)

                                            1. -1

                                              You can make this kind of handwavy argument about anything.

                                              1. 1

                                                Alternatively, they can base their arguments on what Ritchie said motivated the design followed by its consequences then and now. Which they did. The motivation was crappy hardware and architecture as I predicted:

                                                “Ritchie later noted that “it seems reasonable to sup-pose that it exists in Unix mainly because of the ease with which fork could be implemented without changing much else.” He goes on to describe how the first fork was implemented in 27 lines of PDP-7 assembly, and consisted of copying the current process out to swap and keeping the child resident in memory. Ritchie also noted that a combined Unix fork-exec “would have been considerably more complicated,if only because exec as such did not exist; its function was already performed, using explicit IO, by the shell.”

                                                1. 5

                                                  So what? LISP car/cdr was motivated by a crappy processor architecture. In fact, it seems to me that crappy, limited, hardware resources produce better designs by necessity.

                                                  1. 1

                                                    That’s an interesting point. Could be some truth in it. “Necessity is the mother of invention.” I’d caution the ideas might not be best and final to keep. It can generate good ideas, though.

                                              2. -2

                                                I’m taking a class right now that has an entire unit on fork(). God save us all.