Looks good to me! --Elad On Wed, 19 Oct 2022 at 19:32, Paul E. McKenney <paulmck@xxxxxxxxxx> wrote: > > On Fri, Oct 14, 2022 at 08:14:42AM -0400, Elad Lahav wrote: > > Ah, multi-threaded fork, my arch-nemesis. > > > > A few points, though I'm not sure any of these are worth mentioning in the book: > > > > 1. It should perhaps be made clear that the child's copy of the lock > > is, in fact, a separate lock. The statement that the lock is held by a > > parent thread is somewhat inaccurate. That is, unless the lock is in > > explicitly-shared memory (i.e., the result of mmap(MAP_SHARED)), in > > which case the lock is indeed the same and is (presumably) meant to be > > shared between the parent and child. > > > > 2. POSIX explicitly says that you can't execute any > > non-async-signal-safe functions between fork() and exec(), which > > pretty much eliminates any function that acquires a lock. > > > > 3. posix_spawn() is a safer alternative to the fork()/exec() pair > > (though not to fork() by itself), at least with sensible > > implementations that don't devolve to fork() and exec(). > > Good points! > > How about the following update? > > Thanx, Paul > > ------------------------------------------------------------------------ > > commit 069eb5ee2b570c9216b7f1244847a4bf2d2dfb47 > Author: Paul E. McKenney <paulmck@xxxxxxxxxx> > Date: Wed Oct 19 16:30:52 2022 -0700 > > locking: Expand on fork()/exec() locking issues > > Reported-by: Elad Lahav <e2lahav@xxxxxxxxx> > Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxx> > > diff --git a/bib/os.bib b/bib/os.bib > index 3ae9b617..0846801e 100644 > --- a/bib/os.bib > +++ b/bib/os.bib > @@ -1442,3 +1442,24 @@ Paul E. McKenney", > note="\url{https://google.github.io/tcmalloc/overview.html}", > lastchecked="January 24, 2020", > } > + > +@unpublished{JoshTriplett2022io_uring_spawn, > + author="Josh Triplett", > + title="Spawning processes faster and easier with \co{io_uring}", > + year="2022", > + month="September", > + day="12", > + url={https://lpc.events/event/16/contributions/1213/}, > + note="\url{https://www.youtube.com/watch?v=_h-kV8AYYqM&t=4074s}", > + lastchecked="October 19, 2022", > +} > + > +@unpublished{JakeEdge2022io_uring_spawn, > + author="Jake Edge", > + title="Introducing \co{io_uring_spawn}", > + year="2022", > + month="September", > + day="20", > + note="\url{https://lwn.net/Articles/908268/}", > + lastchecked="October 19, 2022", > +} > diff --git a/locking/locking.tex b/locking/locking.tex > index 6d3bb1c8..f74e0784 100644 > --- a/locking/locking.tex > +++ b/locking/locking.tex > @@ -2436,11 +2436,11 @@ As noted earlier, if a thread executing a library function is holding > a lock at the time that some other thread invokes \apipx{fork()}, the > fact that the parent's memory is copied to create the child means that > this lock will be born held in the child's context. > -The thread that will release this lock is running in the parent, but not > -in the child, which means that the child's copy of this lock will never > -be released. > +The thread that will release this lock is running in the parent, but > +not in the child, which means that although the parent's copy of this > +lock will be released, the child's copy never will be. > Therefore, any attempt on the part of the child to invoke that same > -library function will result in deadlock. > +library function (thus acquiring that same lock) will result in deadlock. > > A pragmatic and straightforward way of solving this problem is > to \co{fork()} a child process while the process is still single-threaded, > @@ -2472,10 +2472,16 @@ parent before the \co{fork()}, one to be called by the parent after the > \co{fork()}, and one to be called by the child after the \co{fork()}. > Appropriate cleanups can then be carried out at these three points. > > -Be warned, however, that coding of \co{pthread_atfork()} handlers is quite subtle > -in general. > -The cases where \co{pthread_atfork()} works best are cases where the data structure > -in question can simply be re-initialized by the child. > +Be warned, however, that coding of \co{pthread_atfork()} handlers is > +quite subtle in general. > +The cases where \co{pthread_atfork()} works best are cases where the > +data structure in question can simply be re-initialized by the child. > +Which might be one reason why the POSIX standard forbids use of any > +non-async-signal-safe functions between the \co{fork()} and the > +\co{exec()}, which rules out acquisition of locks during that time. > + > +Other alternatives to \co{fork()}/\co{exec()} include \co{posix_spawn()} > +and \co{io_uring_spawn()}~\cite{JoshTriplett2022io_uring_spawn,JakeEdge2022io_uring_spawn}. > > \subsubsection{Parallel Libraries: > Discussion}