From 149701fdbbfdab267c89783914b2a7380174441e Mon Sep 17 00:00:00 2001 From: krynju Date: Fri, 16 Oct 2026 11:31:32 +0200 Subject: [PATCH] fix: no close_notify from the finalizer The finalizer called `close(ssl)`, which sends the close_notify, a socket write. A write that has to wait for the socket switches tasks, which a finalizer may not do: on nightly, where the socket write path waits more readily, `NoCloseStream` printed "task switch not allowed from inside gc finalizer". Older versions only wait when the socket buffer is full, so the hazard was latent. The finalizer now calls `close(ssl, false)`: the SSL object is freed and the socket closed, nothing is written. Co-Authored-By: Claude Fable 5.1 --- src/ssl.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ssl.jl b/src/ssl.jl index a469f2d..7a2eef5 100644 --- a/src/ssl.jl +++ b/src/ssl.jl @@ -419,7 +419,9 @@ mutable struct SSLStream <: IO bio_write::BIO = BIO(io; finalize=false) ssl = SSL(ssl_context, bio_read, bio_write) x = new(ssl, ssl_context, bio_read, bio_write, io, ReentrantLock(), ReentrantLock(), Ref{Csize_t}(0), Ref{Csize_t}(0), Ref{UInt8}(0x00), Ref{Csize_t}(0), false) - finalizer(close, x) + # no close_notify from the finalizer: sending it is a socket write, which can + # wait for the peer, and a finalizer may not switch tasks + finalizer(x -> close(x, false), x) return x end end