master
c 141 lines 3.83 KB
Raw
1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * Originally derived from nbdkit common/utils/exit-with-parent.c
4 * Copyright Red Hat
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * * Neither the name of Red Hat nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * Implement the --exit-with-parent feature on operating systems which
37 * support it.
38 */
39
40 #include "qemu/osdep.h"
41 #include "qemu/exit-with-parent.h"
42
43 #if defined(__linux__)
44
45 #include <sys/prctl.h>
46
47 /*
48 * Send SIGTERM to self when the parent exits. This will cause
49 * qemu_system_killed() to be called.
50 *
51 * PR_SET_PDEATHSIG has been defined since Linux 2.1.57.
52 */
53 int
54 set_exit_with_parent(void)
55 {
56 return prctl(PR_SET_PDEATHSIG, SIGTERM);
57 }
58
59 #elif defined(__FreeBSD__)
60
61 #include <sys/procctl.h>
62
63 /*
64 * Send SIGTERM to self when the parent exits. This will cause
65 * qemu_system_killed() to be called.
66 *
67 * PROC_PDEATHSIG_CTL has been defined since FreeBSD 11.2.
68 */
69 int
70 set_exit_with_parent(void)
71 {
72 const int sig = SIGTERM;
73 return procctl(P_PID, 0, PROC_PDEATHSIG_CTL, (void *) &sig);
74 }
75
76 #elif defined(__APPLE__)
77
78 /* For macOS. */
79
80 #include "qemu/thread.h"
81 #include "qemu/error-report.h"
82 #include "system/runstate.h"
83 #include <sys/event.h>
84
85 static void *
86 exit_with_parent_loop(void *vp)
87 {
88 const pid_t ppid = getppid();
89 int fd;
90 struct kevent kev, res[1];
91 int r;
92
93 /* Register the kevent to wait for ppid to exit. */
94 fd = kqueue();
95 if (fd == -1) {
96 error_report("exit_with_parent_loop: kqueue: %m");
97 return NULL;
98 }
99 EV_SET(&kev, ppid, EVFILT_PROC, EV_ADD | EV_ENABLE, NOTE_EXIT, 0, NULL);
100 if (kevent(fd, &kev, 1, NULL, 0, NULL) == -1) {
101 error_report("exit_with_parent_loop: kevent: %m");
102 close(fd);
103 return NULL;
104 }
105
106 /* Wait for the kevent to happen. */
107 r = kevent(fd, 0, 0, res, 1, NULL);
108 if (r == 1 && res[0].ident == ppid) {
109 /* Behave like Linux and FreeBSD above, as if SIGTERM was sent */
110 qemu_system_killed(SIGTERM, ppid);
111 }
112 close(fd);
113
114 return NULL;
115 }
116
117 int
118 set_exit_with_parent(void)
119 {
120 QemuThread exit_with_parent_thread;
121
122 /*
123 * We have to block waiting for kevent, so that requires that we
124 * start a background thread.
125 */
126 qemu_thread_create(&exit_with_parent_thread,
127 "exit-parent",
128 exit_with_parent_loop, NULL,
129 QEMU_THREAD_DETACHED);
130 return 0;
131 }
132
133 #else /* any platform that doesn't support this function */
134
135 int
136 set_exit_with_parent(void)
137 {
138 g_assert_not_reached();
139 }
140
141 #endif