[Libwebsockets] surprise when using equivalent file descriptors

Per Bothner per at bothner.com
Wed Nov 4 23:02:36 CET 2020

On 11/4/20 12:14 PM, andy at warmcat.com wrote:

>> The obvious fix once I realized the failure was EAGAIN was:
> ...
> If we're literally talking about both the original fd and its dup() both managed by lws event loop, it's not really 'wrong', but it means that from the event / wake perspective if one fd feels POLLIN state is called for because something to read on the underlying shared socket,

Not a socket in this case, but same (slave side of) pty.

> the other, dup-ed fd will definitely feel the same way, and probably atomically, ie either neither fd will come out of the wait with POLLIN indicated, or both will.
> Normally the RX callback is only executed due to a POLLIN indication on the fd, we already know there will be something to read and there won't be any EAGAIN possible.  But servicing the first fd also read what was originally thought to be waiting on the dup'd guy too, and when he services his separate POLLIN there is usually nothing to read any more in the shared underlying object, unless new rx data raced it.

Yes, that is what I figured.

> If it's about that dup case, accepting EAGAIN as normal for fd isn't much overhead.... but... from your earlier description, if fd 1== stdout, the fd might not support POLLIN / rx if, eg, opened O_WRONLY.

I don't think that could happen if they're both dup'd from the same descriptor
(a pty or socket), since stdin has to be readable and stdout has to be writable.
So I don't see that as an issue.

> For both cases if the fd's real purpose is simplex output like driving stdout or stderr you can defeat POLLIN event on the fd by 'set' (the flag is 0) rx flow control on it permanently

I tried this, and it seems to work (without getting EAGAIN)

     lws_sock_file_fd_type fd;
     fd.filefd = options->fd_in;
     struct lws *pin_lws = lws_adopt_descriptor_vhost(vhost, 0, fd, "proxy", NULL);
     struct lws *pout_lws;
     if (options->fd_out == options->fd_in) {
         pout_lws = pin_lws;
     } else {
         fd.filefd = options->fd_out;
         pout_lws = lws_adopt_descriptor_vhost(vhost, 0, fd, "proxy-out", NULL);
         lws_rx_flow_control(pout_lws, 0);

The "proxy" and "proxy-out" protocols have the same callback functions,
so most of the logic is the same whether pin_lws and pout_lws are
the same object or not.  (Even if they're different, they share 'user' structure.)
	--Per Bothner
per at bothner.com   http://per.bothner.com/

More information about the Libwebsockets mailing list