summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-10-15 09:08:10 +0200
committerHans de Goede <hdegoede@redhat.com>2010-10-15 10:22:37 +0200
commita52324525d5707365c4b6758e5d5b08f21b0ac31 (patch)
treea5faec7270f23d3ab1bf5976b30136fb46f7e66b /server
parentd37adccfa7e4586a68e7da8a225de0a50c6eeff5 (diff)
downloadspice-a52324525d5707365c4b6758e5d5b08f21b0ac31.tar.gz
spice-a52324525d5707365c4b6758e5d5b08f21b0ac31.tar.xz
spice-a52324525d5707365c4b6758e5d5b08f21b0ac31.zip
server: always call read_from_vdi_port() in a while loop
read_from_vdi_port() MUST always be called in a while loop until it returns 0. This is needed because it can cause new data available events and its recursion protection causes those to get lost. Calling it until it returns 0 ensures that all data has been consumed. Example scenario where we can fail to read the available data otherwise: - server/reds.c: vdagent_char_device_wakeup get called by hw/spice-vmc.c because data has arrived from the guest, - hw/spice-vmc.c: vmc_read get calls - If the vmc_read call depletes the current buffer it calls virtio_serial_throttle_port(&svc->port, false) - This causes vmc_have_data to get called, which if in the mean time another buffer has arrived causes vdagent_char_device_wakeup to gets called again (so recursively) - vdagent_char_device_wakeup is protected against recursive calling and ignores the second call (a nasty hack) - if no other data arrives, the arrived data will not get read
Diffstat (limited to 'server')
-rw-r--r--server/reds.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/server/reds.c b/server/reds.c
index a88ca95e..8e630629 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1229,6 +1229,10 @@ static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
}
}
+/* Note this function MUST always be called in a while loop until it
+ returns 0. This is needed because it can cause new data available events
+ and its recursion protection causes those to get lost. Calling it until
+ it returns 0 ensures that all data has been consumed. */
static int read_from_vdi_port(void)
{
// FIXME: UGLY HACK. Result of spice-vmc vmc_read triggering flush of throttled data, and recalling this.
@@ -1665,7 +1669,7 @@ static void reds_main_handle_message(void *opaque, size_t size, uint32_t type, v
agent_start = (SpiceMsgcMainAgentTokens *)message;
reds->agent_state.client_agent_started = TRUE;
reds->agent_state.send_tokens = agent_start->num_tokens; // TODO: sanitize? coming from guest!
- read_from_vdi_port();
+ while (read_from_vdi_port());
break;
}
case SPICE_MSGC_MAIN_AGENT_DATA: {
@@ -1721,7 +1725,7 @@ static void reds_main_handle_message(void *opaque, size_t size, uint32_t type, v
token = (SpiceMsgcMainAgentTokens *)message;
reds->agent_state.send_tokens += token->num_tokens;
- read_from_vdi_port();
+ while (read_from_vdi_port());
break;
}
case SPICE_MSGC_MAIN_ATTACH_CHANNELS: