blob: 147e39e2c62be977751d67f7772b1b9acbd8722d [file] [log] [blame]
Marcelo Tosattidcc38d12010-10-11 15:31:15 -03001/*
2 * signalfd/eventfd compatibility
3 *
4 * Copyright IBM, Corp. 2008
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
Paolo Bonzini6b620ca2012-01-13 17:44:23 +010012 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030014 */
15
Peter Maydellaafd7582016-01-29 17:49:55 +000016#include "qemu/osdep.h"
Jan Kiszka518420d2013-05-02 10:21:18 +020017#include "qemu/thread.h"
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030018
David CARLIER81b7b1e2020-07-13 14:36:10 +010019#if defined(CONFIG_SIGNALFD)
Kacper Słomiński6bd17dc2021-09-05 03:16:22 +020020#include <sys/signalfd.h>
David CARLIER81b7b1e2020-07-13 14:36:10 +010021#endif
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030022
Mahmoud Mandour7e3a61c2021-03-15 12:58:13 +020023struct sigfd_compat_info {
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030024 sigset_t mask;
25 int fd;
26};
27
28static void *sigwait_compat(void *opaque)
29{
30 struct sigfd_compat_info *info = opaque;
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030031
Tristan Gingold30faaf72011-02-18 14:17:16 +010032 while (1) {
33 int sig;
34 int err;
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030035
Tristan Gingold30faaf72011-02-18 14:17:16 +010036 err = sigwait(&info->mask, &sig);
37 if (err != 0) {
38 if (errno == EINTR) {
39 continue;
40 } else {
41 return NULL;
42 }
43 } else {
44 struct qemu_signalfd_siginfo buffer;
Tristan Gingold30faaf72011-02-18 14:17:16 +010045 memset(&buffer, 0, sizeof(buffer));
46 buffer.ssi_signo = sig;
47
Marc-André Lureaud0dedf22022-04-20 17:26:18 +040048 if (qemu_write_full(info->fd, &buffer, sizeof(buffer)) != sizeof(buffer)) {
49 return NULL;
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030050 }
51 }
Tristan Gingold30faaf72011-02-18 14:17:16 +010052 }
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030053}
54
55static int qemu_signalfd_compat(const sigset_t *mask)
56{
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030057 struct sigfd_compat_info *info;
Jan Kiszka518420d2013-05-02 10:21:18 +020058 QemuThread thread;
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030059 int fds[2];
60
Mahmoud Mandoure0c5a182021-03-15 12:58:14 +020061 info = g_malloc(sizeof(*info));
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030062
Marc-André Lureau81badab2022-04-22 14:45:35 +040063 if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
Mahmoud Mandoure0c5a182021-03-15 12:58:14 +020064 g_free(info);
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030065 return -1;
66 }
67
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030068 memcpy(&info->mask, mask, sizeof(*mask));
69 info->fd = fds[1];
70
Dr. David Alan Gilbert49001162014-01-30 10:20:32 +000071 qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info,
72 QEMU_THREAD_DETACHED);
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030073
74 return fds[0];
75}
76
77int qemu_signalfd(const sigset_t *mask)
78{
79#if defined(CONFIG_SIGNALFD)
80 int ret;
81
Kacper Słomiński6bd17dc2021-09-05 03:16:22 +020082 ret = signalfd(-1, mask, SFD_CLOEXEC);
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030083 if (ret != -1) {
Marcelo Tosattidcc38d12010-10-11 15:31:15 -030084 return ret;
85 }
86#endif
87
88 return qemu_signalfd_compat(mask);
89}