diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-02-18 19:52:42 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-02-18 19:52:42 -0500 |
commit | e9417fffb39c299e556c5ad0c1545f0c02618e3c (patch) | |
tree | 90c04bef0567ff4df7c7b57986a756b8b11b506c /src/thread/pthread_atfork.c | |
parent | 446b4207cc7a30d8a4d5b2445a5a1b27d440f55d (diff) | |
download | musl-e9417fffb39c299e556c5ad0c1545f0c02618e3c.tar.gz musl-e9417fffb39c299e556c5ad0c1545f0c02618e3c.tar.xz musl-e9417fffb39c299e556c5ad0c1545f0c02618e3c.zip |
add pthread_atfork interface
note that this presently does not handle consistency of the libc's own global state during forking. as per POSIX 2008, if the parent process was threaded, the child process may only call async-signal-safe functions until one of the exec-family functions is called, so the current behavior is believed to be conformant even if non-ideal. it may be improved at some later time.
Diffstat (limited to 'src/thread/pthread_atfork.c')
-rw-r--r-- | src/thread/pthread_atfork.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/thread/pthread_atfork.c b/src/thread/pthread_atfork.c new file mode 100644 index 00000000..0773dc8f --- /dev/null +++ b/src/thread/pthread_atfork.c @@ -0,0 +1,48 @@ +#include <pthread.h> +#include "libc.h" + +static struct atfork_funcs { + void (*prepare)(void); + void (*parent)(void); + void (*child)(void); + struct atfork_funcs *prev, *next; +} *funcs; + +static int lock; + +static void fork_handler(int who) +{ + struct atfork_funcs *p; + if (who < 0) { + LOCK(&lock); + for (p=funcs; p; p = p->next) { + if (p->prepare) p->prepare(); + funcs = p; + } + } else { + for (p=funcs; p; p = p->prev) { + if (!who && p->parent) p->parent(); + else if (who && p->child) p->child(); + funcs = p; + } + UNLOCK(&lock); + } +} + +int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) +{ + struct atfork_funcs *new = malloc(sizeof *new); + if (!new) return -1; + + LOCK(&lock); + libc.fork_handler = fork_handler; + new->next = funcs; + new->prev = 0; + new->prepare = prepare; + new->parent = parent; + new->child = child; + if (funcs) funcs->prev = new; + funcs = new; + UNLOCK(&lock); + return 0; +} |