Commit 7c3370d4fe3fa6cda8655f109e4659afc8ca4269
Committed by
Mark McLoughlin
1 parent
c27ff608
slirp: Avoid zombie processes after fork_exec
Slirp uses fork_exec for spawning service processes, and QEMU uses this for running smbd. As SIGCHLD is not handled, these processes become zombies on termination. Fix this by installing a proper signal handler, but also make sure we disable the signal while waiting on forked network setup/shutdown scripts. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Showing
2 changed files
with
45 additions
and
28 deletions
net.c
... | ... | @@ -1134,38 +1134,46 @@ static int tap_open(char *ifname, int ifname_size) |
1134 | 1134 | |
1135 | 1135 | static int launch_script(const char *setup_script, const char *ifname, int fd) |
1136 | 1136 | { |
1137 | + sigset_t oldmask, mask; | |
1137 | 1138 | int pid, status; |
1138 | 1139 | char *args[3]; |
1139 | 1140 | char **parg; |
1140 | 1141 | |
1141 | - /* try to launch network script */ | |
1142 | - pid = fork(); | |
1143 | - if (pid >= 0) { | |
1144 | - if (pid == 0) { | |
1145 | - int open_max = sysconf (_SC_OPEN_MAX), i; | |
1146 | - for (i = 0; i < open_max; i++) | |
1147 | - if (i != STDIN_FILENO && | |
1148 | - i != STDOUT_FILENO && | |
1149 | - i != STDERR_FILENO && | |
1150 | - i != fd) | |
1151 | - close(i); | |
1152 | - | |
1153 | - parg = args; | |
1154 | - *parg++ = (char *)setup_script; | |
1155 | - *parg++ = (char *)ifname; | |
1156 | - *parg++ = NULL; | |
1157 | - execv(setup_script, args); | |
1158 | - _exit(1); | |
1159 | - } | |
1160 | - while (waitpid(pid, &status, 0) != pid); | |
1161 | - if (!WIFEXITED(status) || | |
1162 | - WEXITSTATUS(status) != 0) { | |
1163 | - fprintf(stderr, "%s: could not launch network script\n", | |
1164 | - setup_script); | |
1165 | - return -1; | |
1142 | + sigemptyset(&mask); | |
1143 | + sigaddset(&mask, SIGCHLD); | |
1144 | + sigprocmask(SIG_BLOCK, &mask, &oldmask); | |
1145 | + | |
1146 | + /* try to launch network script */ | |
1147 | + pid = fork(); | |
1148 | + if (pid == 0) { | |
1149 | + int open_max = sysconf(_SC_OPEN_MAX), i; | |
1150 | + | |
1151 | + for (i = 0; i < open_max; i++) { | |
1152 | + if (i != STDIN_FILENO && | |
1153 | + i != STDOUT_FILENO && | |
1154 | + i != STDERR_FILENO && | |
1155 | + i != fd) { | |
1156 | + close(i); | |
1166 | 1157 | } |
1167 | 1158 | } |
1168 | - return 0; | |
1159 | + parg = args; | |
1160 | + *parg++ = (char *)setup_script; | |
1161 | + *parg++ = (char *)ifname; | |
1162 | + *parg++ = NULL; | |
1163 | + execv(setup_script, args); | |
1164 | + _exit(1); | |
1165 | + } else if (pid > 0) { | |
1166 | + while (waitpid(pid, &status, 0) != pid) { | |
1167 | + /* loop */ | |
1168 | + } | |
1169 | + sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
1170 | + | |
1171 | + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { | |
1172 | + return 0; | |
1173 | + } | |
1174 | + } | |
1175 | + fprintf(stderr, "%s: could not launch network script\n", setup_script); | |
1176 | + return -1; | |
1169 | 1177 | } |
1170 | 1178 | |
1171 | 1179 | static int net_tap_init(VLANState *vlan, const char *model, | ... | ... |
vl.c
... | ... | @@ -4783,7 +4783,12 @@ static void termsig_handler(int signal) |
4783 | 4783 | qemu_system_shutdown_request(); |
4784 | 4784 | } |
4785 | 4785 | |
4786 | -static void termsig_setup(void) | |
4786 | +static void sigchld_handler(int signal) | |
4787 | +{ | |
4788 | + waitpid(-1, NULL, WNOHANG); | |
4789 | +} | |
4790 | + | |
4791 | +static void sighandler_setup(void) | |
4787 | 4792 | { |
4788 | 4793 | struct sigaction act; |
4789 | 4794 | |
... | ... | @@ -4792,6 +4797,10 @@ static void termsig_setup(void) |
4792 | 4797 | sigaction(SIGINT, &act, NULL); |
4793 | 4798 | sigaction(SIGHUP, &act, NULL); |
4794 | 4799 | sigaction(SIGTERM, &act, NULL); |
4800 | + | |
4801 | + act.sa_handler = sigchld_handler; | |
4802 | + act.sa_flags = SA_NOCLDSTOP; | |
4803 | + sigaction(SIGCHLD, &act, NULL); | |
4795 | 4804 | } |
4796 | 4805 | |
4797 | 4806 | #endif |
... | ... | @@ -5918,7 +5927,7 @@ int main(int argc, char **argv, char **envp) |
5918 | 5927 | |
5919 | 5928 | #ifndef _WIN32 |
5920 | 5929 | /* must be after terminal init, SDL library changes signal handlers */ |
5921 | - termsig_setup(); | |
5930 | + sighandler_setup(); | |
5922 | 5931 | #endif |
5923 | 5932 | |
5924 | 5933 | /* Maintain compatibility with multiple stdio monitors */ | ... | ... |