[Libwebsockets] lws_cancel_service() and libev

Andy Green andy at warmcat.com
Mon Feb 10 01:16:15 CET 2020

On February 9, 2020 10:31:19 PM GMT, Olivier Langlois <olivier at olivierlanglois.net> wrote:
>I have found out that lws_cancel_service() wasn't cancelling foreign
>To workaround this, here is what I had to do:
>1. Create my loop outside lws and pass it through foreign_loops when
>creating my lws_context
>2. Handle LWS_CALLBACK_EVENT_WAIT_CANCELLED and call ev_break() from my
>Maybe this is something that lws could handle itself. This is

... lws_cancel_service() just says it's going to get you the EVENT_WAIT_CANCELLED callback from the event loop context, whatever that may be.  If that's coming quickly after the call, via the pipe() set up for that, it's doing what it's supposed to from lws perspective.  It should be able to do that for all event lib backends, even rtos that doesn't have a wait-integrated pipe() by using lo-bound UDP for the same purpose, because the pipe or udp socket fd is a participant on the event loop.

>definitely a call from the architect in chief but if I was to imagine
>how it could be done, I would say:
>a) Add a cancel operation to the event-libs ops
>b) call the cancel operation from the roles/pipe code where
>Now fixing lws_cancel_service() for libev is causing another problem:

... I don't understand what you think is broken that this 'fixes'.  We already evidently cancelled the event loop wait since we woke up and did the callback.

>Exiting lws_service() with internal loop returns 0 whereas with any
>other loop it returns 1:
>       if (context->event_loop_ops->run_pt) {
>                /* we are configured for an event loop */
>                context->event_loop_ops->run_pt(context, tsi);
>                pt->inside_service = 0;
>                return 1;
>        }
>        n = _lws_plat_service_tsi(context, timeout_ms, tsi);
>        pt->inside_service = 0;
>        return n;
>This is breaking examples code such as minimal-ws-client-echo.c if they
>are used with a foreign loop:
>        while (!lws_service(context, 0) && !interrupted)
>                ;
>Having to find those workarounds did again force me to study lws code
>and this gave me few questions around lws_cancel_service().
>- Why calling lws_cancel_service() from lws_create_context() to
>initialize the protocols?

If there is no network event, depending on the event loop backend once we return to the event loop from create context, it may never come back - ie, remain asleep -  to init the protocols otherwise.

>- Why not just calling lws_protocol_init() directly instead from

IIRC the main reason is it guarantees context creation completed and any user code, typically in main(), that needed the context pointer to init things (eg, to create explicit vhosts) before starting the event loop has been able to get the context pointer and has definitely run, before protocols get their PROTOCOL_INIT to set themselves up on their vhosts.

>- If protocols were initialized before exiting lws_create_context(),
>the code wouldn't have to verify the protocol initialisation from
>various points (such as in lws_client_connect_via_info())...

That checking a flag (in lws internal code) is not very burdensome and lets user code follow the convenient pattern of linearly creating the context and then the vhosts.

Also in lws vhost creation and destruction is something that can happen dynamically too, not just at init.


>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org

More information about the Libwebsockets mailing list