[Libwebsockets] polling for file descriptor i/o

Andy Green andy at warmcat.com
Sat Mar 4 20:50:15 CET 2017



On March 4, 2017 11:03:48 PM GMT+08:00, Per Bothner <per at bothner.com> wrote:
>On 03/01/2017 03:04 PM, Andy Green wrote:
>>
>>
>> On March 2, 2017 7:41:51 AM GMT+09:00, Per Bothner <per at bothner.com>
>wrote:
>
>>> LWS_CALLBACK_RAW_RX_FILE reads (from the pty child) into a buffer,
>but
>>> waits to write the data out on the WebSocket.  I could defer the
>read
>>>from the child until the WebSocket is writeable, but would that be
>>> right?
>>
>> Yes, in fact it's ideal, but you will have to use the rx flow control
>api to modulate POLLIN, otherwise it will keep tapping you on the
>shoulder until you consume the read data when the ws wsi is writable. 
>You'd reenable the file desc flow control after you read as much as you
>wanted, it'll come back around if there's more, at whatever rate the
>outgoing ws connection can cope with.
>
>The read from the pty fd has to be done in RAW_RX_FILE callback,
>not the SERVER_WRITEABLE callback.
>
>Otherwise, notice trace below. The 2nd poll reports that both the ws
>socket
>is writeable *and* the pty fd is readable.  The former is handled
>first.

Did you use the rx flow control api to "modulate POLLIN" to avoid getting "tapped on the shoulder" continuously with POLLINs?

The flow should be

 - notified of rx on file fd
 - set the parent flag and ask for writeable callback on parent
 - lws_rx_flow_control(wsi, 0); to disable POLLIN / rx notifications

 - notified of parent writeable
 - read child and send data
 - lws_rx_flow_control(wsi_child, 1);  to allow more rx on child file fd

-Andy

>It reads from the pty fd, and writes the ws socket.
>Then we handle the RAW_RX_FILE callback, which just sets the flag
>that we have something to read, and calls lws_callback_on_writable.
>Then the SERVER_WRITEABLE callbak sees we have something to read, calls
>read -
>and hangs, because we already read it.
>
>poll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=10,
>events=POLLIN|POLLOUT}, {fd=11, events=POLLIN}], 4, 10) = 2 ([{fd=10,
>revents=POLLOUT}, {fd=11, revents=POLLIN}])
><<callback_tty CALLBACK_SERVER_WRITEABLE>>
><<callback_tty RAW_RX_FILE>>
>poll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=10,
>events=POLLIN|POLLOUT}, {fd=11, events=POLLIN}], 4, 10) = 2 ([{fd=10,
>revents=POLLOUT}, {fd=11, revents=POLLIN}])
><<callback_tty CALLBACK_SERVER_WRITEABLE>>
>read(11, "\33]777;notify;Command completed;v"..., 2048) = 193
>brk(NULL)                               = 0x1a85000
>brk(0x1aa8000)                          = 0x1aa8000
>brk(NULL)                               = 0x1aa8000
>brk(0x1ad8000)                          = 0x1ad8000
>sendto(10,
>"\302~\0\222\222\216577\267\316\313/\311L\253\264v\316\317\315M\314KQH\316\317-\310I-"...,
>150, MSG_NOSIGNAL, NULL, 0) = 150
><<callback_tty RAW_RX_FILE>>
>poll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=10,
>events=POLLIN|POLLOUT}, {fd=11, events=POLLIN}], 4, 10) = 1 ([{fd=10,
>revents=POLLOUT}])
><<callback_tty CALLBACK_SERVER_WRITEABLE>>
>read(11, 0x1a74d40, 2048)               = ? ERESTARTSYS (To be
>restarted if SA_RESTART is set)
>read(11, <<HANGS>>
>
>What works is for the RAW_RX_FILE callback to do the read (into a
>buffer
>pointer to by the user_data), and then SERVER_WRITEABLE does the write
>from that buffer.



More information about the Libwebsockets mailing list