From ec9f917101371baaae34ca10ae952392c2c2343d Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Tue, 13 Dec 2016 22:41:35 -0800 Subject: More comments, and detection of fork-reentrancy. Much effort was spent trying to come to a fork-safe solution, but ultimately we gave up. --- src/platform/posix/posix_synch.h | 18 +++++-------- src/platform/posix/posix_thread.h | 56 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 13 deletions(-) (limited to 'src/platform') diff --git a/src/platform/posix/posix_synch.h b/src/platform/posix/posix_synch.h index 94058d32..d3e44411 100644 --- a/src/platform/posix/posix_synch.h +++ b/src/platform/posix/posix_synch.h @@ -85,11 +85,6 @@ nni_mutex_destroy(nni_mutex_t m) if (pthread_mutex_destroy(&m->mx) != 0) { nni_panic("pthread_mutex_destroy failed"); } - /* - * If destroy fails for some reason, we can't really do - * anything about it. This would actually represent a programming - * bug, and the right thing to do here would be to panic. - */ nni_free(m, sizeof (*m)); } @@ -183,7 +178,6 @@ nni_cond_create(nni_cond_t *cvp, nni_mutex_t mx) nni_free(c, sizeof (*c)); return (NNG_ENOMEM); } - *cvp = c; return (0); } @@ -232,12 +226,12 @@ nni_cond_timedwait(nni_cond_t c, uint64_t usec) ts.tv_sec = usec / 1000000; ts.tv_nsec = (usec % 10000) * 1000; - if ((rv = pthread_cond_timedwait(&c->cv, c->mx, &ts)) != 0) { - if (rv == ETIMEDOUT) { - return (NNG_ETIMEDOUT); - } else { - nni_panic("pthread_cond_timedwait returned %d", rv); - } + rv = pthread_cond_timedwait(&c->cv, c->mx, &ts); + + if (rv == ETIMEDOUT) { + return (NNG_ETIMEDOUT); + } else if (rv != 0) { + nni_panic("pthread_cond_timedwait returned %d", rv); } return (0); } diff --git a/src/platform/posix/posix_thread.h b/src/platform/posix/posix_thread.h index 239959f8..27ad888f 100644 --- a/src/platform/posix/posix_thread.h +++ b/src/platform/posix/posix_thread.h @@ -37,8 +37,23 @@ struct nni_thread { pthread_t tid; + void *arg; + void (*func)(void *); }; +static pthread_mutex_t plat_lock = PTHREAD_MUTEX_INITIALIZER; +static int plat_init = 0; +static int plat_fork = 0; + +static void * +thrfunc(void *arg) +{ + nni_thread_t thr = arg; + + thr->func(thr->arg); + return (NULL); +} + int nni_thread_create(nni_thread_t *tp, void (*fn)(void *), void *arg) { @@ -48,7 +63,10 @@ nni_thread_create(nni_thread_t *tp, void (*fn)(void *), void *arg) if ((thr = nni_alloc(sizeof (*thr))) == NULL) { return (NNG_ENOMEM); } - if ((rv = pthread_create(&thr->tid, NULL, (void *)fn, arg)) != 0) { + thr->func = fn; + thr->arg = arg; + + if ((rv = pthread_create(&thr->tid, thr, thrfunc, arg)) != 0) { nni_free(thr, sizeof (*thr)); return (NNG_ENOMEM); } @@ -65,3 +83,39 @@ nni_thread_reap(nni_thread_t thr) } nni_free(thr, sizeof (*thr)); } + +void +atfork_child(void) +{ + plat_fork = 1; +} + +int +nni_platform_init(void) +{ + if (plat_fork) { + nni_panic("nng is fork-reentrant safe"); + } + if (plat_init) { + return (0); /* fast path */ + } + pthread_mutex_lock(&plat_lock); + if (plat_init) { /* check again under the lock to be sure */ + pthread_mutex_unlock(&plat_lock); + return (0); + } + if (pthread_atfork(NULL, NULL, atfork_child) != 0) { + pthread_mutex_unlock(&plat_lock); + return (NNG_ENOMEM); + } + plat_init = 1; + pthread_mutex_unlock(&plat_lock); + + return (0); +} + +void +nni_platform_fini(void) +{ + /* XXX: NOTHING *YET* */ +} \ No newline at end of file -- cgit v1.2.3-70-g09d2