PR #25635 opened by Marti2203
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25635
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25635.patch
Follow-up to #25505, from a pre-existing issue noted in the Forgejo_Fairy
review there.
In single-client listen mode (`listen=1`), `http_listen()` returns handshake
errors without closing `s->hd`, and `http_open()` returns that result directly
instead of going through its `bail_out` cleanup, so `s->uri` and the other
allocations are kept as well. Since `ffurl_connect()` only marks the context
connected after a successful open, `http_close()` is never called for it.
A program that calls `avio_open2("http://127.0.0.1:18080", AVIO_FLAG_WRITE,
..., listen=1)` in a loop, with a client that sends `BOGUS\r\n\r\n` and hangs
up each time, ends up with 26 open fds after 20 failed opens on master (6
before). With this patch it stays at 6. `fate-http-status-line`, `fate-url` and
`fate-api-seek` pass.
The patch closes the lower connection on failure in `http_listen()` and lets
`http_open()` fall through to `bail_out`. It does not touch `http_close()`, so
no `0\r\n\r\n` chunk footer can be sent to a client that never got a reply
header.
Not covered here: in multi-client mode (`listen=2`), a context returned by
`avio_accept()` is not marked connected until its handshake succeeds, so
closing it after a failed handshake (or before any handshake, as the parent
process in `doc/examples/avio_http_serve_files.c` does) also skips
`http_close()` and keeps the accepted socket open. Fixing that needs
`http_close()` to know whether a reply was sent, so it is left for a separate
change.
This issue was found during an LLM review (Forgejo_Fairy, #25505); the fix was
verified manually.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
From d8dbe449a9ebec1f17bb9a545de82fa0524e4861 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Sat, 31 Oct 2026 13:47:50 +0800
Subject: [PATCH] avformat/http: close the connection if the single-client
handshake fails
http_listen() returned handshake errors without closing the lower
connection, and http_open() returned the result of http_listen()
directly, so the URI and other allocations were not freed either.
ffurl_connect() marks the context connected only after a successful
open, so http_close() is not called afterwards and nothing else
releases them.
An application that calls avio_open2() with listen=1 in a loop leaked
one socket for every client whose request failed, e.g. a bad request
line or a client that hung up early.
Signed-off-by: Martin Mirchev <[email protected]>
---
libavformat/http.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/libavformat/http.c b/libavformat/http.c
index 2f4f522363a..bab2719997d 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -809,6 +809,8 @@ static int http_listen(URLContext *h, const char *uri, int
flags,
while ((ret = http_handshake(h)) > 0);
}
fail:
+ if (ret < 0)
+ ffurl_closep(&s->hd);
av_dict_free(&s->chained_options);
av_dict_free(&s->cookie_dict);
return ret;
@@ -858,10 +860,10 @@ static int http_open(URLContext *h, const char *uri, int
flags,
}
}
- if (s->listen) {
- return http_listen(h, uri, flags, options);
- }
- ret = http_open_cnx(h, options, 0);
+ if (s->listen)
+ ret = http_listen(h, uri, flags, options);
+ else
+ ret = http_open_cnx(h, options, 0);
bail_out:
if (ret < 0) {
av_dict_free(&s->chained_options);
--
2.54.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]