[Libguestfs] [PATCH nbdkit 02/10] freebsd: Implement --exit-with-parent on FreeBSD ≥ 11.2.

Richard W.M. Jones rjones at redhat.com
Sun Aug 12 08:51:17 UTC 2018


See also: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
---
 common/include/Makefile.am        |  5 +-
 common/include/exit-with-parent.h | 80 +++++++++++++++++++++++++++++++
 configure.ac                      |  2 +-
 docs/nbdkit-captive.pod           | 12 +++--
 src/Makefile.am                   |  3 +-
 src/main.c                        | 13 ++---
 tests/Makefile.am                 |  9 +++-
 tests/test-exit-with-parent.c     |  7 +--
 tests/test-layers.c               |  7 +--
 9 files changed, 109 insertions(+), 29 deletions(-)

diff --git a/common/include/Makefile.am b/common/include/Makefile.am
index 4ce1723..a882ff9 100644
--- a/common/include/Makefile.am
+++ b/common/include/Makefile.am
@@ -32,8 +32,9 @@
 
 include $(top_srcdir)/common-rules.mk
 
-# These headers contain only common code shared by plugins and
-# filters.  They are not installed.
+# These headers contain only common code shared by the core server,
+# plugins and/or filters.  They are not installed.
 EXTRA_DIST = \
+	exit-with-parent.h \
 	ispowerof2.h \
 	iszero.h
diff --git a/common/include/exit-with-parent.h b/common/include/exit-with-parent.h
new file mode 100644
index 0000000..cb4bc9b
--- /dev/null
+++ b/common/include/exit-with-parent.h
@@ -0,0 +1,80 @@
+/* nbdkit
+ * Copyright (C) 2013-2018 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Implement the --exit-with-parent feature on operating systems which
+ * support it.
+ */
+
+#ifndef NBDKIT_EXIT_WITH_PARENT_H
+#define NBDKIT_EXIT_WITH_PARENT_H
+
+#include <config.h>
+
+#include <signal.h>
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
+#ifdef HAVE_SYS_PROCCTL_H
+#include <sys/procctl.h>
+#endif
+
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_PDEATHSIG)
+
+/* For Linux >= 2.1.57. */
+
+static inline int
+set_exit_with_parent (void)
+{
+  return prctl (PR_SET_PDEATHSIG, SIGTERM);
+}
+
+#define HAVE_EXIT_WITH_PARENT 1
+
+#elif defined(HAVE_SYS_PROCCTL_H) && defined(PROC_PDEATHSIG_CTL)
+
+/* For FreeBSD >= 11.2 */
+
+static inline int
+set_exit_with_parent (void)
+{
+  const int sig = SIGTERM;
+  return procctl (P_PID, 0, PROC_PDEATHSIG_CTL, (void*) &sig);
+}
+
+#define HAVE_EXIT_WITH_PARENT 1
+
+#endif
+
+#endif /* NBDKIT_INTERNAL_H */
diff --git a/configure.ac b/configure.ac
index 91473e8..b9bb220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -129,7 +129,7 @@ dnl restore CFLAGS
 CFLAGS="${acx_nbdkit_save_CFLAGS}"
 
 dnl Check for other headers, all optional.
-AC_CHECK_HEADERS([selinux/selinux.h sys/prctl.h])
+AC_CHECK_HEADERS([selinux/selinux.h sys/prctl.h sys/procctl.h])
 
 dnl Check support for setsockcreatecon_raw (part of SELinux).
 AC_CHECK_LIB([selinux], [setsockcreatecon_raw], [], [:])
diff --git a/docs/nbdkit-captive.pod b/docs/nbdkit-captive.pod
index 5b7eff0..6db9520 100644
--- a/docs/nbdkit-captive.pod
+++ b/docs/nbdkit-captive.pod
@@ -103,20 +103,22 @@ I<--exit-with-parent> is incompatible with forking into the background
 (because when we fork into the background we lose track of the parent
 process).  Therefore I<-f> / I<--foreground> is implied.
 
-This is currently implemented using a feature of the Linux kernel, so
-it requires a Linux build of nbdkit and won't work on other operating
-systems (patches welcome to make it work).
+This is currently implemented using a non-POSIX feature available in
+S<Linux ≥ 2.1.57> and S<FreeBSD ≥ 11.2>, so it won't work on other
+operating systems (patches welcome to make it work).
 
 If the parent application is multithreaded, then (in the Linux
 implementation) if the parent I<thread> exits, that will cause nbdkit
 to exit.  Thus in multithreaded applications you usually want to run
 C<nbdkit --exit-with-parent> only from the main thread (unless you
 actually want nbdkit to exit with the thread, but that may not work
-reliably if we extend the implementation to other operating systems).
+reliably on all operating systems).
 
 =head1 SEE ALSO
 
