mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-gtk
synced 2026-02-04 04:58:16 +00:00
session: remove channels on disconnect
A channel is considered to be part of a session as long as it is alive. However, this model is problematic, since library user may hold channel references, and thus the channel will remain in the session. Calling spice_session_disconnect() several time will end up calling spice_channel_destroy(), releasing references that aren't owned by the session. This usually causes crashes, in particular with language bindings that do not deal well with a library model where objects can't be referenced at will.
This commit is contained in:
parent
a67e5df149
commit
8943d23299
@ -152,9 +152,6 @@ static void spice_channel_dispose(GObject *gobject)
|
||||
|
||||
CHANNEL_DEBUG(channel, "%s %p", __FUNCTION__, gobject);
|
||||
|
||||
if (c->session)
|
||||
spice_session_channel_destroy(c->session, channel);
|
||||
|
||||
spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED);
|
||||
|
||||
if (c->session) {
|
||||
@ -2041,7 +2038,7 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
|
||||
* spice_channel_destroy:
|
||||
* @channel:
|
||||
*
|
||||
* Disconnect and unref the @channel. Called by @spice_session_disconnect()
|
||||
* Disconnect and unref the @channel. Called by @spice_session_channel_destroy()
|
||||
*
|
||||
**/
|
||||
void spice_channel_destroy(SpiceChannel *channel)
|
||||
|
||||
@ -48,7 +48,6 @@ gboolean spice_session_get_client_provided_socket(SpiceSession *session);
|
||||
GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel,
|
||||
gboolean *use_tls, GError **error);
|
||||
void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel);
|
||||
void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel);
|
||||
void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel);
|
||||
|
||||
void spice_session_set_mm_time(SpiceSession *session, guint32 time);
|
||||
|
||||
@ -210,6 +210,8 @@ enum {
|
||||
|
||||
static guint signals[SPICE_SESSION_LAST_SIGNAL];
|
||||
|
||||
static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel);
|
||||
|
||||
static void update_proxy(SpiceSession *self, const gchar *str)
|
||||
{
|
||||
SpiceSessionPrivate *s = self->priv;
|
||||
@ -1462,8 +1464,10 @@ void spice_session_switching_disconnect(SpiceSession *self)
|
||||
for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
|
||||
next = ring_next(&s->channels, ring);
|
||||
item = SPICE_CONTAINEROF(ring, struct channel, link);
|
||||
if (item->channel != s->cmain)
|
||||
spice_channel_destroy(item->channel); /* /!\ item and channel are destroy() after this call */
|
||||
|
||||
if (item->channel == s->cmain)
|
||||
continue;
|
||||
spice_session_channel_destroy(self, item->channel);
|
||||
}
|
||||
|
||||
g_warn_if_fail(!ring_is_empty(&s->channels)); /* ring_get_length() == 1 */
|
||||
@ -1742,7 +1746,7 @@ void spice_session_disconnect(SpiceSession *session)
|
||||
for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
|
||||
next = ring_next(&s->channels, ring);
|
||||
item = SPICE_CONTAINEROF(ring, struct channel, link);
|
||||
spice_channel_destroy(item->channel); /* /!\ item and channel are destroy() after this call */
|
||||
spice_session_channel_destroy(session, item->channel);
|
||||
}
|
||||
|
||||
s->connection_id = 0;
|
||||
@ -2030,8 +2034,7 @@ void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel)
|
||||
g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_NEW], 0, channel);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
|
||||
static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
|
||||
{
|
||||
g_return_if_fail(SPICE_IS_SESSION(session));
|
||||
g_return_if_fail(SPICE_IS_CHANNEL(channel));
|
||||
@ -2061,6 +2064,9 @@ void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
|
||||
free(item);
|
||||
|
||||
g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel);
|
||||
|
||||
g_clear_object(&channel->priv->session);
|
||||
spice_channel_destroy(channel);
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
|
||||
Loading…
Reference in New Issue
Block a user