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

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

 



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