Subject: Re: Multiple channels and epoll(7)

Re: Multiple channels and epoll(7)

From: John-Mark Gurney <>
Date: Mon, 16 Nov 2020 11:48:19 -0800

Jason Ni wrote this message on Mon, Nov 16, 2020 at 10:23 +0800:
> I was trying to use async-ssh2, which is an async wrapper of libssh2, to
> implement a remote port forward proxy.
> However, I may encounter the same issue as talked in this thread 6 years
> before.
> Could any one help to confirm that is there any rework or fix of this issue?

I'd like to see this as well... I'm running into an issue that in order to
work around the api brokenness, that I end up busy waiting. This is because
when opening a channel (new sftp connection), you can't tell if the EAGAIN
is due to another channel receiving data, and needing to continue, or if
it needs work to progress.

> ----------------------------------------------------------------------------------------------------
> From: Henrik Nordström <
> <>>
> Date: Fri, 27 Jun 2014 11:19:11 +0200
> tor 2014-06-26 klockan 23:24 -0600 skrev Eduardo Silva:
> *> but there is a remaining problem, when i get the notification that *
> *> some data is available, after try to accept a channel and then read *
> *> all channels, i need a timeout in the event loop to re-check if *
> *> something was pending. Still wondering how to avoid that re-check. *
> Looking at your code, and thinking and ugh... the libssh2 API is borked
> when it comes to handling of multiple concurrent channels.
> What I said earlier might work if you set epoll into edge triggered mode
> unless kernel cancels events if they get cleared before processed (I do
> not remember what happens, maybe kernel release dependent even). But
> current libssh2 API makes any level triggered non-blocking I/O on
> multiple channels unreliable (including poll/select) and requires a
> short timeout to avoid blocking due to incoming packets being held in
> the libssh2 packets queue without the application being aware.
> Looping over all channels until all report EAGAIN shortens the window
> where this may happen, but do not eleminate it as packets may still
> arrive into the packet queue while you process later channels.
> The earlier discussed API addition of giving access to inspect the
> packet queue would help solving this. You then loop processing until
> internal packet queue is drained. When internal packet queue is drained
> you know that libssh is actually waiting for the socket.
> Separating I/O from processing would also solve this problem and likely
> scale better with number of channels, removing the implicit socket read
> from libssh2_channel_read() and friends, requiring a explicit separate
> call to read the socket.
> Another interesting thought would be to aim to rework the libssh2 API to
> the level that it can support libevent buffered I/O events and similar
> I/O loops by delegating all actual I/O to the application. Above is
> likely a first step towards that.

  John-Mark Gurney				Voice: +1 415 225 5579
     "All that I will do, has been done, All that I have, has not."
Received on 2020-11-16