Fix callback exception handling to be per-Connection instead of per-Context (#1535)
* Track callback exceptions per Connection instead of per helper
Exceptions raised inside verify, ALPN selection, OCSP and DTLS cookie
callbacks cannot be raised from inside the callback, so they were
deferred on a _CallbackExceptionHelper and re-raised by
Connection._raise_ssl_error on the next send/recv/do_handshake. For
callbacks registered on a Context, that helper (and its FIFO of pending
exceptions) was shared by every Connection created from the Context.
Because cffi releases the GIL around the SSL_* calls, a server that
drives connections from several threads could have one connection pop
and raise an exception that another connection's callback produced,
aborting an otherwise healthy connection with a misattributed error,
while the connection that actually failed reported a generic SSL error
(or an IndexError from the unsynchronised check-then-pop).
Record the pending exceptions on the Connection whose callback raised
them instead, and have _raise_ssl_error and DTLSv1_listen only raise
that connection's own. With no shared state left, the
_CallbackExceptionHelper base class has nothing to do and is removed.
This also fixes exceptions raised from a verify callback installed via
Connection.set_verify being silently dropped: _raise_ssl_error only
consulted the Context's verify helper, but the callback OpenSSL actually
invokes for a connection is the one copied at SSL_new time or the one
installed by Connection.set_verify.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A46SM1jtRoG4Yh5P2k9cUm
* Clear the OpenSSL error queue directly before raising a callback exception
_raise_callback_problem drained the thread's OpenSSL error queue by
calling _raise_current_error() and swallowing the resulting Error. That
relies on _raise_current_error() raising even when the queue is empty,
and obscures the intent. _raise_ssl_error already uses ERR_clear_error()
for the same purpose a few lines further down; do the same here.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A46SM1jtRoG4Yh5P2k9cUm
* Credit the reporter in the changelog
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A46SM1jtRoG4Yh5P2k9cUm
---------
Co-authored-by: Claude <noreply@anthropic.com>
3 files changed