Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
> On Wed, 2016-11-02 at 13:05 -0400, Frediano Ziglio wrote: > > > > > > > > > On Wed, 2016-11-02 at 08:31 -0400, Frediano Ziglio wrote: > > > > > > > > > > > > > > > > > > > > > > > > Hi, > > > > > > > > > > On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > From: Jonathon Jongsma> > > > > > > > > > > > > > Store the channel in the char device object, and unref it > > > > > > > in > > > > > > > dispose. > > > > > > > Previously, we were just creating a channel and allowing it > > > > > > > to > > > > > > > leak. > > > > > > > There may be better long-term solutions, but this works for > > > > > > > now. > > > > > > > --- > > > > > > > server/spicevmc.c | 27 --- > > > > > > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > > > > > > > > > > > Changes: > > > > > > > - squashed fixup. > > > > > > > > > > > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > > > > > > index 7067bc7..a77e868 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,9 +853,13 @@ RedCharDevice > > > > > > > *spicevmc_device_connect(RedsState > > > > > > > *reds, > > > > > > > SpiceCharDeviceInst > > > > > > > ance > > > > > > > *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. */ > > > > > > > @@ -904,10 +906,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(>channel); > > > > > > > > > > > > This call produce a double free. > > > > > > The channel is already freed in spicevmc_device_disconnect. > > > > > > > > > > But g_clear_object() verify if channel is null before the unref > > > > > and > > > > > set > > > > > it to NULL afterwards. > > > > > > > > > > > > > Doing a NULL check on a dangling pointer is not much helpful. > > > > > > Hmm, you're right. If we're going to remove the 'opaque' property > > > (in a > > > different patch), I think we do need to keep a pointer to the > > > channel > > > inside of the char device. But perhaps it should be a weak > > >
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
On Wed, 2016-11-02 at 13:05 -0400, Frediano Ziglio wrote: > > > > > > On Wed, 2016-11-02 at 08:31 -0400, Frediano Ziglio wrote: > > > > > > > > > > > > > > > > > > > Hi, > > > > > > > > On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > From: Jonathon Jongsma> > > > > > > > > > > > Store the channel in the char device object, and unref it > > > > > > in > > > > > > dispose. > > > > > > Previously, we were just creating a channel and allowing it > > > > > > to > > > > > > leak. > > > > > > There may be better long-term solutions, but this works for > > > > > > now. > > > > > > --- > > > > > > server/spicevmc.c | 27 --- > > > > > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > > > > > > > > > Changes: > > > > > > - squashed fixup. > > > > > > > > > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > > > > > index 7067bc7..a77e868 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,9 +853,13 @@ RedCharDevice > > > > > > *spicevmc_device_connect(RedsState > > > > > > *reds, > > > > > > SpiceCharDeviceInst > > > > > > ance > > > > > > *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. */ > > > > > > @@ -904,10 +906,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(>channel); > > > > > > > > > > This call produce a double free. > > > > > The channel is already freed in spicevmc_device_disconnect. > > > > > > > > But g_clear_object() verify if channel is null before the unref > > > > and > > > > set > > > > it to NULL afterwards. > > > > > > > > > > Doing a NULL check on a dangling pointer is not much helpful. > > > > Hmm, you're right. If we're going to remove the 'opaque' property > > (in a > > different patch), I think we do need to keep a pointer to the > > channel > > inside of the char device. But perhaps it should be a weak > > reference > > instead. So maybe we could just remove the dispose changes from > > this > > patch and squash it with that patch? > > > > Yes, I think we should kind of merge part of this patch in the other > one. > This could also be fixed setting the pointer to NULL after
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
> > On Wed, 2016-11-02 at 08:31 -0400, Frediano Ziglio wrote: > > > > > > > > > Hi, > > > > > > On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio wrote: > > > > > > > > > > > > > > > > > > > From: Jonathon Jongsma> > > > > > > > > > Store the channel in the char device object, and unref it in > > > > > dispose. > > > > > Previously, we were just creating a channel and allowing it to > > > > > leak. > > > > > There may be better long-term solutions, but this works for > > > > > now. > > > > > --- > > > > > server/spicevmc.c | 27 --- > > > > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > > > > > > > Changes: > > > > > - squashed fixup. > > > > > > > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > > > > index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ > > > > > @@ -904,10 +906,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(>channel); > > > > > > > > This call produce a double free. > > > > The channel is already freed in spicevmc_device_disconnect. > > > > > > But g_clear_object() verify if channel is null before the unref and > > > set > > > it to NULL afterwards. > > > > > > > Doing a NULL check on a dangling pointer is not much helpful. > > Hmm, you're right. If we're going to remove the 'opaque' property (in a > different patch), I think we do need to keep a pointer to the channel > inside of the char device. But perhaps it should be a weak reference > instead. So maybe we could just remove the dispose changes from this > patch and squash it with that patch? > Yes, I think we should kind of merge part of this patch in the other one. This could also be fixed setting the pointer to NULL after calling spicevmc_device_disconnect. > Also: perhaps the RedsState object should hold a reference to the > channels added via reds_register_channel() and unref the channel in > reds_unregister_channel(). It seems that it shouldn't be necessary to > call red_channel_destroy() explicitly. This should just happen in the > RedChannel destructor when the last ref is dropped... > > There is already a patch in the queue that does this; you wrote it :) (cfr
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
On Wed, 2016-11-02 at 08:31 -0400, Frediano Ziglio wrote: > > > > > > Hi, > > > > On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio wrote: > > > > > > > > > > > > > > > From: Jonathon Jongsma> > > > > > > > Store the channel in the char device object, and unref it in > > > > dispose. > > > > Previously, we were just creating a channel and allowing it to > > > > leak. > > > > There may be better long-term solutions, but this works for > > > > now. > > > > --- > > > > server/spicevmc.c | 27 --- > > > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > > > > > Changes: > > > > - squashed fixup. > > > > > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > > > index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ > > > > @@ -904,10 +906,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(>channel); > > > > > > This call produce a double free. > > > The channel is already freed in spicevmc_device_disconnect. > > > > But g_clear_object() verify if channel is null before the unref and > > set > > it to NULL afterwards. > > > > Doing a NULL check on a dangling pointer is not much helpful. Hmm, you're right. If we're going to remove the 'opaque' property (in a different patch), I think we do need to keep a pointer to the channel inside of the char device. But perhaps it should be a weak reference instead. So maybe we could just remove the dispose changes from this patch and squash it with that patch? Also: perhaps the RedsState object should hold a reference to the channels added via reds_register_channel() and unref the channel in reds_unregister_channel(). It seems that it shouldn't be necessary to call red_channel_destroy() explicitly. This should just happen in the RedChannel destructor when the last ref is dropped... > > > > > > > > > > > > > > > > > +} > > > > + > > > > +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 = > > > >
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
> > Hi, > > On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio wrote: > > > > > > From: Jonathon Jongsma> > > > > > Store the channel in the char device object, and unref it in dispose. > > > Previously, we were just creating a channel and allowing it to leak. > > > There may be better long-term solutions, but this works for now. > > > --- > > > server/spicevmc.c | 27 --- > > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > > > Changes: > > > - squashed fixup. > > > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > > index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ > > > @@ -904,10 +906,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(>channel); > > > > This call produce a double free. > > The channel is already freed in spicevmc_device_disconnect. > > But g_clear_object() verify if channel is null before the unref and set > it to NULL afterwards. > Doing a NULL check on a dangling pointer is not much helpful. > > > > > +} > > > + > > > +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; > > > > Removing the double free from this patch will basically revert the > > entire patch except the RED_CHAR_DEVICE_SPICEVMC_PRIVATE cleanup. > > Frediano ___ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
Hi, On Wed, Nov 02, 2016 at 04:34:47AM -0400, Frediano Ziglio wrote: > > > > From: Jonathon Jongsma> > > > Store the channel in the char device object, and unref it in dispose. > > Previously, we were just creating a channel and allowing it to leak. > > There may be better long-term solutions, but this works for now. > > --- > > server/spicevmc.c | 27 --- > > 1 file changed, 20 insertions(+), 7 deletions(-) > > > > Changes: > > - squashed fixup. > > > > diff --git a/server/spicevmc.c b/server/spicevmc.c > > index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ > > @@ -904,10 +906,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(>channel); > > This call produce a double free. > The channel is already freed in spicevmc_device_disconnect. But g_clear_object() verify if channel is null before the unref and set it to NULL afterwards. > > > +} > > + > > +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; > > Removing the double free from this patch will basically revert the > entire patch except the RED_CHAR_DEVICE_SPICEVMC_PRIVATE cleanup. > > Frediano > ___ > Spice-devel mailing list > Spice-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/spice-devel signature.asc Description: PGP signature ___ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel
Re: [Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
> > From: Jonathon Jongsma> > Store the channel in the char device object, and unref it in dispose. > Previously, we were just creating a channel and allowing it to leak. > There may be better long-term solutions, but this works for now. > --- > server/spicevmc.c | 27 --- > 1 file changed, 20 insertions(+), 7 deletions(-) > > Changes: > - squashed fixup. > > diff --git a/server/spicevmc.c b/server/spicevmc.c > index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ > @@ -904,10 +906,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(>channel); This call produce a double free. The channel is already freed in spicevmc_device_disconnect. > +} > + > +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; Removing the double free from this patch will basically revert the entire patch except the RED_CHAR_DEVICE_SPICEVMC_PRIVATE cleanup. Frediano ___ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel
[Spice-devel] [PATCH spice-server v2] Manage lifetime of RedVmcChannel
From: Jonathon JongsmaStore the channel in the char device object, and unref it in dispose. Previously, we were just creating a channel and allowing it to leak. There may be better long-term solutions, but this works for now. --- server/spicevmc.c | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) Changes: - squashed fixup. diff --git a/server/spicevmc.c b/server/spicevmc.c index 7067bc7..a77e868 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,9 +853,13 @@ 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. */ @@ -904,10 +906,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(>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; -- 2.7.4 ___ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel