[Spice-commits] 4 commits - server/spicevmc.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Fri Nov 4 09:00:14 UTC 2016


 server/spicevmc.c |   68 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 20 deletions(-)

New commits:
commit 97e299cc50600d2b539511b018144e5816d7fad0
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Nov 3 16:01:10 2016 +0000

    spicevmc: Clear RedVmcChannel on red_char_device_spicevmc_dispose
    
    This move object destructions from spicevmc_device_disconnect
    to RedCharDeviceSpiceVmc destructor functions assuring any possible
    RedCharDeviceSpiceVmc object free will clear its references.
    
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/spicevmc.c b/server/spicevmc.c
index b643787..d095378 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -879,19 +879,8 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
 /* Must be called from RedClient handling thread. */
 void spicevmc_device_disconnect(RedsState *reds, SpiceCharDeviceInstance *sin)
 {
-    RedVmcChannel *channel;
-    RedCharDeviceSpiceVmc *vmc = RED_CHAR_DEVICE_SPICEVMC(sin->st);
-
-    channel = vmc->channel;
-    vmc->channel = NULL;
-
-    /* FIXME */
-    red_char_device_destroy(RED_CHAR_DEVICE(vmc));
-    channel->chardev = NULL;
+    g_object_unref(RED_CHAR_DEVICE(sin->st));
     sin->st = NULL;
-
-    reds_unregister_channel(reds, RED_CHANNEL(channel));
-    red_channel_destroy(RED_CHANNEL(channel));
 }
 
 SPICE_GNUC_VISIBLE void spice_server_port_event(SpiceCharDeviceInstance *sin, uint8_t event)
@@ -923,7 +912,20 @@ red_char_device_spicevmc_dispose(GObject *object)
 {
     RedCharDeviceSpiceVmc *self = RED_CHAR_DEVICE_SPICEVMC(object);
 
-    g_clear_object(&self->channel);
+    if (self->channel) {
+        RedChannel *channel = RED_CHANNEL(self->channel);
+        RedsState *reds = red_char_device_get_server(RED_CHAR_DEVICE(self));
+
+        // prevent possible recursive calls
+        self->channel->chardev = NULL;
+
+        // prevent future connection
+        reds_unregister_channel(reds, channel);
+
+        // close all current connections and drop the reference
+        red_channel_destroy(channel);
+        self->channel = NULL;
+    }
 }
 
 static void
