>From 861be2ff3c860e180db90f7f6928fbb427d7971a Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 13 Mar 2011 21:58:24 +0200 Subject: [PATCH 4/6] qxl vga update: don't read, preventing pipe loop of death --- hw/qxl.c | 44 +++++++++++++++++++++++++------------------- ui/spice-display.h | 1 + 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index d040bee..dfbb740 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -356,7 +356,7 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) QXLCommand *cmd; int notify; int r; - unsigned char req, ack; + unsigned char req; switch (qxl->mode) { case QXL_MODE_VGA: @@ -364,21 +364,21 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) /* TODO -- 1. check write+read return codes. retry upon e.g. EINTR */ /* TODO -- 2. change the imlpementation inside qemu_spice_create_update (option rename+add functions) */ - req = QXL_SERVER_CREATE_UPDATE; - r = write(qxl->pipe[1], &req , 1); - ASSERT(r == 1); - ack = 0; - r = read(qxl->pipe_out[0], &ack, 1); - ASSERT(r == 1); - ASSERT(ack == QXL_SERVER_CREATE_UPDATE); // ack==req update = qxl->ssd.update; - //update = qemu_spice_create_update(&qxl->ssd); - if (update == NULL) { + if (update != NULL) { + qxl->ssd.update = NULL; + *ext = update->ext; + qxl_log_command(qxl, "vga", ext); + return true; + } else { + if (!qxl->ssd.waiting_for_update) { + qxl->ssd.waiting_for_update = 1; + req = QXL_SERVER_CREATE_UPDATE; + r = write(qxl->pipe[1], &req , 1); + ASSERT(r == 1); + } return false; } - *ext = update->ext; - qxl_log_command(qxl, "vga", ext); - return true; case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: case QXL_MODE_UNDEFINED: @@ -611,6 +611,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d) qemu_spice_create_host_primary(&d->ssd); d->mode = QXL_MODE_VGA; memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); + d->ssd.waiting_for_update = 0; } static void qxl_exit_vga_mode(PCIQXLDevice *d) @@ -1084,6 +1085,7 @@ static void pipe_read(void *opaque) PCIQXLDevice *d = opaque; unsigned char cmd; int len, again = 1, set_irq_done = 0; + int create_update = 0; do { cmd = 0; @@ -1091,6 +1093,9 @@ static void pipe_read(void *opaque) if ((len < 0) && (errno == EINTR)) { continue; } + if (len <= 0) { + break; + } switch (cmd) { case QXL_SERVER_SET_IRQ: if (set_irq_done == 0) { @@ -1100,16 +1105,19 @@ static void pipe_read(void *opaque) } break; case QXL_SERVER_CREATE_UPDATE: - again = 0; - d->ssd.update = qemu_spice_create_update(&d->ssd); - len = write(d->pipe_out[1], &cmd, 1); - ASSERT(len == 1); + create_update = 1; break; default: fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd); abort(); } } while (again); + if (create_update) { + if (d->ssd.update == NULL) { + d->ssd.update = qemu_spice_create_update(&d->ssd); + } + d->ssd.waiting_for_update = 0; + } } static void qxl_send_events(PCIQXLDevice *d, uint32_t events) @@ -1145,14 +1153,12 @@ static void init_pipe_signaling(PCIQXLDevice *d) return; } -#if 0 // why non-blocking ? code does not check that case #ifdef CONFIG_IOTHREAD fcntl(d->pipe[0], F_SETFL, O_NONBLOCK); #else fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */); #endif fcntl(d->pipe[1], F_SETFL, O_NONBLOCK); -#endif //(if 0) fcntl(d->pipe[0], F_SETOWN, getpid()); diff --git a/ui/spice-display.h b/ui/spice-display.h index e1fc398..37ce297 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -48,6 +48,7 @@ typedef struct SimpleSpiceDisplay { /* ssd updates (one request/command at a time) */ struct SimpleSpiceUpdate *update; + int waiting_for_update; } SimpleSpiceDisplay; typedef struct SimpleSpiceUpdate { -- 1.7.4.1