Set up signalfd under !CONFIG_IOTHREAD

Will be required for SIGBUS handling. For obvious reasons, this will
remain a nop on Windows hosts.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
Jan Kiszka 2011-02-01 22:15:56 +01:00 committed by Marcelo Tosatti
parent 9a36085b86
commit d0f294cec0
2 changed files with 65 additions and 54 deletions

View File

@ -141,7 +141,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y))
common-obj-y += iov.o acl.o
common-obj-$(CONFIG_THREAD) += qemu-thread.o
common-obj-$(CONFIG_IOTHREAD) += compatfd.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o

117
cpus.c
View File

@ -227,6 +227,59 @@ static void dummy_signal(int sig)
{
}
/* If we have signalfd, we mask out the signals we want to handle and then
* use signalfd to listen for them. We rely on whatever the current signal
* handler is to dispatch the signals when we receive them.
*/
static void sigfd_handler(void *opaque)
{
int fd = (unsigned long) opaque;
struct qemu_signalfd_siginfo info;
struct sigaction action;
ssize_t len;
while (1) {
do {
len = read(fd, &info, sizeof(info));
} while (len == -1 && errno == EINTR);
if (len == -1 && errno == EAGAIN) {
break;
}
if (len != sizeof(info)) {
printf("read from sigfd returned %zd: %m\n", len);
return;
}
sigaction(info.ssi_signo, NULL, &action);
if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
action.sa_sigaction(info.ssi_signo,
(siginfo_t *)&info, NULL);
} else if (action.sa_handler) {
action.sa_handler(info.ssi_signo);
}
}
}
static int qemu_signalfd_init(sigset_t mask)
{
int sigfd;
sigfd = qemu_signalfd(&mask);
if (sigfd == -1) {
fprintf(stderr, "failed to create signalfd\n");
return -errno;
}
fcntl_setfl(sigfd, O_NONBLOCK);
qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
(void *)(unsigned long) sigfd);
return 0;
}
static void sigbus_reraise(void);
static void qemu_kvm_eat_signals(CPUState *env)
@ -330,6 +383,17 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
int qemu_init_main_loop(void)
{
#ifndef _WIN32
sigset_t blocked_signals;
int ret;
sigemptyset(&blocked_signals);
ret = qemu_signalfd_init(blocked_signals);
if (ret) {
return ret;
}
#endif
cpu_set_debug_excp_handler(cpu_debug_handler);
return qemu_event_init();
@ -426,41 +490,6 @@ static QemuCond qemu_system_cond;
static QemuCond qemu_pause_cond;
static QemuCond qemu_work_cond;
/* If we have signalfd, we mask out the signals we want to handle and then
* use signalfd to listen for them. We rely on whatever the current signal
* handler is to dispatch the signals when we receive them.
*/
static void sigfd_handler(void *opaque)
{
int fd = (unsigned long) opaque;
struct qemu_signalfd_siginfo info;
struct sigaction action;
ssize_t len;
while (1) {
do {
len = read(fd, &info, sizeof(info));
} while (len == -1 && errno == EINTR);
if (len == -1 && errno == EAGAIN) {
break;
}
if (len != sizeof(info)) {
printf("read from sigfd returned %zd: %m\n", len);
return;
}
sigaction(info.ssi_signo, NULL, &action);
if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
action.sa_sigaction(info.ssi_signo,
(siginfo_t *)&info, NULL);
} else if (action.sa_handler) {
action.sa_handler(info.ssi_signo);
}
}
}
static void cpu_signal(int sig)
{
if (cpu_single_env) {
@ -532,24 +561,6 @@ static sigset_t block_io_signals(void)
return set;
}
static int qemu_signalfd_init(sigset_t mask)
{
int sigfd;
sigfd = qemu_signalfd(&mask);
if (sigfd == -1) {
fprintf(stderr, "failed to create signalfd\n");
return -errno;
}
fcntl_setfl(sigfd, O_NONBLOCK);
qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
(void *)(unsigned long) sigfd);
return 0;
}
int qemu_init_main_loop(void)
{
int ret;