4 ms·
You absolutely need to lock all the locks, because fork() kills all the other threads, so if any one of them was in a critical section while fork was called, th
by jart 2y ago
You absolutely need to lock all the locks, because fork() kills all the other threads, so if any one of them was in a critical section while fork was called, then the new process will deadlock if it tries to acquire that lock afterwards. Yes, I know the POSIX standard has turned against fork() and considers vfork() beyond the pale. I don't know how they can forbid UNIX behavior that's essential to the workings of /bin/sh. No it's not realistic for the OS to define its most important function to be as useless as a signal handler, but here we are. That advice will be never be accepted. People on the best OSes like Linux and FreeBSD will always use vfork() regardless of what POSIX says. The de facto standard is that only vfork() must guarantee a swift execve() call. You learn to take the official standard with a grain of salt when you realize it's bankrolled by regulated enterprises who hire cheap engineers to work on life or death machinery and therefore can't be trusted with powerful footguns.
- o11c 2y ago> then the new process will deadlock if it tries to acquire that lock afterwards which is not async-signal safe and thus illegal if other threads ever existed (or if we're called from a signal handler). All semi-new programs (which might use threads) are responsible for not introducing such bugs. And if we're the only thread (and not in a signal handler), which all sufficiently-old programs (including shells) will be, it's the caller's responsibility to not call fork() while holding a mutex. Thus, one way or another, there's really no need to do this. From an application perspective, it's unnecessary, and from a libc perspective it is at most a QoI feature (one which should be limited to a very small number of locks at most, and frankly we've strongly learned should just detect the error (which is a simple matter of 2 thread-local counters - one for "number of mutexes held" and one for "number of async-signal contexts entered" - as well as knowledge of whether other threads exist) rather than trying to continue in the face of UB).
- zbentley 2y agoIllegal it may be, but as jart (who has probably seen some shit, to put it mildly) points out, that doesn’t stop a very wide variety of programs from depending on this behavior, intentionally or inadvertently. Heck, runtimes like Python (and Node, if jart is correct in GGP) ship with atfork handlers specifically for the purpose of massaging runtime-created mutexes/condvars/etc. I don’t think those are there because the language maintainers like breaking the rules; they’re probably there because users kept depending on this behavior in spite of cautionary statements.
- saagarjha 2y ago> I don’t think those are there because the language maintainers like breaking the rules You think wrong.
- zbentley 2y agoSay more? Is this just get-gud anti scripting language elitism, or a reference to some specific history that the Python/Node/others(?) maintainers have regarding decisions made in this area?
- saagarjha 2y agoPeople who maintain language runtimes are typically very smart people who often do things that are inadvisable when maintaining said runtime.