Update Red Hat Copyright Notices
[nbdkit.git] / common / utils / exit-with-parent.c
blobb57c40b8bbee34e6e80ee2a33792a279fc5ebe80
1 /* nbdkit
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 /* Implement the --exit-with-parent feature on operating systems which
34 * support it.
37 #include <config.h>
39 #include <stdlib.h>
40 #include <stdbool.h>
41 #include <signal.h>
43 #ifdef HAVE_SYS_PRCTL_H
44 #include <sys/prctl.h>
45 #endif
47 #ifdef HAVE_SYS_PROCCTL_H
48 #include <sys/procctl.h>
49 #endif
51 #if defined (HAVE_SYS_PRCTL_H) && defined (PR_SET_PDEATHSIG)
53 /* For Linux >= 2.1.57. */
55 int
56 set_exit_with_parent (void)
58 return prctl (PR_SET_PDEATHSIG, SIGTERM);
61 bool
62 can_exit_with_parent (void)
64 return true;
67 #elif defined (HAVE_SYS_PROCCTL_H) && defined (PROC_PDEATHSIG_CTL)
69 /* For FreeBSD >= 11.2 */
71 int
72 set_exit_with_parent (void)
74 const int sig = SIGTERM;
75 return procctl (P_PID, 0, PROC_PDEATHSIG_CTL, (void*) &sig);
78 bool
79 can_exit_with_parent (void)
81 return true;
84 #elif defined (__APPLE__)
86 /* For macOS. */
88 #include <unistd.h>
89 #include <errno.h>
90 #include <sys/event.h>
91 #include <pthread.h>
93 #include "nbdkit-plugin.h"
95 static void *
96 exit_with_parent_loop (void *vp)
98 const pid_t ppid = getppid ();
99 int fd;
100 struct kevent kev, res[1];
101 int r;
103 nbdkit_debug ("macOS: --exit-with-parent: "
104 "registering exit with parent for ppid %d",
105 (int) ppid);
107 /* Register the kevent to wait for ppid to exit. */
108 fd = kqueue ();
109 if (fd == -1) {
110 nbdkit_error ("exit_with_parent_loop: kqueue: %m");
111 return NULL;
113 EV_SET (&kev, ppid, EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
114 if (kevent (fd, &kev, 1, NULL, 0, NULL) == -1) {
115 nbdkit_error ("exit_with_parent_loop: kevent: %m");
116 close (fd);
117 return NULL;
120 /* Wait for the kevent to happen. */
121 r = kevent (fd, 0, 0, res, 1, NULL);
122 if (r == 1 && res[0].ident == ppid) {
123 /* Shut down the whole process when the parent dies. */
124 nbdkit_debug ("macOS: --exit-with-parent: "
125 "exit because parent process died");
126 nbdkit_shutdown ();
129 return NULL;
133 set_exit_with_parent (void)
135 int r;
136 pthread_attr_t attrs;
137 pthread_t exit_with_parent_thread;
139 /* We have to block waiting for kevent, so that requires that we
140 * start a background thread.
142 pthread_attr_init (&attrs);
143 pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED);
144 r = pthread_create (&exit_with_parent_thread, NULL,
145 exit_with_parent_loop, NULL);
146 if (r != 0) {
147 errno = r;
148 return -1;
151 return 0;
154 bool
155 can_exit_with_parent (void)
157 return true;
160 #else /* any platform that doesn't support this function */
163 set_exit_with_parent (void)
165 abort ();
168 bool
169 can_exit_with_parent (void)
171 return false;
174 #endif