[Spice-devel] [PATCH] fixup! spicevmc: Change creation of RedCharDeviceSpiceVmc

Jonathon Jongsma jjongsma at redhat.com
Fri Nov 4 19:25:43 UTC 2016


On Fri, 2016-11-04 at 13:34 -0400, Frediano Ziglio wrote:
> > 
> > 
> > ---
> > Possible fixup to Frediano's proposed patch. In general, GObject
> > _new()
> > functions should try not to do more than call g_object_new(). This
> > is mostly
> > to
> > make things simpler for language bindings, but I think it's good
> > practice to
> > do
> > as much initialization via the GObject construction framework as
> > possible. So
> > I
> > made 'channel' a GObject property in RedCharDeviceSpicevmc, and
> > moved some of
> > the additional work up to spicevmc_device_connect().
> > 
> > For the time being, I've left the duplicated 'sin' parameter in the
> > RedVmcChannel. But if we removed that from the channel (and simply
> > retrieved
> > it
> > as-needed from the char device as discussed in another patch), it
> > would
> > simplify things further, since spicevmc_device_connect() would not
> > really
> > have
> > to do any additional work besides creating the objects.
> > 
> >  server/spicevmc.c | 81
> >  ++++++++++++++++++++++++++++++++++++++++---------------
> >  1 file changed, 59 insertions(+), 22 deletions(-)
> > 
> > diff --git a/server/spicevmc.c b/server/spicevmc.c
> > index cf743de..084f09a 100644
> > --- a/server/spicevmc.c
> > +++ b/server/spicevmc.c
> > @@ -89,7 +89,7 @@ struct RedCharDeviceSpiceVmcClass
> >  static GType red_char_device_spicevmc_get_type(void) G_GNUC_CONST;
> >  static RedCharDevice
> > *red_char_device_spicevmc_new(SpiceCharDeviceInstance
> >  *sin,
> >                                                     RedsState
> > *reds,
> > -                                                   uint8_t
> > channel_type);
> > +                                                   RedVmcChannel
> > *channel);
> >  
> >  G_DEFINE_TYPE(RedCharDeviceSpiceVmc, red_char_device_spicevmc,
> >  RED_TYPE_CHAR_DEVICE)
> >  
> > @@ -806,7 +806,20 @@ RedCharDevice
> > *spicevmc_device_connect(RedsState *reds,
> >                                         SpiceCharDeviceInstance
> > *sin,
> >                                         uint8_t channel_type)
> >  {
> > -    return red_char_device_spicevmc_new(sin, reds, channel_type);
> > +    RedCharDevice *dev;
> > +    RedVmcChannel *channel = red_vmc_channel_new(reds,
> > channel_type);
> > +    if (!channel) {
> > +        return NULL;
> > +    }
> > +
> > +    /* char device takes ownership of channel */
> > +    dev = red_char_device_spicevmc_new(sin, reds, channel);
> > +
> > +    channel->chardev_sin = sin;
> > +    g_object_unref(channel);
> > +
> > +    return dev;
> >  }
> >  
> >  /* Must be called from RedClient handling thread. */
> > @@ -861,18 +874,54 @@ red_char_device_spicevmc_dispose(GObject
> > *object)
> >      }
> >  }
> >  
> > +enum {
> > +    PROP0,
> > +    PROP_CHANNEL
> > +};
> > +
> > +static void
> > +red_char_device_spicevmc_set_property(GObject *object,
> > +                                      guint property_id,
> > +                                      const GValue *value,
> > +                                      GParamSpec *pspec)
> > +{
> > +    RedCharDeviceSpiceVmc *self =
> > RED_CHAR_DEVICE_SPICEVMC(object);
> > +    switch (property_id)
> > +    {
> > +        case PROP_CHANNEL:
> > +            spice_assert(self->channel == NULL);
> > +            self->channel = g_value_dup_object(value);
> > +            self->channel->chardev = RED_CHAR_DEVICE(self);
> > +
> > +            break;
> > +        default:
> > +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id,
> > pspec);
> > +    }
> > +}
> > +
> >  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->set_property =
> > red_char_device_spicevmc_set_property;
> >      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;
> >      char_dev_class->remove_client =
> > spicevmc_char_dev_remove_client;
> > +
> > +    g_object_class_install_property(object_class,
> > +                                    PROP_CHANNEL,
> > +                                    g_param_spec_object("channel",
> > +                                                         "Channel"
> > ,
> > +                                                         "Channel
> > associated
> > with this device",
> > +
> > RED_TYPE_VMC_CHANNEL,
> > +
> > G_PARAM_STATIC_STRINGS
> > > 
> > > 
> > +                                                         G_PARAM_W
> > RITABLE |
> > +
> > G_PARAM_CONSTRUCT));
> >  }
> >  
> >  static void
> > @@ -883,25 +932,13 @@
> > red_char_device_spicevmc_init(RedCharDeviceSpiceVmc
> > *self)
> >  static RedCharDevice *
> >  red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
> >                               RedsState *reds,
> > -                             uint8_t channel_type)
> > +                             RedVmcChannel *channel)
> >  {
> > -    RedCharDeviceSpiceVmc *dev;
> > -    RedVmcChannel *channel = red_vmc_channel_new(reds,
> > channel_type);
> > -    if (!channel) {
> > -        return NULL;
> > -    }
> > -
> > -    dev = g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
> > -                       "sin", sin,
> > -                       "spice-server", reds,
> > -                       "client-tokens-interval", 0ULL,
> > -                       "self-tokens", ~0ULL,
> > -                       "opaque", channel,
> > -                       NULL);
> > -
> > -    channel->chardev = RED_CHAR_DEVICE(dev);
> > -    channel->chardev_sin = sin;
> > -    dev->channel = channel;
> > -
> > -    return RED_CHAR_DEVICE(dev);
> > +    return g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
> > +                        "sin", sin,
> > +                        "spice-server", reds,
> > +                        "client-tokens-interval", 0ULL,
> > +                        "self-tokens", ~0ULL,
> > +                        "opaque", channel,
> > +                        NULL);
> >  }
> 
> Not adding "channel" here cause a crash. Don't know why.
> Adding it fixes the problem (opaque and channel are both needed).
> Actually was a bit weird... not having "channel" in the list
> crashed in red_char_device_spicevmc_set_property, specifically
> 
>    self->channel->chardev = RED_CHAR_DEVICE(self);
> 
> line. But why this property is set if not passed? Perhaps
> objects not passed are tried to set to NULL? Maybe.

That's what I get for trying to get the patch sent off quickly before
lunch break. Sorry.

Yeah, construct properties are always set, I believe. They just use
default values (NULL in this case) if they're not explicitly specified.
https://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobje
ct-construction/

> 
> By the way, this is a reason I don't like much too dynamic code
> in a static language like C. We (just question of time before it
> happens to me) are keeping sending buggy patches hard to review
> and test.
> This from my point of view is less maintainable code.

Well, you have a point. But that is the why these 'dynamic' calls are
hidden inside of a typesafe 'constructor' function (_new()). I think
that's a reasonable compromise.

Jonathon


More information about the Spice-devel mailing list