[Spice-devel] [PATCH spice-server v2] red-channel-client: Avoid weird memory references using MarkerPipeItem
Frediano Ziglio
fziglio at redhat.com
Wed Nov 22 11:41:49 UTC 2017
ping
>
> Instead of having MarkerPipeItem pointing to an external variable with
> the possibility to forget to reset it and have a dangling pointer use
> reference counting to keep the item and mark the item when sent.
> This item is placed into the queue to understand when it was sent. The
> current implementation detect the unqueue when the item is destroyed so
> we use an external variable to use it after the item is released.
> Instead this change update the variable (stored in the item) when the
> item is attempted to be sent. This avoids having to destroy the item.
>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
> server/red-channel-client.c | 30 +++++++++++-------------------
> 1 file changed, 11 insertions(+), 19 deletions(-)
>
> diff --git a/server/red-channel-client.c b/server/red-channel-client.c
> index 34202c492..de3ac27cb 100644
> --- a/server/red-channel-client.c
> +++ b/server/red-channel-client.c
> @@ -218,7 +218,7 @@ typedef struct RedEmptyMsgPipeItem {
>
> typedef struct MarkerPipeItem {
> RedPipeItem base;
> - gboolean *item_in_pipe;
> + bool item_in_pipe;
> } MarkerPipeItem;
>
> static void red_channel_client_start_ping_timer(RedChannelClient *rcc,
> uint32_t timeout)
> @@ -613,6 +613,7 @@ static void red_channel_client_send_item(RedChannelClient
> *rcc, RedPipeItem *ite
> red_channel_client_send_ping(rcc);
> break;
> case RED_PIPE_ITEM_TYPE_MARKER:
> + SPICE_UPCAST(MarkerPipeItem, item)->item_in_pipe = false;
> break;
> default:
> red_channel_send_item(rcc->priv->channel, rcc, item);
> @@ -1757,23 +1758,13 @@ void
> red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_
> rcc->priv->send_data.header.set_msg_sub_list(&rcc->priv->send_data.header,
> sub_list);
> }
>
> -static void marker_pipe_item_free(RedPipeItem *base)
> -{
> - MarkerPipeItem *item = SPICE_UPCAST(MarkerPipeItem, base);
> -
> - if (item->item_in_pipe) {
> - *item->item_in_pipe = FALSE;
> - }
> - free(item);
> -}
> -
> /* TODO: more evil sync stuff. anything with the word wait in it's name. */
> bool red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
> GList *item_pos,
> int64_t timeout)
> {
> uint64_t end_time;
> - gboolean item_in_pipe;
> + bool item_in_pipe;
>
> spice_debug("trace");
>
> @@ -1785,10 +1776,9 @@ bool
> red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
>
> MarkerPipeItem *mark_item = spice_new0(MarkerPipeItem, 1);
>
> - red_pipe_item_init_full(&mark_item->base, RED_PIPE_ITEM_TYPE_MARKER,
> - marker_pipe_item_free);
> - item_in_pipe = TRUE;
> - mark_item->item_in_pipe = &item_in_pipe;
> + red_pipe_item_init(&mark_item->base, RED_PIPE_ITEM_TYPE_MARKER);
> + mark_item->item_in_pipe = true;
> + red_pipe_item_ref(&mark_item->base);
> red_channel_client_pipe_add_after_pos(rcc, &mark_item->base, item_pos);
>
> if (red_channel_client_is_blocked(rcc)) {
> @@ -1797,7 +1787,7 @@ bool
> red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
> }
> red_channel_client_push(rcc);
>
> - while (item_in_pipe &&
> + while (mark_item->item_in_pipe &&
> (timeout == -1 || spice_get_monotonic_time_ns() < end_time)) {
> usleep(CHANNEL_BLOCKED_SLEEP_DURATION);
> red_channel_client_receive(rcc);
> @@ -1805,9 +1795,11 @@ bool
> red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
> red_channel_client_push(rcc);
> }
>
> + item_in_pipe = mark_item->item_in_pipe;
> + red_pipe_item_unref(&mark_item->base);
> +
> if (item_in_pipe) {
> - // still on the queue, make sure won't overwrite the stack variable
> - mark_item->item_in_pipe = NULL;
> + // still on the queue
> spice_warning("timeout");
> return FALSE;
> } else {
More information about the Spice-devel
mailing list