[Libwebsockets] 'Close' frame with external message loop issue

Andrejs Hanins andrejs.hanins at ubnt.com
Tue Nov 3 16:49:14 CET 2015



On 11/03/2015 04:57 PM, Andy Green wrote:
> 
> 
> On 3 November 2015 22:46:09 GMT+08:00, Andrejs Hanins <andrejs.hanins at ubnt.com> wrote:
>>
>>
>> On 11/02/2015 09:21 PM, Andy Green wrote:
>>>
>>>
>>> On 3 November 2015 02:49:15 GMT+08:00, Andrejs Hanins
>> <andrejs.hanins at ubnt.com> wrote:
>>>>
>>>>
>>>> On 11/02/2015 08:25 PM, Andy Green wrote:
>>>>>
>>>>>
>>>>> On 2 November 2015 22:52:59 GMT+08:00, Andrejs Hanins
>>>> <andrejs.hanins at ubnt.com> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> 	I'm using LWS in server mode with external message loop (i.e. I
>>>> call
>>>>>> libwebsocket_service_fd by myself based on poll events reported by
>>>>>> external mechanism). Everything works absolutely fine, except when
>>>> WS
>>>>>> client sends a 'Close' frame to the sever. The frame is
>> successfully
>>>>>> received by server (server log has 'server sees client close
>>>> packet')
>>>>>> but the client doesn't receive a response to 'Close' frame. I see
>>>> that
>>>>>> server requests 'writable' state with the intention to respond
>> back
>>>> to
>>>>>> the client (POLLOUT added to the events), 'writable' state is
>> indeed
>>>>>> acquired as per message 'lws_calllback_as_writeable: 0xb39910
>>>>>> (user=0xb99a50)' followed only by a single user callback
>>>>>> LWS_CALLBACK_SERVER_WRITEABLE. The actual sending of 'Close'
>>>> response
>>>>>> doesn't happedn.
>>>>>>
>>>>>> 	I have a suspicion that this situation is not handled properly by
>>>> LWS
>>>>>> code. Instead of sending an internal frame ('Close' response), the
>>>>>> library just calls LWS_CALLBACK_SERVER_WRITEABLE *as if* user had
>>>>>> requested a write, but this is not the case. User code doesn't
>> have
>>>>>> anything to write. As a result, system ends up in hanged state -
>>>> client
>>>>>> wait for 'Close' response, but server does nothing.
>>>>>
>>>>> Is your lws older than a couple of weeks?  This patch was aimed at
>>>> solving that:
>>>>>
>>>>>
>>>>
>> http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/commit/?id=2488c46c9bbed0ff5f1438f8709421effe4b224b
>>>>
>>>> I'm using latest stable tag v1.5-chrome47-firefox41 which includes
>>>> mentioned fix. But yes, the
>>>> issue seems to be somewhat similar, because I also get unexpected
>>>> writable cb.
>>>
>>> Might be worth dumping wsi->state at the place that's patched, in
>> case it's a slightly different close-related state than is checked for
>> atm.
>>
>> Did that and got the following log:
>>
>> written 66 bytes to client
>> spill on uh-ws-proto
>> server sees client close packet
>> libwebsocket_read: read_ok
>> lws_handle_POLLOUT_event 7 <--- 7 is WSI_STATE_RETURNED_CLOSE_ALREADY
>> lws_calllback_as_writeable: 0x9e9bf0 (user=0x9e9680)
>>
>> There is nothing else follows in the log.
>>
>> So, the state 7 is already handled by the patch, but the connection is
>> still not closed and user writable callback is called.
>> Although, I'm struggling to understand how writable callback *is not*
> 
> From the user code perspective, it looks like that.
> 
> But in fact that api sets POLLOUT able to do something.  After POLLOUT comes, other code in the library on POLLOUT path can write things, but in this case not call the user code.
> 
>> supposed to be called in state 7 if the last line of
>> lws_handle_POLLOUT_event() method is exactly
>> lws_calllback_as_writeable().
>>
>> Any other ideas to try?
> 
> Not sure what your problem is now... originally it was extra writeable callback coming to user code, right?  But this patch does suppress it?  Or still two?

The original problem is that LWS server doesn't answer to 'Close' packet sent by client which wants to close the connection.
We have captured the traffic and the last two packets in the capture are:
C -> S: Websocket 'Close' packet (---> server sees client close packet)
S -> C: TCP ACK with zero-length payload (that is, no websocket message)

So, instead of sending a response to 'Close' packet, server only calls user writable callback and doesn't close the WS
connection.


> 
> -Andy
> 
>>>
>>> -Andy
>>>
>>>>>
>>>>> -Andy
>>>>>
>>>>>> 	I tried to call libwebsocket_service(ctx, 0) each time I receive
>>>>>> LWS_CALLBACK_SERVER_WRITEABLE, but it also doesn't help for some
>>>>>> reason. I just got additional callback to
>> LWS_CALLBACK_GET_THREAD_ID
>>>>>> for which I always return 0.
>>>>>>
>>>>>> BR, Andrey
>>>>>> _______________________________________________
>>>>>> Libwebsockets mailing list
>>>>>> Libwebsockets at ml.libwebsockets.org
>>>>>> http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>>>>>
>>>
> 



More information about the Libwebsockets mailing list