Commit f976bb1cb7 for ffmpeg
commit f976bb1cb725e2a450bb8b86df07c0a06db377bb
Author: Martin Storsjö <martin@martin.st>
Date: Mon Sep 21 15:49:04 2026 +0300
tls_openssl: Call ERR_clear_error before OpenSSL IO functions
OpenSSL stores errors in a thread specific queue. If an earlier
function call has set an error that we haven't observed/consumed,
then this can affect the output of SSL_get_error on the same
thread. (This is an issue in particular for nonblocking IO, where
a SSL_WANT_WRITE case instead can return an old queued fatal error.)
Such fatal errors can be set if SSL_shutdown is called on a connection
that isn't in the right state for doing a proper shutdown.
The documentation for SSL_get_error,
https://docs.openssl.org/3.4/man3/SSL_get_error/, explicitly says:
> The current thread's error queue must be empty before the TLS/SSL
> I/O operation is attempted, or SSL_get_error() will not work reliably.
diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c
index 48b4a2226a..f417953404 100644
--- a/libavformat/tls_openssl.c
+++ b/libavformat/tls_openssl.c
@@ -649,6 +649,7 @@ static int dtls_handshake(URLContext *h)
goto end;
}
+ ERR_clear_error();
ret = SSL_do_handshake(c->ssl);
if (ret == 1) {
av_log(c, AV_LOG_TRACE, "Handshake success\n");
@@ -907,6 +908,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
}
av_log(c, AV_LOG_VERBOSE, "Setup ok, MTU=%d\n", c->tls_shared.mtu);
} else {
+ ERR_clear_error();
ret = s->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl);
if (ret == 0) {
av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
@@ -941,6 +943,7 @@ static int tls_read(URLContext *h, uint8_t *buf, int size)
// Set or clear the AVIO_FLAG_NONBLOCK on the underlying socket
uc->flags &= ~AVIO_FLAG_NONBLOCK;
uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
+ ERR_clear_error();
ret = SSL_read(c->ssl, buf, size);
if (ret > 0)
return ret;
@@ -965,6 +968,7 @@ static int tls_write(URLContext *h, const uint8_t *buf, int size)
size = FFMIN(size, mtu_size);
}
+ ERR_clear_error();
ret = SSL_write(c->ssl, buf, size);
if (ret > 0)
return ret;