mirror of https://github.com/xemu-project/xemu.git
add a service to reap zombies, use it in SLIRP
SLIRP -smb support wants to fork a process and forget about reaping it. To please it, add a generic service to register a process id and let QEMU reap it. In the future it could be enhanced to pass a status, but this would be unused. With this in place, the SIGCHLD signal handler would not stomp on pclose anymore. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
0298141998
commit
4d54ec7898
64
iohandler.c
64
iohandler.c
|
@ -27,6 +27,10 @@
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
#include "qemu-queue.h"
|
#include "qemu-queue.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct IOHandlerRecord {
|
typedef struct IOHandlerRecord {
|
||||||
int fd;
|
int fd;
|
||||||
IOCanReadHandler *fd_read_poll;
|
IOCanReadHandler *fd_read_poll;
|
||||||
|
@ -127,3 +131,63 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reaping of zombies. right now we're not passing the status to
|
||||||
|
anyone, but it would be possible to add a callback. */
|
||||||
|
#ifndef _WIN32
|
||||||
|
typedef struct ChildProcessRecord {
|
||||||
|
int pid;
|
||||||
|
QLIST_ENTRY(ChildProcessRecord) next;
|
||||||
|
} ChildProcessRecord;
|
||||||
|
|
||||||
|
static QLIST_HEAD(, ChildProcessRecord) child_watches =
|
||||||
|
QLIST_HEAD_INITIALIZER(child_watches);
|
||||||
|
|
||||||
|
static QEMUBH *sigchld_bh;
|
||||||
|
|
||||||
|
static void sigchld_handler(int signal)
|
||||||
|
{
|
||||||
|
qemu_bh_schedule(sigchld_bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigchld_bh_handler(void *opaque)
|
||||||
|
{
|
||||||
|
ChildProcessRecord *rec, *next;
|
||||||
|
|
||||||
|
QLIST_FOREACH_SAFE(rec, &child_watches, next, next) {
|
||||||
|
if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) {
|
||||||
|
QLIST_REMOVE(rec, next);
|
||||||
|
qemu_free(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_init_child_watch(void)
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
|
||||||
|
|
||||||
|
act.sa_handler = sigchld_handler;
|
||||||
|
act.sa_flags = SA_NOCLDSTOP;
|
||||||
|
sigaction(SIGCHLD, &act, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_add_child_watch(pid_t pid)
|
||||||
|
{
|
||||||
|
ChildProcessRecord *rec;
|
||||||
|
|
||||||
|
if (!sigchld_bh) {
|
||||||
|
qemu_init_child_watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
QLIST_FOREACH(rec, &child_watches, next) {
|
||||||
|
if (rec->pid == pid) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rec = qemu_mallocz(sizeof(ChildProcessRecord));
|
||||||
|
rec->pid = pid;
|
||||||
|
QLIST_INSERT_HEAD(&child_watches, rec, next);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -67,11 +67,6 @@ static void termsig_handler(int signal, siginfo_t *info, void *c)
|
||||||
qemu_system_killed(info->si_signo, info->si_pid);
|
qemu_system_killed(info->si_signo, info->si_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sigchld_handler(int signal)
|
|
||||||
{
|
|
||||||
waitpid(-1, NULL, WNOHANG);
|
|
||||||
}
|
|
||||||
|
|
||||||
void os_setup_signal_handling(void)
|
void os_setup_signal_handling(void)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
@ -82,10 +77,6 @@ void os_setup_signal_handling(void)
|
||||||
sigaction(SIGINT, &act, NULL);
|
sigaction(SIGINT, &act, NULL);
|
||||||
sigaction(SIGHUP, &act, NULL);
|
sigaction(SIGHUP, &act, NULL);
|
||||||
sigaction(SIGTERM, &act, NULL);
|
sigaction(SIGTERM, &act, NULL);
|
||||||
|
|
||||||
act.sa_handler = sigchld_handler;
|
|
||||||
act.sa_flags = SA_NOCLDSTOP;
|
|
||||||
sigaction(SIGCHLD, &act, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a likely location for support files using the location of the binary.
|
/* Find a likely location for support files using the location of the binary.
|
||||||
|
|
|
@ -214,6 +214,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
||||||
void qemu_set_cloexec(int fd);
|
void qemu_set_cloexec(int fd);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
int qemu_add_child_watch(pid_t pid);
|
||||||
int qemu_eventfd(int pipefd[2]);
|
int qemu_eventfd(int pipefd[2]);
|
||||||
int qemu_pipe(int pipefd[2]);
|
int qemu_pipe(int pipefd[2]);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -119,6 +119,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
char *bptr;
|
char *bptr;
|
||||||
const char *curarg;
|
const char *curarg;
|
||||||
int c, i, ret;
|
int c, i, ret;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
DEBUG_CALL("fork_exec");
|
DEBUG_CALL("fork_exec");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
|
@ -142,7 +143,8 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(fork()) {
|
pid = fork();
|
||||||
|
switch(pid) {
|
||||||
case -1:
|
case -1:
|
||||||
lprint("Error: fork failed: %s\n", strerror(errno));
|
lprint("Error: fork failed: %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
|
@ -206,6 +208,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
qemu_add_child_watch(pid);
|
||||||
if (do_pty == 2) {
|
if (do_pty == 2) {
|
||||||
close(s);
|
close(s);
|
||||||
so->s = master;
|
so->s = master;
|
||||||
|
|
Loading…
Reference in New Issue