[NPTH] npth and fork

NIIBE Yutaka gniibe at fsij.org
Sat Oct 1 10:33:29 CEST 2016


This summer, for AIX, I put a workaround for the issue 2260.  That's
basically, we have fork(2) inside GnuPG (gpg-agent, scdaemon), but it
fails on AIX because of semaphore.

After that, I learned that macOS also has an issue with unnamed

This week, I examined the code again, and concluded that current
workaround for AIX and macOS is not that good, in fact.  I have a new

You can skip to PROPOSAL.

* DETAIL of current implementation of nPth in master

In nPth, we have a semaphore to control threads execution so that only
a single thread can run at a time.

On GNU/Linux, FreeBSD, etc., it is a unnamed semaphore which is
private to a process.  According to POSIX specification and OS
manuals, it is not clear if fork(2) is safe or not for the use of such
semaphore, but it works well on those systems.

On AIX, it is explicitly addressed in the OS manual and unnamed
private semaphore is not safe in a child process (access is prohibited
by child process).  So, I added a workaorund to allocate a unnamed
semaphore which is shareable among processes.

On macOS, unnamed semaphore doesn't work well (although we have a
defined symbol in the library), and it falls back to a named semaphore
at runtime.

This week, I realized that nPth with a named/shareable semaphore runs
not that correctly.  Let's see how it goes.

(1) npth_init

A semaphore is allocated by npth_init function.

(2) fork

When a thread calls fork(2), new child process is created.  The
semaphore is shared between a parent process and newly created child

Here, both of parent and child consider they "own" the resource.

For the specific use cases in GnuPG, it is to be a daemon, there is no
problem; It is only a single side of process among two processes which
continues to run as nPth application program.

If both processes try to keep running as nPth application program,
each process goes wrong because of shared semaphore: two threads can
run simultaneously in a process.


It is better to use unnamed private semaphore for all OSes.  For
macOS, I think that the semaphore in "Grand Central Dispatch" instead
of POSIX named semaphore is good.

Note that Grand Central Dispatch implementation also prohibits use of
semaphore after fork.

For those OSes which prohibits use of
already-allocated-semaphore-by-parent after fork, we call
pthread_atfork at npth_init; We setup a callback for child.  In the
callback for child, the child process initializes a unnamed semaphore,
so that threads can be controlled by the semaphore.

More information about the Gnupg-devel mailing list