diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-02-08 10:04:18 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-02-20 16:32:31 +0100 |
commit | f3f8ebe91bb95aa340b49a24e5b945a82cefe7c7 (patch) | |
tree | 586dee1c614884aeca8602d21d9dd37913eaeb27 | |
parent | 7e3fb815ccdfd7ab42ed8b03958ec00e470e1e8f (diff) |
server/spicevmc: Don't destroy the rcc twice
spicevmc calls red_channel_client_destroy() on the rcc when it disconnects
since we don't want to delay the destroy until the session gets closed as
spicevmc channels can be opened, closed and opened again during a single
session.
This causes red_channel_client_destroy() to get called twice, triggering
an assert, when a connected channel gets destroyed.
This was fixed with commit ffc4de01e6f9ea0676f17b10e45a137d7e15d6ac for
the case where: a spicevmc channel was open on client disconnected, and
the main channel disconnect gets handled first.
But the channel can also be destroyed when the chardev gets unregistered
with the spice-server. This path still triggers the assert.
This patch fixes this by adding a destroying flag to the rcc struct, and
also moves the previous fix over to the same, more clean, method of
detecting this special case.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | server/red_channel.c | 2 | ||||
-rw-r--r-- | server/red_channel.h | 1 | ||||
-rw-r--r-- | server/spicevmc.c | 6 |
3 files changed, 6 insertions, 3 deletions
diff --git a/server/red_channel.c b/server/red_channel.c index ec02018..6296dc9 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -780,6 +780,7 @@ void red_channel_set_data(RedChannel *channel, void *data) void red_channel_client_destroy(RedChannelClient *rcc) { + rcc->destroying = 1; if (red_channel_client_is_connected(rcc)) { red_channel_client_disconnect(rcc); } @@ -1439,6 +1440,7 @@ void red_client_destroy(RedClient *client) // some channels may be in other threads, so disconnection // is not synchronous. rcc = SPICE_CONTAINEROF(link, RedChannelClient, client_link); + rcc->destroying = 1; // some channels may be in other threads. However we currently // assume disconnect is synchronous (we changed the dispatcher // to wait for disconnection) diff --git a/server/red_channel.h b/server/red_channel.h index 045bfd4..543aec1 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -255,6 +255,7 @@ struct RedChannelClient { RedChannelCapabilities remote_caps; int is_mini_header; + int destroying; }; struct RedChannel { diff --git a/server/spicevmc.c b/server/spicevmc.c index 5cdc513..30aaf2f 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -116,9 +116,9 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc) sin = state->chardev_sin; sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base); - /* Don't destroy the rcc if the entire client is disconnecting, as then - red_client_destroy will already do this! */ - if (!rcc->client->disconnecting) + /* Don't destroy the rcc if it is already being destroyed, as then + red_client_destroy/red_channel_client_destroy will already do this! */ + if (!rcc->destroying) red_channel_client_destroy(rcc); state->rcc = NULL; |