[Libwebsockets] Multi-tail ring-buffer's oldest_tail issue

Ariel D'Alessandro ariel at vanguardiasur.com.ar
Tue Nov 27 14:38:52 CET 2018


Hi,

I have a question related to the multi-tail ring-buffer implementation.
Specifically on what happens with the ring-buffer's oldest_tail when the
object with *that* tail is removed from the list of objects.

As you can see in some of the minimal-examples, e.g.:

    minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c

when the client connection is closed, the object is removed from the
list of living objects, but the ring-buffer is not updated at all.

    case LWS_CALLBACK_CLOSED:
        /* remove our closing pss from the list of live pss */
        lws_ll_fwd_remove(struct per_session_data__minimal, pss_list,
                          pss, vhd->pss_list);
        break;

On the other hand, elements on the ring-buffer are consumed by a call to:

    lws_ring_consume_and_update_oldest_tail(
        vhd->ring,
        struct per_session_data__minimal,
        &pss->tail,
        1,
        vhd->pss_list,
        tail,
        pss_list
    );

which updates the oldest_tail based on the living objects' tails. But it
will only update the oldest_tail if the actual consumer *is* the
oldest_tail:

    #define lws_ring_consume_and_update_oldest_tail(\
        [ ... ]
        ) { \
            int ___n, ___m; \
        \
        ___n = lws_ring_get_oldest_tail(___ring) == *(___ptail); \
        lws_ring_consume(___ring, ___ptail, NULL, ___count); \
        if (___n) { \
            [ ... update oldest_tail ... ]
        } \
    }

So, the issue I see is the following sequence:
* Object A is the *only* living object with a tail matching the
ring-buffer's oldest_tail.
* Object A is removed from the list of living objects, without updating
the ring-buffer's oldest tail (as in the minimal-example above).
* Further calls to lws_ring_consume_and_update_oldest_tail on the list
of living objects won't update the ring-buffer's oldest_tail as nobody
has a tail matching it.

Does this make any sense? Shold we be "consuming" all its waiting
elements before removing the object from list of living objects?

    case LWS_CALLBACK_CLOSED:
        lws_ring_consume_and_update_oldest_tail(
            vhd->ring,
            struct per_session_data__minimal,
            &pss->tail,
            /* Consume all waiting elements within this tail. */
            lws_ring_get_count_waiting_elements(vhd->ring, &pss->tail),
            vhd->pss_list,
            tail,
            pss_list
        );
        /* remove our closing pss from the list of live pss */
        lws_ll_fwd_remove(struct per_session_data__minimal, pss_list,
                          pss, vhd->pss_list);
        break;

Thanks,

-- 
Ariel D'Alessandro, VanguardiaSur
www.vanguardiasur.com.ar


More information about the Libwebsockets mailing list