-L<nbdkit(1)>.
+L<nbdkit(1)>,
+L<prctl(2)> (on Linux),
+L<procctl(2)> (on FreeBSD).
 
 =head1 AUTHORS
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 84ef477..ae7dcc3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,7 +62,8 @@ nbdkit_CPPFLAGS = \
 	-Dfilterdir=\"$(filterdir)\" \
 	-Dsbindir=\"$(sbindir)\" \
 	-Dsysconfdir=\"$(sysconfdir)\" \
-	-I$(top_srcdir)/include
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/common/include
 nbdkit_CFLAGS = \
 	-pthread \
 	$(WARNINGS_CFLAGS) \
diff --git a/src/main.c b/src/main.c
index 4d8a92b..c6f0878 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,15 +50,12 @@
 #include <assert.h>
 #include <syslog.h>
 
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
 #include <pthread.h>
 
 #include <dlfcn.h>
 
 #include "internal.h"
+#include "exit-with-parent.h"
 
 #define FIRST_SOCKET_ACTIVATION_FD 3 /* defined by systemd ABI */
 
@@ -266,7 +263,7 @@ main (int argc, char *argv[])
       break;
 
     case EXIT_WITH_PARENT_OPTION:
-#ifdef PR_SET_PDEATHSIG
+#ifdef HAVE_EXIT_WITH_PARENT
       exit_with_parent = 1;
       foreground = 1;
       break;
@@ -539,10 +536,10 @@ main (int argc, char *argv[])
   /* Implement --exit-with-parent early in case plugin initialization
    * takes a long time and the parent exits during that time.
    */
-#ifdef PR_SET_PDEATHSIG
+#ifdef HAVE_EXIT_WITH_PARENT
   if (exit_with_parent) {
-    if (prctl (PR_SET_PDEATHSIG, SIGTERM) == -1) {
-      perror ("prctl: PR_SET_PDEATHSIG");
+    if (set_exit_with_parent () == -1) {
+      perror ("nbdkit: --exit-with-parent");
       exit (EXIT_FAILURE);
     }
   }
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 86bef71..e4a28d5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -175,8 +175,12 @@ endif HAVE_CXX
 check_PROGRAMS += test-exit-with-parent
 TESTS += test-exit-with-parent
 
-test_exit_with_parent_SOURCES = test-exit-with-parent.c test.h
-test_exit_with_parent_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
+test_exit_with_parent_SOURCES = \
+	test-exit-with-parent.c test.h
+test_exit_with_parent_CPPFLAGS = \
+	-I$(top_srcdir)/common/include
+test_exit_with_parent_CFLAGS = \
+	$(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
 
 # PKI files for the TLS tests.
 check_DATA += pki/.stamp
@@ -530,6 +534,7 @@ test_layers_SOURCES = \
 	test-layers.c \
 	$(top_srcdir)/src/protocol.h
 test_layers_CPPFLAGS = \
+	-I$(top_srcdir)/common/include \
 	-I$(top_srcdir)/src
 test_layers_CFLAGS = \
 	$(WARNINGS_CFLAGS) \
diff --git a/tests/test-exit-with-parent.c b/tests/test-exit-with-parent.c
index 358d64f..d364884 100644
--- a/tests/test-exit-with-parent.c
+++ b/tests/test-exit-with-parent.c
@@ -43,10 +43,7 @@
 #include <sys/wait.h>
 #include <errno.h>
 
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
+#include "exit-with-parent.h"
 #include "test.h"
 
 static char pidpath[] = "/tmp/nbdkitpidXXXXXX";
@@ -56,7 +53,7 @@ static void run_test (void);
 int
 main (int argc, char *argv[])
 {
-#ifndef PR_SET_PDEATHSIG
+#ifndef HAVE_EXIT_WITH_PARENT
   printf ("--exit-with-parent is not implemented on this platform, skipping\n");
   exit (77);
 #else
diff --git a/tests/test-layers.c b/tests/test-layers.c
index b83fad6..ee425ea 100644
--- a/tests/test-layers.c
+++ b/tests/test-layers.c
@@ -57,12 +57,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
 #include <pthread.h>
 
+#include "exit-with-parent.h"
 #include "protocol.h"           /* From nbdkit core. */
 
 /* Declare program_name. */
@@ -97,7 +94,7 @@ main (int argc, char *argv[])
   struct reply reply;
   char data[512];
 
-#ifndef PR_SET_PDEATHSIG
+#ifndef HAVE_EXIT_WITH_PARENT
   printf ("%s: this test requires --exit-with-parent functionality\n",
           program_name);
   exit (77);
-- 
2.18.0




More information about the Libguestfs mailing list