aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix/posix_thread.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-04 18:30:33 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-04 18:30:33 -0800
commit40da92f0fffc7b69f876ca060d9b4e6682e45a8c (patch)
tree3147f840adc3815dd55693e440380992f76b1ba9 /src/platform/posix/posix_thread.c
parentc1d11425846baf22e9a07b0f2bf2ad405e0b42e5 (diff)
downloadnng-40da92f0fffc7b69f876ca060d9b4e6682e45a8c.tar.gz
nng-40da92f0fffc7b69f876ca060d9b4e6682e45a8c.tar.bz2
nng-40da92f0fffc7b69f876ca060d9b4e6682e45a8c.zip
Fix close related races (POSIX close is a PITA).
Diffstat (limited to 'src/platform/posix/posix_thread.c')
-rw-r--r--src/platform/posix/posix_thread.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/platform/posix/posix_thread.c b/src/platform/posix/posix_thread.c
index 02f0b058..00419aac 100644
--- a/src/platform/posix/posix_thread.c
+++ b/src/platform/posix/posix_thread.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
+#include <fcntl.h>
static pthread_mutex_t nni_plat_lock = PTHREAD_MUTEX_INITIALIZER;
static int nni_plat_inited = 0;
@@ -28,6 +29,11 @@ static int nni_plat_next = 0;
pthread_condattr_t nni_cvattr;
pthread_mutexattr_t nni_mxattr;
+// We open a /dev/null file descriptor so that we can dup2() it to
+// cause MacOS X to wakeup. This gives us a "safe" close semantic.
+
+int nni_plat_devnull = -1;
+
uint32_t
nni_plat_nextid(void)
{
@@ -228,30 +234,39 @@ nni_plat_init(int (*helper)(void))
if (nni_plat_inited) {
return (0); // fast path
}
+
+ if ((nni_plat_devnull = open("/dev/null", O_RDONLY)) < 0) {
+ return (nni_plat_errno(errno));
+ }
pthread_mutex_lock(&nni_plat_lock);
if (nni_plat_inited) { // check again under the lock to be sure
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (0);
}
if (pthread_condattr_init(&nni_cvattr) != 0) {
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (NNG_ENOMEM);
}
#if !defined(NNG_USE_GETTIMEOFDAY) && NNG_USE_CLOCKID != CLOCK_REALTIME
if (pthread_condattr_setclock(&nni_cvattr, NNG_USE_CLOCKID) != 0) {
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (NNG_ENOMEM);
}
#endif
if (pthread_mutexattr_init(&nni_mxattr) != 0) {
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (NNG_ENOMEM);
}
rv = pthread_mutexattr_settype(&nni_mxattr, PTHREAD_MUTEX_ERRORCHECK);
if (rv != 0) {
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (NNG_ENOMEM);
}
@@ -276,6 +291,7 @@ nni_plat_init(int (*helper)(void))
if (pthread_atfork(NULL, NULL, nni_atfork_child) != 0) {
pthread_mutex_unlock(&nni_plat_lock);
+ (void) close(nni_plat_devnull);
return (NNG_ENOMEM);
}
if ((rv = helper()) == 0) {
@@ -294,6 +310,8 @@ nni_plat_fini(void)
if (nni_plat_inited) {
pthread_mutexattr_destroy(&nni_mxattr);
pthread_condattr_destroy(&nni_cvattr);
+ (void) close(nni_plat_devnull);
+ nni_plat_devnull = -1;
nni_plat_inited = 0;
}
pthread_mutex_unlock(&nni_plat_lock);