[Libwebsockets] polling for file descriptor i/o

Andy Green andy at warmcat.com
Sun Mar 5 04:08:08 CET 2017

On 5 March 2017 10:34:45 GMT+08:00, Per Bothner <per at bothner.com> wrote:
>On 03/04/2017 03:39 PM, Andy Green wrote:
>> Is it ok if multiple rx come before the remote side becomes
>writeable?  Mirror can do that safely only because he has a fifo and
>ultimately rx flow control to manage when he will get new rx.  So he
>never gets rx with nowhere to put it.
>Bytes from the pty are appended to a buffer, so it is ok if multiple rx
>come before the remote side becomes writeable.
>It would be easy enough to reallocate the buffer if it fills up.
>However, we don't want to let the client process run wild - just like
>with a pipe,
>we'd want suspend the client when it has produced too much output.

Exactly... rx flow control does this.  If the receiver is not draining the incoming data, the tcp window fills up and the sender side will block (or not signal POLLOUT).  So there is a "backpressure" mechanism that makes itself felt all the way back to the source just like a shell pipe does.

>If a less-like pager is built into ldomterm (as I've been thinking
>you'd want the user to be able to use a commend to kill the running
>process and
>discard extra output.  That's easier (and cheaper) if the client gets
>when it has produced huge amounts of output.
>So perhaps this makes sense:  On each LWS_CALLBACK_RAW_RX_FILE append
>to a buffer
>(which LWS_CALLBACK_SERVER_WRITEABLE later extracts).  If the buffer is
>too much, send a SIGTSTP to the child progess.

I think that's a separate issue... flow control is needed because the remote sink for the data may go away silently for short or long periods.  His train may go in a tunnel etc but the source is still spamming.  Stretchy buffers will help but there's a limit to it; it doesn't scale well for memory if there are huge numbers of sessions and / or clients.

>> Without that since rx can come when it likes you can get a system
>that is fragile against real-world network links where the remote
>connection becoming writeable in effect races the next rx coming.
>> If you will do the read in the rx callback and buffer it, it's ok but
>the rx flow control stuff is mandatory.
>I'm having problems getting rx flow control to work.  I'll experiment
>some more.
>>  Doing the read in the writable callback lets you eliminate the
>memory for the per-connection bulk data buffer, but otherwise the same.
>> BTW I am still going on the zip integration... I can't use mmap since
>some platforms we support don't have it.
>On non-mmap platforms you could read the zip file into a buffer in
>memory.  That is always supported
>- but of course it might be expensive on low-memory platforms.

The kind of low-end platforms lws covers include things like ESP8266 (total memory: 72KB) and ESP32 (a bit more but still measured in KB), there will probably be more of these very resource-constrained devices.  They're the ones that really benefit from being able to store and serve stuff gzip-compressed.  They really need no requirement to have everything in one place in memory at one time, either compressed or uncompressed.

permessage-deflate extension lws already has works the same, only compressing or decompressing a chunk at a time even for very large streams.

>>So several iterations of optimization have ended up with libz stuff
>directly being called from zip_fops, no storage of the zip index in
>memory, that suggested other improvements to fops like generic file
>position and length held there, that has other knock-ons.  I also have
>implemented chunked inflate, so it does not require memory to inflate
>the whole file any more, but does it piecemeal like permessage-deflate,
>and seeking (although it is expensive since it restarts the inflate and
>inflates its way to the seek point).
>> The last problem yesterday was I changed the code to use really
>virtual file paths, like /var/www/docs/manual.zip/index.html... that
>looks like it will require adding fstat to the fops, since lws serving
>code wants fstat it before opening it.
>As long as I have the *option* of serving the zip file from memory
>mmap or initialized data).

Can you live with creating it in a tmpfs?  If not we can probably figure another way.


Sent from my Android device with K-9 Mail. Please excuse my brevity.

More information about the Libwebsockets mailing list