1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include "thread_internal.h"
static struct _pthread_fastlock __atfork_struct_lock = { PTHREAD_SPIN_UNLOCKED };
static struct __thread_atfork {
struct __thread_atfork*next,*prev;
void (*prepare)(void);
void (*parent)(void);
void (*child)(void);
} pthread_atfork_buf={&pthread_atfork_buf,&pthread_atfork_buf,0,0,0};
int pthread_atfork(void (*prepare)(void),
void (*parent)(void),
void (*child)(void)) {
_pthread_descr this=__thread_self();
struct __thread_atfork*new;
int ret=0;
__NO_ASYNC_CANCEL_BEGIN_(this);
__pthread_lock(&__atfork_struct_lock);
if ((new=(struct __thread_atfork*)malloc(sizeof(struct __thread_atfork)))) {
new->prepare=prepare;
new->parent=parent;
new->child=child;
new->next=pthread_atfork_buf.next;
new->prev=&pthread_atfork_buf;
pthread_atfork_buf.next->prev=new;
pthread_atfork_buf.next=new;
}
else ret=ENOMEM;
__pthread_unlock(&__atfork_struct_lock);
__NO_ASYNC_CANCEL_END_(this);
return ret;
}
pid_t fork(void) {
_pthread_descr this=__thread_self();
struct __thread_atfork*tmp;
pid_t pid;
__NO_ASYNC_CANCEL_BEGIN_(this);
__TEST_CANCEL_(this);
__pthread_lock(&__atfork_struct_lock);
for (tmp=pthread_atfork_buf.next;tmp!=&pthread_atfork_buf;tmp=tmp->next)
if (tmp->prepare) tmp->prepare();
pid=__libc_fork();
if (pid) {
for (tmp=pthread_atfork_buf.prev;tmp!=&pthread_atfork_buf;tmp=tmp->prev) {
if (tmp->parent) tmp->parent();
}
}
else {
__thread_manager_close();
for (tmp=pthread_atfork_buf.prev;tmp!=&pthread_atfork_buf;tmp=tmp->prev) {
if (tmp->child) tmp->child();
}
}
__pthread_unlock(&__atfork_struct_lock);
__NO_ASYNC_CANCEL_END_(this);
return pid;
}
|