mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-12 19:18:11 +00:00
Fix crash attempting to connect duplicate channels
You could easily trigger this issue using multiple monitors and a
modified spice-gtk client with this patch:
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -1699,6 +1699,7 @@ static gboolean _channel_new(channel_new_t *c)
{
g_return_val_if_fail(c != NULL, FALSE);
+ if (c->type == SPICE_CHANNEL_DISPLAY) c->id = 0;
spice_channel_new(c->session, c->type, c->id);
g_object_unref(c->session);
which cause a crash like
(process:28742): Spice-WARNING **: Failed to create channel client: Client 0x40246f5d0: duplicate channel type 2 id 0
2017-08-24 09:36:57.451+0000: shutting down, reason=crashed
RedChannelClient is an GInitable type, which means that the object is
constructed, and then the _init() function is called, which can fail.
If the _init() fails, the newly-created object will be destroyed. As
part of _init(), we add a new watch for the stream using the core
interface that is associated with the channel. After adding the watch,
our rcc creation fails (due to duplicate ID), and the rcc object is
unreffed. This results in a call to reds_stream_free() (since the rcc
now owns the stream). But in reds_stream_free, we were trying to remove
the watch from the core interface associated with the RedsState. For
most channels, these two core interfaces are equivalent. But for the
Display and Cursor channels, it is the core Glib-based interface
associated with the RedWorker.
The watch in RedsStream by default is bound to the Qemu provided
SpiceCoreInterface while RedChannelClient bound it to Glib one causing
the crash when the watch is deleted from RedsStream. Change the bound
interface.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
parent
692c133765
commit
5d7ecb0162
@ -339,6 +339,16 @@ red_channel_client_finalize(GObject *object)
|
||||
{
|
||||
RedChannelClient *self = RED_CHANNEL_CLIENT(object);
|
||||
|
||||
SpiceCoreInterfaceInternal *core = red_channel_get_core_interface(self->priv->channel);
|
||||
if (self->priv->latency_monitor.timer) {
|
||||
core->timer_remove(core, self->priv->latency_monitor.timer);
|
||||
self->priv->latency_monitor.timer = NULL;
|
||||
}
|
||||
if (self->priv->connectivity_monitor.timer) {
|
||||
core->timer_remove(core, self->priv->connectivity_monitor.timer);
|
||||
self->priv->connectivity_monitor.timer = NULL;
|
||||
}
|
||||
|
||||
reds_stream_free(self->priv->stream);
|
||||
self->priv->stream = NULL;
|
||||
|
||||
@ -921,12 +931,14 @@ static gboolean red_channel_client_initable_init(GInitable *initable,
|
||||
}
|
||||
|
||||
core = red_channel_get_core_interface(self->priv->channel);
|
||||
if (self->priv->stream)
|
||||
if (self->priv->stream) {
|
||||
reds_stream_set_core_interface(self->priv->stream, core);
|
||||
self->priv->stream->watch =
|
||||
core->watch_add(core, self->priv->stream->socket,
|
||||
SPICE_WATCH_EVENT_READ,
|
||||
red_channel_client_event,
|
||||
self);
|
||||
}
|
||||
|
||||
if (self->priv->monitor_latency
|
||||
&& reds_stream_get_family(self->priv->stream) != AF_UNIX) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user