char-device: Define and use (un)ref

Prepare to remove GObject.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Frediano Ziglio 2020-03-05 05:35:43 +00:00 committed by Frediano Ziglio
parent 9e5781e81c
commit ea0d056bb7
8 changed files with 73 additions and 83 deletions

View File

@ -307,7 +307,7 @@ static bool red_char_device_read_from_device(RedCharDevice *dev)
}
max_send_tokens = red_char_device_max_send_tokens(dev);
g_object_ref(dev);
dev->ref();
/*
* Reading from the device only in case at least one of the clients have a free token.
* All messages will be discarded if no client is attached to the device
@ -333,7 +333,7 @@ static bool red_char_device_read_from_device(RedCharDevice *dev)
if (dev->priv->running) {
dev->priv->active = dev->priv->active || did_read;
}
g_object_unref(dev);
dev->unref();
return did_read;
}
@ -439,7 +439,7 @@ static int red_char_device_write_to_device(RedCharDevice *dev)
return 0;
}
g_object_ref(dev);
dev->ref();
if (dev->priv->write_to_dev_timer) {
red_timer_cancel(dev->priv->write_to_dev_timer);
@ -488,7 +488,7 @@ static int red_char_device_write_to_device(RedCharDevice *dev)
dev->priv->active = dev->priv->active || total;
}
dev->priv->during_write_to_device = 0;
g_object_unref(dev);
dev->unref();
return total;
}
@ -757,10 +757,10 @@ void red_char_device_start(RedCharDevice *dev)
{
spice_debug("char device %p", dev);
dev->priv->running = TRUE;
g_object_ref(dev);
dev->ref();
while (red_char_device_write_to_device(dev) ||
red_char_device_read_from_device(dev));
g_object_unref(dev);
dev->unref();
}
void red_char_device_stop(RedCharDevice *dev)

View File

@ -45,17 +45,15 @@ struct RedCharDevicePrivate;
#endif
/* 'SpiceCharDeviceState' name is used for consistency with what spice-char.h exports */
struct SpiceCharDeviceState
struct SpiceCharDeviceState: public GObject
{
GObject parent;
RedCharDevicePrivate *priv;
void ref() { g_object_ref(this); }
void unref() { g_object_unref(this); }
};
struct RedCharDeviceClass
struct RedCharDeviceClass: public GObjectClass
{
GObjectClass parent_class;
/*
* Messages that are addressed to the client can be queued in case we have
* multiple clients and some of them don't have enough tokens.

View File

@ -27,9 +27,8 @@
#define MAX_GUEST_CAPABILITIES_BYTES ((STREAM_CAP_END+7)/8)
struct StreamDevice {
RedCharDevice parent;
struct StreamDevice: public RedCharDevice
{
StreamDevHeader hdr;
uint8_t hdr_pos;
union AllMessages {
@ -78,7 +77,7 @@ static void
close_timer_func(StreamDevice *dev)
{
if (dev->opened && dev->has_error) {
char_device_set_state(RED_CHAR_DEVICE(dev), 0);
char_device_set_state(dev, 0);
}
}
@ -114,7 +113,7 @@ stream_device_partial_read(StreamDevice *dev, SpiceCharDeviceInstance *sin)
// As calling sif->state here can cause a crash, schedule
// a timer and do the call in it. Remove this code when
// we are sure all Qemu versions have been patched.
RedsState *reds = red_char_device_get_server(RED_CHAR_DEVICE(dev));
RedsState *reds = red_char_device_get_server(dev);
if (!dev->close_timer) {
dev->close_timer = reds_core_timer_add(reds, close_timer_func, dev);
}
@ -233,7 +232,7 @@ handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin, const char *
int msg_size = sizeof(StreamMsgNotifyError) + strlen(error_msg) + 1;
int total_size = sizeof(StreamDevHeader) + msg_size;
RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
RedCharDevice *char_dev = dev;
RedCharDeviceWriteBuffer *buf =
red_char_device_write_buffer_get_server(char_dev, total_size, false);
buf->buf_used = total_size;
@ -336,7 +335,7 @@ handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance *sin)
dev->device_display_info.device_address,
dev->device_display_info.device_display_id);
reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
reds_send_device_display_info(red_char_device_get_server(dev));
return true;
}
@ -571,9 +570,8 @@ stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
int msg_size = sizeof(*start) + sizeof(start->codecs[0]) * start->num_codecs;
int total_size = sizeof(StreamDevHeader) + msg_size;
RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
RedCharDeviceWriteBuffer *buf =
red_char_device_write_buffer_get_server(char_dev, total_size, false);
red_char_device_write_buffer_get_server(dev, total_size, false);
buf->buf_used = total_size;
StreamDevHeader *hdr = (StreamDevHeader *)buf->buf;
@ -581,7 +579,7 @@ stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
memcpy(&hdr[1], start, msg_size);
red_char_device_write_buffer_add(char_dev, buf);
red_char_device_write_buffer_add(dev, buf);
}
static void
@ -607,7 +605,7 @@ stream_device_stream_queue_stat(void *opaque, const StreamQueueStat *stats G_GNU
// TODO resume flow...
// avoid recursion if we need to call get data from data handling from
// data handling
red_char_device_wakeup(&dev->parent);
red_char_device_wakeup(dev);
}
}
@ -667,7 +665,7 @@ stream_device_create_channel(StreamDevice *dev)
return;
}
SpiceServer* reds = red_char_device_get_server(RED_CHAR_DEVICE(dev));
SpiceServer* reds = red_char_device_get_server(dev);
SpiceCoreInterfaceInternal* core = reds_get_core_interface(reds);
int id = reds_get_free_channel_id(reds, SPICE_CHANNEL_DISPLAY);

View File

@ -217,16 +217,13 @@ typedef struct SPICE_ATTR_PACKED VDInternalBuf {
SPICE_DECLARE_TYPE(RedCharDeviceVDIPort, red_char_device_vdi_port, CHAR_DEVICE_VDIPORT);
#define RED_TYPE_CHAR_DEVICE_VDIPORT red_char_device_vdi_port_get_type()
struct RedCharDeviceVDIPort
struct RedCharDeviceVDIPort: public RedCharDevice
{
RedCharDevice parent;
RedCharDeviceVDIPortPrivate *priv;
};
struct RedCharDeviceVDIPortClass
struct RedCharDeviceVDIPortClass: public RedCharDeviceClass
{
RedCharDeviceClass parent_class;
};
G_DEFINE_TYPE_WITH_PRIVATE(RedCharDeviceVDIPort, red_char_device_vdi_port, RED_TYPE_CHAR_DEVICE)
@ -415,7 +412,6 @@ static void reds_reset_vdp(RedsState *reds)
{
RedCharDeviceVDIPort *dev = reds->agent_dev;
SpiceCharDeviceInterface *sif;
RedCharDevice *char_dev;
dev->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
dev->priv->receive_pos = (uint8_t *)&dev->priv->vdi_chunk_header;
@ -449,10 +445,9 @@ static void reds_reset_vdp(RedsState *reds)
* The tokens are also reset to avoid mismatch in upon agent reconnection.
*/
dev->priv->agent_attached = FALSE;
char_dev = RED_CHAR_DEVICE(dev);
red_char_device_stop(char_dev);
red_char_device_reset(char_dev);
red_char_device_reset_dev_instance(char_dev, NULL);
red_char_device_stop(dev);
red_char_device_reset(dev);
red_char_device_reset_dev_instance(dev, NULL);
sif = spice_char_device_get_interface(reds->vdagent);
if (sif->state) {
@ -468,7 +463,7 @@ static RedCharDeviceWriteBuffer *vdagent_new_write_buffer(RedCharDeviceVDIPort *
uint32_t total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size;
RedCharDeviceWriteBuffer *char_dev_buf;
char_dev_buf = red_char_device_write_buffer_get_server(RED_CHAR_DEVICE(agent_dev),
char_dev_buf = red_char_device_write_buffer_get_server(agent_dev,
total_msg_size,
use_token);
if (!char_dev_buf) {
@ -528,8 +523,8 @@ void reds_client_disconnect(RedsState *reds, RedClient *client)
/* note that client might be NULL, if the vdagent was once
* up and than was removed */
if (red_char_device_client_exists(RED_CHAR_DEVICE(reds->agent_dev), client)) {
red_char_device_client_remove(RED_CHAR_DEVICE(reds->agent_dev), client);
if (red_char_device_client_exists(reds->agent_dev, client)) {
red_char_device_client_remove(reds->agent_dev, client);
}
reds->clients = g_list_remove(reds->clients, client);
@ -546,7 +541,7 @@ void reds_client_disconnect(RedsState *reds, RedClient *client)
0,
false);
red_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_dev), char_dev_buf);
red_char_device_write_buffer_add(reds->agent_dev, char_dev_buf);
}
/* Reset write filter to start with clean state on client reconnect */
@ -739,7 +734,7 @@ static void vdi_port_read_buf_free(RedPipeItem *base)
necessary. Note that since we can be called from red_char_device_wakeup
this can cause recursion, but we have protection for that */
if (buf->dev->priv->agent_attached) {
red_char_device_wakeup(RED_CHAR_DEVICE(buf->dev));
red_char_device_wakeup(buf->dev);
}
g_free(buf);
}
@ -783,7 +778,7 @@ static RedPipeItem *vdi_port_read_one_msg_from_device(RedCharDevice *self,
int n;
reds = red_char_device_get_server(self);
g_assert(RED_CHAR_DEVICE(reds->agent_dev) == sin->st);
g_assert(reds->agent_dev == sin->st);
if (!reds->vdagent) {
return NULL;
}
@ -937,7 +932,7 @@ void reds_send_device_display_info(RedsState *reds)
reds->pending_device_display_info_message = false;
red_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_dev), char_dev_buf);
red_char_device_write_buffer_add(reds->agent_dev, char_dev_buf);
}
/* after calling this, we unref the message, and the ref is in the instance side */
@ -1012,7 +1007,7 @@ void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState *mou
VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
internal_buf->u.mouse_state = *mouse_state;
red_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_dev), char_dev_buf);
red_char_device_write_buffer_add(reds->agent_dev, char_dev_buf);
}
SPICE_GNUC_VISIBLE int spice_server_get_num_clients(SpiceServer *reds)
@ -1069,7 +1064,7 @@ SpiceMsgChannels *reds_msg_channels_new(RedsState *reds)
void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, uint32_t num_tokens)
{
RedCharDevice *dev_state = RED_CHAR_DEVICE(reds->agent_dev);
RedCharDevice *dev_state = reds->agent_dev;
RedClient *client;
if (!reds->vdagent) {
@ -1146,7 +1141,7 @@ uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, siz
spice_assert(dev->priv->recv_from_client_buf == NULL);
client = mcc->get_client();
dev->priv->recv_from_client_buf =
red_char_device_write_buffer_get_client(RED_CHAR_DEVICE(dev),
red_char_device_write_buffer_get_client(dev,
client,
size + sizeof(VDIChunkHeader));
/* check if buffer was allocated, as flow control is enabled for
@ -1170,7 +1165,7 @@ void reds_release_agent_data_buffer(RedsState *reds, uint8_t *buf)
spice_assert(buf == dev->priv->recv_from_client_buf->buf + sizeof(VDIChunkHeader));
/* if we pushed the buffer the buffer is attached to the channel so don't free it */
if (!dev->priv->recv_from_client_buf_pushed) {
red_char_device_write_buffer_release(RED_CHAR_DEVICE(dev),
red_char_device_write_buffer_release(dev,
&dev->priv->recv_from_client_buf);
}
dev->priv->recv_from_client_buf = NULL;
@ -1259,7 +1254,7 @@ void reds_on_main_agent_data(RedsState *reds, MainChannelClient *mcc, const void
dev->priv->recv_from_client_buf->buf_used = sizeof(VDIChunkHeader) + size;
dev->priv->recv_from_client_buf_pushed = TRUE;
red_char_device_write_buffer_add(RED_CHAR_DEVICE(dev), dev->priv->recv_from_client_buf);
red_char_device_write_buffer_add(dev, dev->priv->recv_from_client_buf);
}
void reds_on_main_migrate_connected(RedsState *reds, int seamless)
@ -1366,7 +1361,7 @@ void reds_marshall_migrate_data(RedsState *reds, SpiceMarshaller *m)
return;
}
red_char_device_migrate_data_marshall(RED_CHAR_DEVICE(agent_dev), m);
red_char_device_migrate_data_marshall(agent_dev, m);
spice_marshaller_add_uint8(m, agent_dev->priv->client_agent_started);
mig_data.agent2client.chunk_header = agent_dev->priv->vdi_chunk_header;
@ -1486,7 +1481,7 @@ static int reds_agent_state_restore(RedsState *reds, SpiceMigrateDataMain *mig_d
agent_dev->priv->read_filter.discard_all,
agent_dev->priv->read_filter.msg_data_to_read,
agent_dev->priv->read_filter.result);
return red_char_device_restore(RED_CHAR_DEVICE(agent_dev), &mig_data->agent_base);
return red_char_device_restore(agent_dev, &mig_data->agent_base);
}
/*
@ -1536,7 +1531,7 @@ bool reds_handle_migrate_data(RedsState *reds, MainChannelClient *mcc,
if (reds->vdagent) {
RedClient *client = mcc->get_client();
/* red_char_device_client_remove disables waiting for migration data */
red_char_device_client_remove(RED_CHAR_DEVICE(agent_dev), client);
red_char_device_client_remove(agent_dev, client);
main_channel_push_agent_connected(reds->main_channel);
}
}
@ -3111,7 +3106,7 @@ static RedCharDevice *attach_to_red_agent(RedsState *reds, SpiceCharDeviceInstan
SpiceCharDeviceInterface *sif;
dev->priv->agent_attached = true;
red_char_device_reset_dev_instance(RED_CHAR_DEVICE(dev), sin);
red_char_device_reset_dev_instance(dev, sin);
reds->vdagent = sin;
reds_update_mouse_mode(reds);
@ -3122,7 +3117,7 @@ static RedCharDevice *attach_to_red_agent(RedsState *reds, SpiceCharDeviceInstan
}
if (!reds_main_channel_connected(reds)) {
return RED_CHAR_DEVICE(dev);
return dev;
}
dev->priv->read_filter.discard_all = FALSE;
@ -3137,10 +3132,10 @@ static RedCharDevice *attach_to_red_agent(RedsState *reds, SpiceCharDeviceInstan
* 2.b If this happens second ==> we already have spice migrate data
* then restore state
*/
if (!red_char_device_client_exists(RED_CHAR_DEVICE(dev), reds_get_client(reds))) {
if (!red_char_device_client_exists(dev, reds_get_client(reds))) {
int client_added;
client_added = red_char_device_client_add(RED_CHAR_DEVICE(dev),
client_added = red_char_device_client_add(dev,
reds_get_client(reds),
TRUE, /* flow control */
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
@ -3170,7 +3165,7 @@ static RedCharDevice *attach_to_red_agent(RedsState *reds, SpiceCharDeviceInstan
main_channel_push_agent_connected(reds->main_channel);
}
return RED_CHAR_DEVICE(dev);
return dev;
}
SPICE_GNUC_VISIBLE void spice_server_char_device_wakeup(SpiceCharDeviceInstance* sin)
@ -3229,7 +3224,7 @@ spice_server_char_device_add_interface(SpiceServer *reds, SpiceBaseInstance *sin
return -1;
}
dev_state = attach_to_red_agent(reds, char_device);
g_object_ref(dev_state);
dev_state->ref();
}
#ifdef USE_SMARTCARD
else if (strcmp(char_device->subtype, SUBTYPE_SMARTCARD) == 0) {
@ -3283,7 +3278,7 @@ static int spice_server_char_device_remove_interface(RedsState *reds, SpiceBaseI
g_return_val_if_fail(char_device == reds->vdagent, -1);
if (reds->vdagent) {
reds_agent_remove(reds);
red_char_device_reset_dev_instance(RED_CHAR_DEVICE(reds->agent_dev), NULL);
red_char_device_reset_dev_instance(reds->agent_dev, NULL);
}
}
#ifdef USE_SMARTCARD
@ -3839,13 +3834,16 @@ SPICE_GNUC_VISIBLE void spice_server_destroy(SpiceServer *reds)
g_object_unref(reds->main_dispatcher);
}
reds_cleanup_net(reds);
g_clear_object(&reds->agent_dev);
if (reds->agent_dev) {
reds->agent_dev->unref();
reds->agent_dev = nullptr;
}
// NOTE: don't replace with g_list_free_full as this function that passed callback
// don't change the list while g_object_unref in this case will change it.
// don't change the list while unreferencing in this case will change it.
RedCharDevice *dev;
GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
g_object_unref(dev);
dev->unref();
}
g_list_free(reds->char_devices);
reds->char_devices = NULL;
@ -4588,7 +4586,7 @@ red_char_device_vdi_port_finalize(GObject *object)
RedCharDeviceVDIPort *dev = RED_CHAR_DEVICE_VDIPORT(object);
/* make sure we have no other references to RedVDIReadBuf buffers */
red_char_device_reset(RED_CHAR_DEVICE(dev));
red_char_device_reset(dev);
if (dev->priv->current_read_buf) {
red_pipe_item_unref(&dev->priv->current_read_buf->base);
dev->priv->current_read_buf = NULL;

View File

@ -85,7 +85,7 @@ SmartCardChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
spice_assert(smartcard_char_device_get_client(smartcard) || priv->smartcard);
spice_assert(!priv->write_buf);
priv->write_buf =
red_char_device_write_buffer_get_client(RED_CHAR_DEVICE(smartcard), this, size);
red_char_device_write_buffer_get_client(smartcard, this, size);
if (!priv->write_buf) {
spice_error("failed to allocate write buffer");
@ -109,7 +109,7 @@ SmartCardChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *
} else {
if (priv->write_buf) { /* msg hasn't been pushed to the guest */
spice_assert(priv->write_buf->buf == msg);
red_char_device_write_buffer_release(RED_CHAR_DEVICE(priv->smartcard),
red_char_device_write_buffer_release(priv->smartcard,
&priv->write_buf);
}
}

View File

@ -246,7 +246,7 @@ void smartcard_device_disconnect(SpiceCharDeviceInstance *char_device)
{
g_return_if_fail(RED_IS_CHAR_DEVICE_SMARTCARD(char_device->st));
g_object_unref(char_device->st);
char_device->st->unref();
}
RedCharDevice *smartcard_device_connect(RedsState *reds, SpiceCharDeviceInstance *char_device)
@ -255,10 +255,10 @@ RedCharDevice *smartcard_device_connect(RedsState *reds, SpiceCharDeviceInstance
dev = smartcard_device_new(reds, char_device);
if (smartcard_char_device_add_to_readers(reds, char_device) == -1) {
g_object_unref(dev);
dev->unref();
return NULL;
}
return RED_CHAR_DEVICE(dev);
return dev;
}
void smartcard_char_device_notify_reader_add(RedCharDeviceSmartcard *dev)
@ -266,7 +266,7 @@ void smartcard_char_device_notify_reader_add(RedCharDeviceSmartcard *dev)
RedCharDeviceWriteBuffer *write_buf;
VSCMsgHeader *vheader;
write_buf = red_char_device_write_buffer_get_server(RED_CHAR_DEVICE(dev),
write_buf = red_char_device_write_buffer_get_server(dev,
sizeof(*vheader),
true);
if (!write_buf) {
@ -290,7 +290,7 @@ void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_device,
spice_assert(!smartcard_channel_client_get_char_device(scc) && !dev->priv->scc);
dev->priv->scc = scc;
smartcard_channel_client_set_char_device(scc, dev);
client_added = red_char_device_client_add(RED_CHAR_DEVICE(dev),
client_added = red_char_device_client_add(dev,
scc,
FALSE, /* no flow control yet */
0, /* send queue size */
@ -319,7 +319,7 @@ gboolean smartcard_char_device_notify_reader_remove(RedCharDeviceSmartcard *dev)
spice_debug("reader add was never sent to the device");
return FALSE;
}
write_buf = red_char_device_write_buffer_get_server(RED_CHAR_DEVICE(dev),
write_buf = red_char_device_write_buffer_get_server(dev,
sizeof(*vheader),
true);
if (!write_buf) {
@ -342,11 +342,11 @@ void smartcard_char_device_detach_client(RedCharDeviceSmartcard *smartcard,
SpiceCharDeviceInterface *sif;
SpiceCharDeviceInstance *sin;
sin = red_char_device_get_device_instance(RED_CHAR_DEVICE(smartcard));
sin = red_char_device_get_device_instance(smartcard);
sif = spice_char_device_get_interface(sin);
spice_assert(smartcard->priv->scc == scc);
red_char_device_client_remove(RED_CHAR_DEVICE(smartcard), scc);
red_char_device_client_remove(smartcard, scc);
smartcard_channel_client_set_char_device(scc, NULL);
smartcard->priv->scc = NULL;
@ -386,7 +386,7 @@ static void smartcard_channel_send_migrate_data(SmartCardChannelClient *scc,
spice_marshaller_add_uint32(m, 0);
spice_debug("null char dev");
} else {
red_char_device_migrate_data_marshall(RED_CHAR_DEVICE(dev), m);
red_char_device_migrate_data_marshall(dev, m);
spice_marshaller_add_uint8(m, dev->priv->reader_added);
spice_marshaller_add_uint32(m, dev->priv->buf_used);
m2 = spice_marshaller_get_ptr_submarshaller(m);
@ -484,7 +484,7 @@ int smartcard_char_device_handle_migrate_data(RedCharDeviceSmartcard *smartcard,
smartcard->priv->reader_added = mig_data->reader_added;
smartcard_device_restore_partial_read(smartcard, mig_data);
return red_char_device_restore(RED_CHAR_DEVICE(smartcard), &mig_data->base);
return red_char_device_restore(smartcard, &mig_data->base);
}
void RedSmartcardChannel::on_connect(RedClient *client, RedStream *stream, int migration,

View File

@ -31,16 +31,13 @@ SPICE_DECLARE_TYPE(RedCharDeviceSmartcard, red_char_device_smartcard, CHAR_DEVIC
struct SmartCardChannelClient;
struct RedCharDeviceSmartcard
struct RedCharDeviceSmartcard: public RedCharDevice
{
RedCharDevice parent;
RedCharDeviceSmartcardPrivate *priv;
};
struct RedCharDeviceSmartcardClass
struct RedCharDeviceSmartcardClass: public RedCharDeviceClass
{
RedCharDeviceClass parent_class;
};
/*

View File

@ -57,14 +57,13 @@ typedef struct RedVmcPipeItem {
uint32_t buf_used;
} RedVmcPipeItem;
struct RedCharDeviceSpiceVmc {
RedCharDevice parent;
struct RedCharDeviceSpiceVmc: public RedCharDevice
{
RedVmcChannel *channel;
};
struct RedCharDeviceSpiceVmcClass
struct RedCharDeviceSpiceVmcClass: public RedCharDeviceClass
{
RedCharDeviceClass parent_class;
};
static RedCharDevice *red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
@ -692,7 +691,7 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
/* Must be called from RedClient handling thread. */
void spicevmc_device_disconnect(SpiceCharDeviceInstance *sin)
{
g_object_unref(RED_CHAR_DEVICE(sin->st));
sin->st->unref();
sin->st = NULL;
}
@ -752,7 +751,7 @@ red_char_device_spicevmc_set_property(GObject *object,
self->channel = (RedVmcChannel*) g_value_get_pointer(value);
spice_assert(self->channel != NULL);
self->channel->ref();
self->channel->chardev = RED_CHAR_DEVICE(self);
self->channel->chardev = self;
break;
default: