2 * Asynchronous teardown
4 * Copyright IBM, Corp. 2022
7 * Claudio Imbrenda <imbrenda@linux.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
10 * option) any later version. See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include <sys/prctl.h>
19 #include "qemu/async-teardown.h"
21 #ifdef _SC_THREAD_STACK_MIN
22 #define CLONE_STACK_SIZE sysconf(_SC_THREAD_STACK_MIN)
24 #define CLONE_STACK_SIZE 16384
27 static pid_t the_ppid
;
30 * Close all open file descriptors.
32 static void close_all_open_fd(void)
38 #ifdef CONFIG_CLOSE_RANGE
39 int r
= close_range(0, ~0U, 0);
41 /* Success, no need to try other ways. */
46 dir
= opendir("/proc/self/fd");
48 /* If /proc is not mounted, there is nothing that can be done. */
51 /* Avoid closing the directory. */
54 for (de
= readdir(dir
); de
; de
= readdir(dir
)) {
55 fd
= atoi(de
->d_name
);
63 static void hup_handler(int signal
)
65 /* Check every second if this process has been reparented. */
66 while (the_ppid
== getppid()) {
67 /* sleep() is safe to use in a signal handler. */
71 /* At this point the parent process has terminated completely. */
75 static int async_teardown_fn(void *arg
)
77 struct sigaction sa
= { .sa_handler
= hup_handler
};
81 /* Set a meaningful name for this process. */
82 snprintf(name
, 16, "cleanup/%d", the_ppid
);
83 prctl(PR_SET_NAME
, (unsigned long)name
);
86 * Close all file descriptors that might have been inherited from the
87 * main qemu process when doing clone, needed to make libvirt happy.
88 * Not using close_range for increased compatibility with older kernels.
92 /* Set up a handler for SIGHUP and unblock SIGHUP. */
93 sigaction(SIGHUP
, &sa
, NULL
);
94 sigemptyset(&hup_signal
);
95 sigaddset(&hup_signal
, SIGHUP
);
96 sigprocmask(SIG_UNBLOCK
, &hup_signal
, NULL
);
98 /* Ask to receive SIGHUP when the parent dies. */
99 prctl(PR_SET_PDEATHSIG
, SIGHUP
);
102 * Sleep forever, unless the parent process has already terminated. The
103 * only interruption can come from the SIGHUP signal, which in normal
104 * operation is received when the parent process dies.
106 if (the_ppid
== getppid()) {
110 /* At this point the parent process has terminated completely. */
115 * Allocate a new stack of a reasonable size, and return a pointer to its top.
117 static void *new_stack_for_clone(void)
119 size_t stack_size
= CLONE_STACK_SIZE
;
122 /* Allocate a new stack and get a pointer to its top. */
123 stack_ptr
= qemu_alloc_stack(&stack_size
);
124 stack_ptr
+= stack_size
;
130 * Block all signals, start (clone) a new process sharing the address space
131 * with qemu (CLONE_VM), then restore signals.
133 void init_async_teardown(void)
135 sigset_t all_signals
, old_signals
;
139 sigfillset(&all_signals
);
140 sigprocmask(SIG_BLOCK
, &all_signals
, &old_signals
);
141 clone(async_teardown_fn
, new_stack_for_clone(), CLONE_VM
, NULL
);
142 sigprocmask(SIG_SETMASK
, &old_signals
, NULL
);