From b0ad7ec40ef4eb09f21a86c802ca6c9f29a97ea6 Mon Sep 17 00:00:00 2001 From: nick evans Date: Thu, 4 Jun 2026 09:21:00 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B5=20Add=20thread=20join=20timeout=20?= =?UTF-8?q?to=20`#disconnect`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since `#disconnect` joins the receiver thread, it may hang until slow response handlers complete. This allows the user to provide a timeout. --- lib/net/imap.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/net/imap.rb b/lib/net/imap.rb index aa7a24aa..7ea8dad5 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -1193,9 +1193,10 @@ def tls_verified?; @tls_verified end # Waits for receiver thread to close before returning, except when called # from inside the connection mutex such as from a response handler. Slow or # stuck response handlers can cause #disconnect to hang until they complete. + # Use +timeout+ to limit how long to wait for the receiver thread to exit. # # Related: #logout, #logout! - def disconnect + def disconnect(timeout: nil) in_logout_state = try_state_logout? return if disconnected? in_receiver_thread = Thread.current == @receiver_thread @@ -1207,7 +1208,7 @@ def disconnect @receiver_thread.raise(e) unless in_receiver_thread end @sock.close - @receiver_thread.join unless mon_owned? || in_receiver_thread + @receiver_thread.join(timeout) unless mon_owned? || in_receiver_thread raise e if e ensure # Try again after shutting down the receiver thread. With no reciever