Commit 39cfc744bf for ffmpeg

commit 39cfc744bfb1e8a94f77419cf316ef731b214daf
Author: Thomas Devoogdt <thomas@devoogdt.com>
Date:   Sun Jul 19 19:23:52 2026 +0200

    avformat/tls_gnutls, tls_openssl: fix AVERROR_EXIT in write callbacks

    Returning 0 from a TLS write callback means "0 bytes sent", not "abort".
    GnuTLS therefore retries the write forever, and OpenSSL reports success
    while silently dropping the record.  Report an error instead: errno =
    EINTR, as required by the GnuTLS transport callback contract, and
    c->io_err for OpenSSL, so that an interrupted ffurl_write() propagates
    to the caller rather than hanging or losing data.

    Signed-off-by: Thomas Devoogdt <thomas@devoogdt.com>

diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c
index aedbc66e56..c40c2cd7f3 100644
--- a/libavformat/tls_gnutls.c
+++ b/libavformat/tls_gnutls.c
@@ -475,9 +475,10 @@ static ssize_t gnutls_url_push(gnutls_transport_ptr_t transport,
     int ret = ffurl_write(uc, buf, len);
     if (ret >= 0)
         return ret;
-    if (ret == AVERROR_EXIT)
-        return 0;
-    if (ret == AVERROR(EAGAIN)) {
+    if (ret == AVERROR_EXIT) {
+        /* Use EINTR, not 0: returning 0 would cause GnuTLS to busy-spin. */
+        errno = EINTR;
+    } else if (ret == AVERROR(EAGAIN)) {
         errno = EAGAIN;
     } else {
         errno = EIO;
diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c
index 789dae48a0..0075288d61 100644
--- a/libavformat/tls_openssl.c
+++ b/libavformat/tls_openssl.c
@@ -580,8 +580,9 @@ static int url_bio_bwrite(BIO *b, const char *buf, int len)
         return ret;
     BIO_clear_retry_flags(b);
     if (ret == AVERROR_EXIT)
-        return 0;
-    if (ret == AVERROR(EAGAIN))
+        /* Don't return 0: that signals success and silently drops the data. */
+        c->io_err = ret;
+    else if (ret == AVERROR(EAGAIN))
         BIO_set_retry_write(b);
     else
         c->io_err = ret;