[Libwebsockets] I may find a bug on lws_write behaviour
andy at warmcat.com
Fri Feb 28 09:40:52 CET 2020
On 2/28/20 7:50 AM, 雷 鸣 wrote:
> According to the comment of function 'lws_write' I found it says that
> * The OS may not accept everything you asked to write on the connection.
> * Posix defines POLLOUT indication from poll() to show that the connection
> * will accept more write data, but it doesn't specifiy how much. It may
> * accept one byte of whatever you wanted to send.
> * LWS will buffer the remainder automatically, and send it out
> * During that time, WRITABLE callbacks will be suppressed.
> But I found the callback comes when last output buffer block is sent.
> I build libwebsockets with libuv and mbedtls in Windows 7 x64, VS2019 by
> arguments of
> I have been with this library for three days in learning how to build a
> I try limiting the transfer speed to simulate FLV live streaming, using
> lws_set_timer_usecs to control the send-flow.
> I found it works with lws_write 1024 bytes per call, but runs into wrong if
> I did it with 65536 bytes per call.
> I traced the program flow and found it ALWAYS request another writeable
> notify (core-net/output.c, line 178) regardless buffered_out is just
> consumed up.
It's true... its problem is while it is concealing writeable callbacks
and sending the oversize data in the background, lws must request by
itself writeable callbacks on that connection, and handle them.
It does not know then if user code has requsted its own writeable
callback that it has trashed and lost by doing the background work. For
that reason, as you say, it always makes a writeable callback request
itself at the end of internally handling them.
> I doubt that it should check buffered_out again before requesting writable
> notify here. And user may or may not request a writeable notify after
> calling lws_write with large block of data.
> Could you staff have a look at the logic whether works as expected?
It is as expected... there is no guarantee you will get callback
requests that you asked for in a 1:1 relationship. You can get extra
ones and additional requests after the first pending one will be ignored
until after the callback happened.
For that reason you have to consult your "pss" per-connection state and
find out what, if anything, you wanted to do with that callback. If
nothing, you can just return 0.
It's better to size what you send to what the kernel will accept in one
go when it tries to send it. TLS has practical a limit of 16KB record
buffer anyway, but once you filled the tcp window, the kernel may only
accept 1 or 2 x mtu (1.5 .. 3KB... but is platform dependent) each time
depending on connection characteristics. There's no point "sending"
something bigger than this then, it's just taking up heap having to hold
it for you while lws hands it out in small chunks the background same as
you would have done yourself.
More information about the Libwebsockets