summaryrefslogtreecommitdiffstats
path: root/server/reds.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-03-31 19:13:28 +0200
committerHans de Goede <hdegoede@redhat.com>2011-04-04 11:22:24 +0200
commitf8e6dc78c7e71a3744be380350a55ad98f75def7 (patch)
tree1e14886fa37287fbe21dc7e18f087596ad0d5735 /server/reds.c
parentc23141739309d8a59c467cc8bd0df027fa899a5b (diff)
downloadspice-f8e6dc78c7e71a3744be380350a55ad98f75def7.tar.gz
spice-f8e6dc78c7e71a3744be380350a55ad98f75def7.tar.xz
spice-f8e6dc78c7e71a3744be380350a55ad98f75def7.zip
server: Don't reset agent state when the client disconnects
We were calling reds_reset_vdp on client disconnect, which is not a good idea. reds_reset_vdp does 3 things: 1) It resets the state related to reading chunks from the spicevmc virtio port. If the client disconnects while the guest agent is in the middle of sending a chunk, this will lead to an inconsistent state, and lots of printing of "dispatch_vdi_port_data: invalid port" messages caused by this inconsistent state sometimes followed by a segfault. This can be triggered by copy and pasting something large (say a screenshot) from the guest to the spice-gtk client, as the spice-gtk client currently has a bug causing it to crash when receiving a multi chunk vdagent messages. Without this patch (and with the spice-gtk bug present) I can consistently reproduce this. 2) It clears any buffered writes from the client to the guest still pending because the virtio port cannot consume data fast enough. Since the agent itself is still running fine, throwing away writes for it because the client has disconnected makes no sense. Esp, since on clean exit the client may very well send a clipboard release message directly before closing the connection, and this may get lost this way. 3) It sets client_agent_started to false, this is the only thing which actually makes sense to do on client disconnect. Note that since we no longer reset the vdp state on client disconnect, we must now reset it on agent disconnect even if we don't have a client. So the reds_reset_vdp call in reds_agent_remove() gets moved to the top, above both the agent_state.connected and reds->peer checks which will both fail in the no client case.
Diffstat (limited to 'server/reds.c')
-rw-r--r--server/reds.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/server/reds.c b/server/reds.c
index 288174e1..705316bb 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -601,7 +601,7 @@ void reds_disconnect()
if (sif->state) {
sif->state(vdagent, reds->agent_state.connected);
}
- reds_reset_vdp();
+ reds->agent_state.client_agent_started = FALSE;
}
reds_shatdown_channels();
@@ -703,6 +703,10 @@ static void reds_agent_remove()
SpiceCharDeviceInstance *sin = vdagent;
SpiceCharDeviceInterface *sif;
+ if (!reds->mig_target) {
+ reds_reset_vdp();
+ }
+
if (!reds->agent_state.connected) {
return;
}
@@ -723,7 +727,6 @@ static void reds_agent_remove()
return;
}
- reds_reset_vdp();
main_channel_push_agent_disconnected(reds->main_channel);
}