commit d80d7447e7f378928c3c679426a149cc0d0147be
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Nov 3 15:50:06 2016 +0000

    spicevmc: More RedVmcChannel::recv_from_client_buf cleanup to finalize
    
    No reason why this should be done only on spicevmc_device_disconnect.
    red_char_device_write_buffer_release can be called with first pointer
    NULL.
    
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/spicevmc.c b/server/spicevmc.c
index 1eadbbb..b643787 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -256,6 +256,7 @@ red_vmc_channel_finalize(GObject *object)
 {
     RedVmcChannel *self = RED_VMC_CHANNEL(object);
 
+    red_char_device_write_buffer_release(self->chardev, &self->recv_from_client_buf);
     if (self->pipe_item) {
         red_pipe_item_unref(&self->pipe_item->base);
     }
@@ -884,7 +885,6 @@ void spicevmc_device_disconnect(RedsState *reds, SpiceCharDeviceInstance *sin)
     channel = vmc->channel;
     vmc->channel = NULL;
 
-    red_char_device_write_buffer_release(channel->chardev, &channel->recv_from_client_buf);
     /* FIXME */
     red_char_device_destroy(RED_CHAR_DEVICE(vmc));
     channel->chardev = NULL;
commit cd7d3d3486037f6275716cc196145d81597483c4
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Wed Nov 2 08:42:29 2016 +0000

    spicevmc: Free pipe_item in finalize
    
    Assure field is freed at the end and not used or allocate again.
    
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/spicevmc.c b/server/spicevmc.c
index 8e23248..1eadbbb 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -251,6 +251,18 @@ red_vmc_channel_init(RedVmcChannel *self)
 {
 }
 
+static void
+red_vmc_channel_finalize(GObject *object)
+{
+    RedVmcChannel *self = RED_VMC_CHANNEL(object);
+
+    if (self->pipe_item) {
+        red_pipe_item_unref(&self->pipe_item->base);
+    }
+
+    G_OBJECT_CLASS(red_vmc_channel_parent_class)->finalize(object);
+}
+
 static RedVmcChannel *red_vmc_channel_new(RedsState *reds, uint8_t channel_type,
                                           SpiceCharDeviceInstance *sin)
 {
@@ -756,6 +768,7 @@ red_vmc_channel_class_init(RedVmcChannelClass *klass)
     object_class->get_property = red_vmc_channel_get_property;
     object_class->set_property = red_vmc_channel_set_property;
     object_class->constructed = red_vmc_channel_constructed;
+    object_class->finalize = red_vmc_channel_finalize;
 
     channel_class->handle_parsed = spicevmc_red_channel_client_handle_message_parsed;
 
@@ -878,7 +891,6 @@ void spicevmc_device_disconnect(RedsState *reds, SpiceCharDeviceInstance *sin)
     sin->st = NULL;
 
     reds_unregister_channel(reds, RED_CHANNEL(channel));
-    free(channel->pipe_item);
     red_channel_destroy(RED_CHANNEL(channel));
 }
 
commit f751eb9fdb88af0d7afd4b92f073f8a6776c470d
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Wed Nov 2 16:25:14 2016 -0500

    spicevmc: store channel in char device
    
    Store the channel in the char device object, and unref it in dispose.
    Previously, we were just creating a channel and potentially allowing it
    to leak.  There may be better long-term solutions, but this works for
    now.
    
    Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/spicevmc.c b/server/spicevmc.c
index 7067bc7..8e23248 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -47,6 +47,9 @@
 #define BUF_SIZE (64 * 1024 + 32)
 #define COMPRESS_THRESHOLD 1000
 
+typedef struct RedVmcChannel RedVmcChannel;
+typedef struct RedVmcChannelClass RedVmcChannelClass;
+
 typedef struct RedVmcPipeItem {
     RedPipeItem base;
 
@@ -75,6 +78,7 @@ typedef struct RedCharDeviceSpiceVmcClass RedCharDeviceSpiceVmcClass;
 
 struct RedCharDeviceSpiceVmc {
     RedCharDevice parent;
+    RedVmcChannel *channel;
 };
 
 struct RedCharDeviceSpiceVmcClass
@@ -89,9 +93,6 @@ static RedCharDevice *red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
 
 G_DEFINE_TYPE(RedCharDeviceSpiceVmc, red_char_device_spicevmc, RED_TYPE_CHAR_DEVICE)
 
-#define RED_CHAR_DEVICE_SPICEVMC_PRIVATE(o) \
-    (G_TYPE_INSTANCE_GET_PRIVATE ((o), RED_TYPE_CHAR_DEVICE_SPICEVMC, RedCharDeviceSpiceVmcPrivate))
-
 #define RED_TYPE_VMC_CHANNEL red_vmc_channel_get_type()
 
 #define RED_VMC_CHANNEL(obj) \
@@ -103,9 +104,6 @@ G_DEFINE_TYPE(RedCharDeviceSpiceVmc, red_char_device_spicevmc, RED_TYPE_CHAR_DEV
 #define RED_VMC_CHANNEL_GET_CLASS(obj) \
     (G_TYPE_INSTANCE_GET_CLASS((obj), RED_TYPE_VMC_CHANNEL, RedVmcChannelClass))
 
-typedef struct RedVmcChannel RedVmcChannel;
-typedef struct RedVmcChannelClass RedVmcChannelClass;
-
 struct RedVmcChannel
 {
     RedChannel parent;
@@ -855,28 +853,33 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
                                        SpiceCharDeviceInstance *sin,
                                        uint8_t channel_type)
 {
+    RedCharDeviceSpiceVmc *dev_state;
     RedVmcChannel *state = red_vmc_channel_new(reds, channel_type, sin);
 
-    return state->chardev;
+    dev_state = RED_CHAR_DEVICE_SPICEVMC(state->chardev);
+    dev_state->channel = state;
+
+    return RED_CHAR_DEVICE(dev_state);
 }
 
 /* Must be called from RedClient handling thread. */
 void spicevmc_device_disconnect(RedsState *reds, SpiceCharDeviceInstance *sin)
 {
-    RedVmcChannel *state;
+    RedVmcChannel *channel;
+    RedCharDeviceSpiceVmc *vmc = RED_CHAR_DEVICE_SPICEVMC(sin->st);
 
-    /* FIXME */
-    state = (RedVmcChannel *)red_char_device_opaque_get((RedCharDevice*)sin->st);
+    channel = vmc->channel;
+    vmc->channel = NULL;
 
-    red_char_device_write_buffer_release(state->chardev, &state->recv_from_client_buf);
+    red_char_device_write_buffer_release(channel->chardev, &channel->recv_from_client_buf);
     /* FIXME */
-    red_char_device_destroy((RedCharDevice*)sin->st);
-    state->chardev = NULL;
+    red_char_device_destroy(RED_CHAR_DEVICE(vmc));
+    channel->chardev = NULL;
     sin->st = NULL;
 
-    reds_unregister_channel(reds, RED_CHANNEL(state));
-    free(state->pipe_item);
-    red_channel_destroy(RED_CHANNEL(state));
+    reds_unregister_channel(reds, RED_CHANNEL(channel));
+    free(channel->pipe_item);
+    red_channel_destroy(RED_CHANNEL(channel));
 }
 
 SPICE_GNUC_VISIBLE void spice_server_port_event(SpiceCharDeviceInstance *sin, uint8_t event)
@@ -904,10 +907,21 @@ SPICE_GNUC_VISIBLE void spice_server_port_event(SpiceCharDeviceInstance *sin, ui
 }
 
 static void
+red_char_device_spicevmc_dispose(GObject *object)
+{
+    RedCharDeviceSpiceVmc *self = RED_CHAR_DEVICE_SPICEVMC(object);
+
+    g_clear_object(&self->channel);
+}
+
+static void
 red_char_device_spicevmc_class_init(RedCharDeviceSpiceVmcClass *klass)
 {
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
     RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
 
+    object_class->dispose = red_char_device_spicevmc_dispose;
+
     char_dev_class->read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev;
     char_dev_class->send_msg_to_client = spicevmc_chardev_send_msg_to_client;
     char_dev_class->send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client;


More information about the Spice-commits mailing list