From f013ddfb8970208c44cbbeed5f037a67058e1d36 Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Wed, 24 Aug 2022 17:23:56 -0600 Subject: [PATCH] When monitoring idle connections, only call eof on tcp socket In a heavy cloud storage workflow, I encountered the following error: ``` AssertionError: ctx.bytesavailable > 0 || !(ctx.isreadable) ``` with traces back to calling `eof(::SSLContext)` from `monitor_idle_connection`. As the workflow was highly concurrent, I believe the error was just a data race between an old async `monitor_idle_connection` task calling `eof` -> `wait_for_decrypted_data`, but when returning from `wait_for_decrypted_data` due to a new connection being reused in HTTP.jl, the `handshake` was redone, which resulted in the `AssertionError` shown above. The proposal here is that when monitoring idle connections, we only call `eof` on the underlying TCPSocket, since we're really only concerned with knowing whether the core socket gets additional data, encrypted or not, when we don't expect it. --- src/ConnectionPool.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ConnectionPool.jl b/src/ConnectionPool.jl index 5ca877cad..16e6b8739 100644 --- a/src/ConnectionPool.jl +++ b/src/ConnectionPool.jl @@ -260,9 +260,13 @@ Close `c` on EOF. TODO: or if response data arrives when no request was sent (isreadable == false). """ function monitor_idle_connection(c::Connection) + tcp = c.io + if tcp isa SSLContext + tcp = tcp.bio + end try - if eof(c.io) ;@debugv 3 "💀 Closed: $c" - close(c.io) + if eof(tcp) ;@debugv 3 "💀 Closed: $c" + isopen(c.io) && close(c.io) end catch ex @try Base.IOError close(c.io)