qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/2] Use fd signal trick to break us out of select; do not sigwait
@ 2008-08-26 14:21 Ian Jackson
  2008-08-26 14:42 ` [Qemu-devel] [PATCH 2/2] Introduce #define QEMU_ASYNC_EVENTLOOP to simplify #ifdefs Ian Jackson
  2008-08-28 20:16 ` [Qemu-devel] [PATCH 1/2] Use fd signal trick to break us out of select; do not sigwait Anthony Liguori
  0 siblings, 2 replies; 7+ messages in thread
From: Ian Jackson @ 2008-08-26 14:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: ian.jackson

* Use of SIGUSR2 to interrupt select() does not work because signals
  which arrive just before entry to select() do not interrupt it.

* The sigwait approach to detecting aio does not work properly because
  some versions of glibc forget to block signals on the private aio
  thread under some hard-to-reproduce conditions.  This means that
  blocking SIGUSR2 is ineffective; the signals can be lost and the
  program can block in sigwait (!)

So instead we use the time-honoured self-pipe trick: in the signal
handler we write to a pipe, which we select on when we want to wait
for the signal, and which we read from (to empty out) just before
actually doing the `top half' processing which deals with the condition
to which the signal relates.

We use the existing fd handler infrastructure to run the desired
completion code out of the main event loop; in the aio completion wait
we use a cut-down version of the same arrangements.

(Cherry picked from qemu-xen ef9633e1290d055543136e136b6b7f59d863a601
 Conflicts: block-raw-posix.c)

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 block-raw-posix.c |   50 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/block-raw-posix.c b/block-raw-posix.c
index 96edab4..94928c0 100644
--- a/block-raw-posix.c
+++ b/block-raw-posix.c
@@ -23,6 +23,8 @@
  */
 #include "qemu-common.h"
 #if !defined(QEMU_IMG) && !defined(QEMU_NBD)
+#include "qemu-char.h"
+#include "qemu_socket.h"
 #include "qemu-timer.h"
 #include "exec-all.h"
 #endif
@@ -441,10 +443,14 @@ typedef struct RawAIOCB {
 static int aio_sig_num = SIGUSR2;
 static RawAIOCB *first_aio; /* AIO issued */
 static int aio_initialized = 0;
+static int aio_sig_pipe[2];
 
 static void aio_signal_handler(int signum)
 {
 #if !defined(QEMU_IMG) && !defined(QEMU_NBD)
+    int e;
+    e = errno;
+    write(aio_sig_pipe[1],"",1); /* ignore errors as they should be EAGAIN */
     CPUState *env = cpu_single_env;
     if (env) {
         /* stop the currently executing cpu because a timer occured */
@@ -455,12 +461,34 @@ static void aio_signal_handler(int signum)
         }
 #endif
     }
+    errno = e;
 #endif
 }
 
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
+static void qemu_aio_sig_pipe_read(void *opaque_ignored) {
+    qemu_aio_poll();
+}
+#endif
+
 void qemu_aio_init(void)
 {
     struct sigaction act;
+    int ret;
+
+    ret = pipe(aio_sig_pipe);
+    if (ret) { perror("qemu_aio_init pipe failed"); exit(-1); }
+    fcntl(aio_sig_pipe[0], F_SETFL, O_NONBLOCK);
+    fcntl(aio_sig_pipe[1], F_SETFL, O_NONBLOCK);
+
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
+    ret = qemu_set_fd_handler2(aio_sig_pipe[0], NULL,
+                               qemu_aio_sig_pipe_read, NULL, NULL);
+    if (ret) {
+        fputs("qemu_aio_init set_fd_handler failed\n",stderr);
+        exit(-1);
+    }
+#endif
 
     aio_initialized = 1;
 
@@ -488,6 +516,12 @@ void qemu_aio_poll(void)
     RawAIOCB *acb, **pacb;
     int ret;
 
+    /* eat any pending signal notifications */
+    {
+        char dummy_buf[16];
+        read(aio_sig_pipe[0],dummy_buf,sizeof(dummy_buf));
+    }
+
     for(;;) {
         pacb = &first_aio;
         for(;;) {
@@ -536,37 +570,29 @@ void qemu_aio_flush(void)
 }
 
 /* wait until at least one AIO was handled */
-static sigset_t wait_oset;
 
 void qemu_aio_wait_start(void)
 {
-    sigset_t set;
-
     if (!aio_initialized)
         qemu_aio_init();
-    sigemptyset(&set);
-    sigaddset(&set, aio_sig_num);
-    sigprocmask(SIG_BLOCK, &set, &wait_oset);
 }
 
 void qemu_aio_wait(void)
 {
-    sigset_t set;
-    int nb_sigs;
+    fd_set check;
 
 #if !defined(QEMU_IMG) && !defined(QEMU_NBD)
     if (qemu_bh_poll())
         return;
 #endif
-    sigemptyset(&set);
-    sigaddset(&set, aio_sig_num);
-    sigwait(&set, &nb_sigs);
+    FD_ZERO(&check);
+    FD_SET(aio_sig_pipe[0], &check);
+    select(aio_sig_pipe[0]+1, &check,0,&check, 0);
     qemu_aio_poll();
 }
 
 void qemu_aio_wait_end(void)
 {
-    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
 }
 
 static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
-- 
1.4.4.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2008-09-07  2:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-26 14:21 [Qemu-devel] [PATCH 1/2] Use fd signal trick to break us out of select; do not sigwait Ian Jackson
2008-08-26 14:42 ` [Qemu-devel] [PATCH 2/2] Introduce #define QEMU_ASYNC_EVENTLOOP to simplify #ifdefs Ian Jackson
2008-08-28 20:18   ` Anthony Liguori
2008-08-29  9:31     ` Ian Jackson
2008-09-07  2:45       ` Anthony Liguori
2008-08-28 20:16 ` [Qemu-devel] [PATCH 1/2] Use fd signal trick to break us out of select; do not sigwait Anthony Liguori
2008-08-29  9:25   ` Ian Jackson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).