Fix for semaphore access by child.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 5 Jul 2016 08:28:38 +0000 (17:28 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 5 Jul 2016 08:28:38 +0000 (17:28 +0900)
* configure.ac (HAVE_FORK_UNSAFE_SEMAPHORE): New.
* src/npth.c (sem_init): Use NPTH_SEMAPHORE_PSHARED.
* tests/t-fork.c: New.

--

Thanks to Uldis An┼ímits.
GnuPG-bug-id: 2260
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
configure.ac
src/npth.c
tests/Makefile.am
tests/t-fork.c [new file with mode: 0644]

index ffc9f7d..ee35e93 100644 (file)
@@ -125,9 +125,15 @@ case "${host}" in
     *-apple-darwin*)
         AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X)
         ;;
+    *-*-aix*)
+       have_fork_unsafe_semaphore=yes
+        ;;
 esac
 
 AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
+if test "$have_fork_unsafe_semaphore" = yes; then
+   AC_DEFINE(HAVE_FORK_UNSAFE_SEMAPHORE, 1, [Defined if we have fork-unsafe semaphore])
+fi
 
 # Set some default values
 config_libs="-lnpth"
index 7de6c9d..c647c26 100644 (file)
 static sem_t sceptre_buffer;
 static sem_t *sceptre = &sceptre_buffer;
 
+/* Configure defines HAVE_FORK_UNSAFE_SEMAPHORE if child process can't
+   access non-shared unnamed semaphore which is created by its parent.
+
+   We use unnamed semaphore (if available) for the global lock.  The
+   specific semaphore is only valid for those threads in a process,
+   and it is no use by other processes.  Thus, PSHARED argument for
+   sem_init is naturally 0.
+
+   However, there are daemon-like applications which use fork after
+   npth's initialization by npth_init.  In this case, a child process
+   uses the semaphore which was created by its parent process, while
+   parent does nothing with the semaphore.  In some system (e.g. AIX),
+   access by child process to non-shared unnamed semaphore is
+   prohibited.  For such a system, HAVE_FORK_UNSAFE_SEMAPHORE should
+   be defined, so that unnamed semaphore will be created with the
+   option PSHARED=1.  The purpose of the setting of PSHARED=1 is only
+   for allowing the access of the lock by child process.  For NPTH, it
+   does not mean any other interactions between processes.
+
+ */
+#ifdef HAVE_FORK_UNSAFE_SEMAPHORE
+#define NPTH_SEMAPHORE_PSHARED 1
+#else
+#define NPTH_SEMAPHORE_PSHARED 0
+#endif
+
 /* The main thread is the active thread at the time pth_init was
    called.  As of now it is only useful for debugging.  The volatile
    make sure the compiler does not eliminate this set but not used
@@ -181,8 +207,8 @@ npth_init (void)
      sem_init.  */
   errno = 0;
 
-  /* The semaphore is not shared and binary.  */
-  res = sem_init (sceptre, 0, 1);
+  /* The semaphore is binary.  */
+  res = sem_init (sceptre, NPTH_SEMAPHORE_PSHARED, 1);
   if (res < 0)
     {
       /* Mac OSX and some AIX versions have sem_init but return
index 0dd436e..2a0542b 100644 (file)
@@ -40,6 +40,7 @@ else
 AM_CPPFLAGS = -I../src -D_POSIX_C_SOURCE=200112L
 AM_LDFLAGS =
 LDADD = ../src/libnpth.la $(LIBSOCKET) $(LIB_CLOCK_GETTIME)
+TESTS += t-fork
 endif
 
 noinst_HEADERS = t-support.h
diff --git a/tests/t-fork.c b/tests/t-fork.c
new file mode 100644 (file)
index 0000000..2f0b181
--- /dev/null
@@ -0,0 +1,49 @@
+/* t-fork.c
+ * Copyright 2016 g10 Code GmbH
+ *
+ * This file is free software; as a special exception the author gives
+ * unlimited permission to copy and/or distribute it, with or without
+ * modifications, as long as this notice is preserved.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "t-support.h"
+
+
+int
+main (int argc, const char *argv[])
+{
+  int rc;
+  pid_t pid;
+
+  if (argc >= 2 && !strcmp (argv[1], "--verbose"))
+    opt_verbose = 1;
+
+  rc = npth_init ();
+  fail_if_err (rc);
+
+  pid = fork ();
+  if (pid == (pid_t)-1)
+    fail_msg ("fork failed");
+  else if (pid)
+   {
+     int status;
+
+     info_msg ("forked");
+     wait (&status);
+     fail_if_err (status);
+   }
+  else
+    {
+      info_msg ("child exit");
+      npth_usleep (1000);     /* Let NPTH enter, sleep, and leave.  */
+    }
+
+  return 0;
+}