Hi,
Excellent, so I think I am finally understanding this correctly. And yes, we do have epoll timeouts to clean up all sort of missed race conditions and bugs (either in kernel or user mode).
For performance reasons, EDGE trigger is a must for my application.
What if instead of using select to understand the socket status (big hammer), I will simple retry the call?
For example, if SSL_read returns WANT_*, I do another SSL_read. On the low chance that this is a negotiation, there will be forward progress and I am fine. If not, I know that the socket is blocked.
It is too bad that I cannot differentiate between the two states without going to kernel space. I wish there were some way by just querying SSL. I see that there is a family of SSL_want* methods. Can these be of use?
Regards,
Eran.
On Wed, Jan 29, 2020 at 6:12 PM Michael Wojcik <Michael.Wojcik@xxxxxxxxxxxxxx> wrote:
> From: Eran Borovik [mailto:eran.borovik@xxxxxxxxx]
> Sent: Wednesday, January 29, 2020 07:32
Please respond to the list rather than directly to me, since the subject
may be of interest to other readers. I'm including the list in this
response.
> The only thing that still confuses me is that if I am reading the docs
> correctly, SSL_read may return SSL_WANT_WRITE and SSL_write may return
> SSL_WANT_READ even when they don't encounter a blocking condition, but
> because of negotiation.
Right.
> Now, I use edge triggered polling with Epoll (EPOLLET), which means
> that if SSL_read/write decides to give me an WANT* status when the
> socket doesn't have a blocking condition, then epoll will never wake
> and I am stuck (unless I understand that this is the case and retry
> immediately). Is there a way to actually understand that there is a
> blocking condition in the socket from OpenSSL or do I need to use
> select with zero timeout to realize what is the correct condition of
> the socket after each time SSL gives me SSL_WANT*?
Yes, I think you need to test for readability / writability at some
point. You can do that immediately when you get a WANT_*, or you can
have your epoll time out periodically and test then if you have
pending I/O.
Personally, I'm leery of edge-triggered activation for this reason.
It's too easy to miss some race condition or other case where you
might end up blocked forever. I'd always have epoll time out so you
can do a level-poll of all sockets that have pending operations;
that turns a failure mode into one that simply has suboptimal
performance, at a small resource cost.
--
Michael Wojcik
Distinguished Engineer, Micro Focus