Use unnamed semaphore of Grand Central Dispatch for macOS.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 29 Nov 2016 02:21:15 +0000 (11:21 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 29 Nov 2016 02:28:33 +0000 (11:28 +0900)
* configure.ac [*-apple-darwin*]: Search dispatch_semaphore_create
and define HAVE_LIB_DISPATCH if found.
* src/npth.c [HAVE_LIB_DISPATCH] (sem_init, sem_post, sem_wait): New.
* src/npth.c (try_sem_open): Remove.
* tests/t-fork.c: Add comments.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
configure.ac
src/npth.c
tests/t-fork.c

index d9c9160..0bd8e04 100644 (file)
@@ -123,7 +123,8 @@ case "${host}" in
        have_ld_version_script=yes
         ;;
     *-apple-darwin*)
-        AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X)
+       AC_SEARCH_LIBS([dispatch_semaphore_create],[dispatch],
+       [AC_DEFINE([HAVE_LIB_DISPATCH],1,[Defined if we have libdispatch])])
         ;;
     *-*-aix*)
        have_fork_unsafe_semaphore=yes
index bfcf0e9..d914a04 100644 (file)
 #include <pthread.h>
 #include <fcntl.h>
 #include <sys/stat.h>
-#include <semaphore.h>
+#ifdef HAVE_LIB_DISPATCH
+# include <dispatch/dispatch.h>
+typedef dispatch_semaphore_t sem_t;
+
+/* This glue code is for macOS which does not have full implementation
+   of POSIX semaphore.  On macOS, using semaphore in Grand Central
+   Dispatch library is better than using the partial implementation of
+   POSIX semaphore where sem_init doesn't work well.
+ */
+
+static int
+sem_init (sem_t *sem, int is_shared, unsigned int value)
+{
+  (void)is_shared;
+  if ((*sem = dispatch_semaphore_create (value)) == NULL)
+    return -1;
+  else
+    return 0;
+}
+
+static int
+sem_post (sem_t *sem)
+{
+  dispatch_semaphore_signal (*sem);
+  return 0;
+}
+
+static int
+sem_wait (sem_t *sem)
+{
+  dispatch_semaphore_wait (*sem, DISPATCH_TIME_FOREVER);
+  return 0;
+}
+#else
+# include <semaphore.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -176,34 +211,6 @@ leave_npth (void)
 #define LEAVE() leave_npth ()
 
 
-static int
-try_sem_open (sem_t **r_sem)
-{
-  sem_t *sem;
-  char name [256];
-  int counter = 0;
-
-  do
-    {
-      snprintf (name, sizeof name - 1, "/npth-sceptre-%lu-%u",
-                (unsigned long)getpid (), counter);
-      name[sizeof name -1] = 0;
-      counter++;
-
-      sem = sem_open (name, (O_CREAT | O_EXCL), (S_IRUSR | S_IWUSR), 1);
-      if (sem != SEM_FAILED)
-        {
-          *r_sem = sem;
-          return 0;
-        }
-      fprintf (stderr, " semOpen(%s): %s\n", name, strerror (errno));
-    }
-  while (errno == EEXIST);
-
-  return -1;
-}
-
-
 int
 npth_init (void)
 {
@@ -220,26 +227,21 @@ npth_init (void)
 
   /* The semaphore is binary.  */
   res = sem_init (sceptre, NPTH_SEMAPHORE_PSHARED, 1);
+  /* There are some versions of operating systems which have sem_init
+     symbol defined but the call actually returns ENOSYS at runtime.
+     We know this problem for older versions of AIX (<= 4.3.3) and
+     macOS.  For macOS, we use semaphore in Grand Central Dispatch
+     library, so ENOSYS doesn't happen.  We only support AIX >= 5.2,
+     where sem_init is supported.
+   */
   if (res < 0)
     {
-      /* Mac OSX and some AIX versions have sem_init but return
-         ENOSYS.  This is allowed according to some POSIX versions but
-         the informative section is quite fuzzy about it.  We resort
-         to sem_open in this case.  */
-      if (errno == ENOSYS)
-        {
-          if (try_sem_open (&sceptre))
-            return errno;
-        }
-      else
-        {
-          /* POSIX.1-2001 defines the semaphore interface but does not
-             specify the return value for success.  Thus we better
-             bail out on error only on a POSIX.1-2008 system.  */
+      /* POSIX.1-2001 defines the semaphore interface but does not
+         specify the return value for success.  Thus we better
+         bail out on error only on a POSIX.1-2008 system.  */
 #if _POSIX_C_SOURCE >= 200809L
-          return errno;
+      return errno;
 #endif
-        }
     }
 
   LEAVE();
index 2f0b181..7ec542c 100644 (file)
 #include <unistd.h>
 #include "t-support.h"
 
+/* This is a test if nPth can allow daemon-like applications
+   initializing earlier.
+
+   For daemon-like applications, ideally, it is expected to call
+   npth_init after fork.  This condition is not satisfied sometimes.
+
+   Failure of this test means nPth implementation doesn't allow
+   npth_init after fork.  In such a case, application should be
+   modified.
+ */
 
 int
 main (int argc, const char *argv[])