Earlier quoted context omitted.
Most non-UNIX OSes only have exec(), not fork(). Hence why fork() is just kind-of implemented on their POSIX compatibility layers. In UNIX it is only an issue, because IEEE doesn't want to set in stone in POSIX how threads, signals and processes should interact, due to the way threads were added to UNIX.
Non-unix systems don't have exec; they have spawn.
Fork() without exec() is dangerous in large programs
31–40 of 106 posts
Re: Fork() without exec() is dangerous in large programs
#32I see two implementation challenges with that suggestion:
1.) implementing that transaction mechanism as a kernel feature: When entering a CS mark all pages CoW, upon leaving the CS merge modified pages (problem: Whole pages are then mutual exclusive, dealing with this is the challenge)
2.) battling with user space implemented locks that use atomics.
-----
An immediate mitigation I see is, that fork() itself is a CS on _all_ the locks of a process. If we consider that only the standard locking mechanisms are used, then whenever a CS is entered (which includes the creation process of a locking primitive) it raises/posts a global fork-lock semaphore. And upon leaving that semaphore is lowered.
This still leaves the DIY-locking primitives problem open. But it should be more or less straightforward to add this to the system libc/pthread libraries' locking primitive implementation and fork() syscall wrappers.
Or did I miss something essential here? Talk is cheap, so if nobody has any obvious objections I'd actually go ahead implement it.
EDIT: Okay, one immediate problem I see is, that this would pose a challenge for calling fork inside a CS. Technically this is a situation where thread recursive locks would help, but as we all know, recursive locks are highly problematic.
Re: Fork() without exec() is dangerous in large programs
#33Earlier quoted context omitted.
You can have your cake and eat it too -- there's no throwing away of performance gains. Libraries can use threads, but not directly or "silently". They should take threads as parameters. Then the application knows when they're being used and the application programmer can reason about it.
Yes, in theory. In practice, every library developer/maintainer uses different guidelines.
Re: Fork() without exec() is dangerous in large programs
#34Earlier quoted context omitted.
true... ...this applies not just to threading, but other things that are not in the domain of the library such as memory allocation strategy or communication mechanism. Libraries should be small, focused and decoupled. This is the way to proper re-usability.
Like left-pad?
I suppose another rule should be that there libraries should encapsulate a sufficient amount of complexity to make their existence worthwhile.... unlike left-pad.
Re: Fork() without exec() is dangerous in large programs
#35Earlier quoted context omitted.
I completely disagree. The only part of this that seems dangerous is the fact that it can turn a single-threaded program into a multi-threaded one, and the only real problem there is it makes fork-without-exec unsafe. But fork-without-exec is basically unsafe anyway unless you can absolutely guarantee that nothing has ever spawned a thread. Meanwhile, preventing libraries from using threading under the covers basical…
You can have your cake and eat it too -- there's no throwing away of performance gains. Libraries can use threads, but not directly or "silently". They should take threads as parameters. Then the application knows when they're being used and the application programmer can reason about it.
Re: Fork() without exec() is dangerous in large programs
#36So if you control very closely the libs you link with and what they do, as well as the threads you use yourself, it is possible to use fork() in a reliable way.
Re: Fork() without exec() is dangerous in large programs
#37In my opinion, it's libraries that secretly use threads under the covers (but still access state shared with the rest of the program like the malloc heap) that are what's dangerous.
What is dangerous is that the interactions between threads and processes aren't part of POSIX standard and its behavior is OS specific across UNIX implementations. This isn't an issue on non-UNIX OSes.
Then there is pipe() and probably some more similar ones.
Re: Fork() without exec() is dangerous in large programs
#38If you are in control of all the threads that an application is running, you can call fork() safely by making sure the threads are put in a safe state (no critical locks retained) when the fork() call happens. Also note that many things that should normally be unsafe, like having running threads calling malloc() while another thread is forking, are actually safe in the real world using certain implementation of fork,…
Re: Fork() without exec() is dangerous in large programs
#39If you are in control of all the threads that an application is running, you can call fork() safely by making sure the threads are put in a safe state (no critical locks retained) when the fork() call happens. Also note that many things that should normally be unsafe, like having running threads calling malloc() while another thread is forking, are actually safe in the real world using certain implementation of fork,…
Re: Fork() without exec() is dangerous in large programs
#40If you are in control of all the threads that an application is running, you can call fork() safely by making sure the threads are put in a safe state (no critical locks retained) when the fork() call happens. Also note that many things that should normally be unsafe, like having running threads calling malloc() while another thread is forking, are actually safe in the real world using certain implementation of fork,…
the apple way of just throwing its hands in the air and abort()ing sound either like giving up because the apple devs think it is too hard, or because they feel the need to impose their way in crippling code that uses fork() without calling exec()
in my opinion if you are going to write a library that uses threads and is supposed to be thread safe then remember you need to handle the issue of fork(); don't be lazy, do the job properly, even if doing it right it is hard and ugly.