diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index f31485677..96cd485bb 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 7.0 Changelog
+* v7.0, 2025-08-11, Merge [#4432](https://github.com/ossrs/srs/pull/4432): AI: HTTP-FLV: Fix heap-use-after-free crash during stream unmount. v7.0.50 (#4432)
* v7.0, 2025-07-28, Merge [#4245](https://github.com/ossrs/srs/pull/4245): Allow Forward to be configured with Env Var. v7.0.49 (#4245)
* v7.0, 2025-07-16, Merge [#4295](https://github.com/ossrs/srs/pull/4295): RTC: audio packet jitter buffer. v7.0.48 (#4295)
* v7.0, 2025-07-11, Merge [#4333](https://github.com/ossrs/srs/pull/4333): NEW PROTOCOL: Support viewing stream over RTSP. v7.0.47 (#4333)
@@ -60,6 +61,7 @@ The changelog for SRS.
## SRS 6.0 Changelog
+* v6.0, 2025-08-11, Merge [#4432](https://github.com/ossrs/srs/pull/4432): AI: HTTP-FLV: Fix heap-use-after-free crash during stream unmount. v6.0.171 (#4432)
* v6.0, 2025-07-28, Merge [#4245](https://github.com/ossrs/srs/pull/4245): Allow Forward to be configured with Env Var. v6.0.170 (#4245)
* v6.0, 2025-07-10, Merge [#4414](https://github.com/ossrs/srs/pull/4414): Fix H.264 B-frame detection logic to comply with specification. v6.0.169 (#4414)
* v6.0, 2025-06-04, Merge [#4325](https://github.com/ossrs/srs/pull/4325): fix bug: loop transcoding #3516. v6.0.168 (#4325)
diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp
index cfe6d42de..6f48462bd 100755
--- a/trunk/src/app/srs_app_http_stream.cpp
+++ b/trunk/src/app/srs_app_http_stream.cpp
@@ -619,6 +619,26 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
{
srs_error_t err = srs_success;
+ SrsHttpMessage* hr = dynamic_cast(r);
+ SrsHttpConn* hc = dynamic_cast(hr->connection());
+
+ // Add the viewer to the viewers list.
+ viewers_.push_back(hc);
+
+ err = serve_http_impl(w, r);
+
+ // Remove viewer from the viewers list.
+ vector::iterator it = std::find(viewers_.begin(), viewers_.end(), hc);
+ srs_assert (it != viewers_.end());
+ viewers_.erase(it);
+
+ return err;
+}
+
+srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
+{
+ srs_error_t err = srs_success;
+
SrsHttpMessage* hr = dynamic_cast(r);
SrsHttpConn* hc = dynamic_cast(hr->connection());
SrsHttpxConn* hxc = dynamic_cast(hc->handler());
@@ -651,6 +671,11 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
return srs_error_wrap(err, "http hook");
}
+ // Fast check whether stream is still available.
+ if (!entry->enabled) {
+ return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "stream not found");
+ }
+
// Always try to create the source, because http handler won't create it.
SrsSharedPtr live_source;
if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) {
@@ -673,16 +698,13 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
// object is not alive.
SrsUniquePtr consumer(consumer_raw);
- // Add the viewer to the viewers list.
- viewers_.push_back(hc);
+ // Fast check whether stream is still available.
+ if (!entry->enabled) {
+ return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "stream not found");
+ }
// Serve the viewer connection.
err = do_serve_http(live_source.get(), consumer.get(), w, r);
-
- // Remove viewer from the viewers list.
- vector::iterator it = std::find(viewers_.begin(), viewers_.end(), hc);
- srs_assert (it != viewers_.end());
- viewers_.erase(it);
// Do hook after serving.
http_hooks_on_stop(r);
@@ -1321,7 +1343,7 @@ srs_error_t SrsHttpStreamDestroy::call()
// Wait for cache and stream to stop.
int i = 0;
- for (; i < 1024; i++) {
+ for (; i < 3000; i++) {
if (!cache->alive() && !stream->alive()) {
break;
}
@@ -1329,7 +1351,9 @@ srs_error_t SrsHttpStreamDestroy::call()
}
if (cache->alive() || stream->alive()) {
- srs_warn("http: try to free a alive stream, cache=%d, stream=%d", cache->alive(), stream->alive());
+ srs_error("http: try to free an alive stream, sid=%s, cache=%d, stream=%d",
+ sid_.c_str(), cache->alive(), stream->alive());
+ srs_assert(false);
}
// Remove the entry from handlers.
diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp
index 90d897ff3..4085ea559 100755
--- a/trunk/src/app/srs_app_http_stream.hpp
+++ b/trunk/src/app/srs_app_http_stream.hpp
@@ -198,6 +198,9 @@ public:
virtual srs_error_t update_auth(SrsRequest* r);
public:
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
+private:
+ srs_error_t serve_http_impl(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
+public:
virtual bool alive();
// Interface ISrsExpire
public:
diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp
index 2de2cc4e7..7df5576ea 100644
--- a/trunk/src/core/srs_core_version6.hpp
+++ b/trunk/src/core/srs_core_version6.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
-#define VERSION_REVISION 170
+#define VERSION_REVISION 171
#endif
diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp
index bf26d5c86..1ee7bc906 100644
--- a/trunk/src/core/srs_core_version7.hpp
+++ b/trunk/src/core/srs_core_version7.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
-#define VERSION_REVISION 49
+#define VERSION_REVISION 50
#endif
\ No newline at end of file