I just learned that forking a process (fork(2) - Linux manual page) might lead to problems with mutexes, condition variables etc. Does that mean that using the Rust standard library and calling fork can lead to UB? At least chrisd mentions in following thread
Why no `fork()` in `std::process`? - #4 by RalfJung - libs - Rust Internals that it is definitely unsafe!.
I wonder which parts of the standard library are still safe to use in the parent process before the fork call? Or to phrase it more practically how can I determine whether some standard library feature / container is "free" from multi-threading?
Lets say I have created an instance of std::Vec<...> and stored it in some static variable [... lazy_static! ...]. Is this vector still safe to use after the fork? I mean, besides thread safety it would also require that pointer addresses are still valid after the fork, right?
I don't think there is anything in the standard library that will spawn threads other than user-code calls to
Forked processes generally have an identical address space to the parent process post-fork so pointers to your example Vec will still be valid.
that's what I needed to hear
One fork-related piece of Rust documentation is
CommandExt::pre_exec() — when spawning a child process, it runs code after the
fork and before the
exec, so it has to tell you about what's safe in a forked process.
This closure will be run in the context of the child process after a
fork. This primarily means that any modifications made to memory on behalf of this closure will not be visible to the parent process. This is often a very constrained environment where normal operations like
malloc, accessing environment variables through
std::env or acquiring a mutex are not guaranteed to work (due to other threads perhaps still running when the
fork was run).
For further details refer to the POSIX fork() specification and the equivalent documentation for any targeted platform, especially the requirements around async-signal-safety.
So, it's more restrictive than you might think — note the mention of memory allocation, mutexes and
env not being allowed. A good rule to start with might be that all the code run after fork needs to be
no_std code (since that implies no syscalls), and then when you want to do something more than that, you check the documentation.