summary refs log tree commit diff stats
path: root/util/oslib-posix.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2017-02-08 13:22:12 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2017-03-03 16:40:02 +0100
commitd98d407234713d05b77114237f839c43a8152089 (patch)
tree2a4a461d82af63d83f2fdce46eb73de3ac654ba8 /util/oslib-posix.c
parent30f3dda24b2a4cd30f8fbf984ab08ef08eaf5020 (diff)
downloadfocaccia-qemu-d98d407234713d05b77114237f839c43a8152089.tar.gz
focaccia-qemu-d98d407234713d05b77114237f839c43a8152089.zip
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.c33
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);
+}