Re: 7.5.2.7: Library Functions Used Between fork() and exec()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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}



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux