diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2017-02-08 13:22:12 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-03 16:40:02 +0100 |
commit | d98d407234713d05b77114237f839c43a8152089 (patch) | |
tree | 2a4a461d82af63d83f2fdce46eb73de3ac654ba8 /util/oslib-posix.c | |
parent | 30f3dda24b2a4cd30f8fbf984ab08ef08eaf5020 (diff) |
cpus: remove ugly cast on sigbus_handler
The cast is there because sigbus_handler is invoked via sigfd_handler.
But it feels just wrong to use struct qemu_signalfd_siginfo in the
prototype of a function that is passed to sigaction.
Instead, do a simple-minded conversion of qemu_signalfd_siginfo to
siginfo_t.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'util/oslib-posix.c')
-rw-r--r-- | util/oslib-posix.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/util/oslib-posix.c b/util/oslib-posix.c index f63146407f..cd686aae3d 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -603,3 +603,36 @@ void qemu_free_stack(void *stack, size_t sz) munmap(stack, sz); } + +void sigaction_invoke(struct sigaction *action, + struct qemu_signalfd_siginfo *info) +{ + siginfo_t si = { 0 }; + si.si_signo = info->ssi_signo; + si.si_errno = info->ssi_errno; + si.si_code = info->ssi_code; + + /* Convert the minimal set of fields defined by POSIX. + * Positive si_code values are reserved for kernel-generated + * signals, where the valid siginfo fields are determined by + * the signal number. But according to POSIX, it is unspecified + * whether SI_USER and SI_QUEUE have values less than or equal to + * zero. + */ + if (info->ssi_code == SI_USER || info->ssi_code == SI_QUEUE || + info->ssi_code <= 0) { + /* SIGTERM, etc. */ + si.si_pid = info->ssi_pid; + si.si_uid = info->ssi_uid; + } else if (info->ssi_signo == SIGILL || info->ssi_signo == SIGFPE || + info->ssi_signo == SIGSEGV || info->ssi_signo == SIGBUS) { + si.si_addr = (void *)(uintptr_t)info->ssi_addr; + } else if (info->ssi_signo == SIGCHLD) { + si.si_pid = info->ssi_pid; + si.si_status = info->ssi_status; + si.si_uid = info->ssi_uid; + } else if (info->ssi_signo == SIGIO) { + si.si_band = info->ssi_band; + } + action->sa_sigaction(info->ssi_signo, &si, NULL); +} |