diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 83acf7ca3..96118be7c 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 4.0 Changelog +* v5.0, 2022-08-24, For [#2136](https://github.com/ossrs/srs/issues/2136): API: Cleanup no active streams for statistics. v4.0.256 * v4.0, 2022-08-17, RTMP URL supports domain in stream parameters. v4.0.255 * v4.0, 2022-08-10, Fix server id generator bug. v4.0.254 * v4.0, 2022-06-29, Update SRS image for r.ossrs.net. v4.0.253 diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index f03a41926..a8f6a8528 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -164,6 +164,11 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj) void SrsStatisticStream::publish(std::string id) { + // To prevent duplicated publish event by bridger. + if (active) { + return; + } + publisher_id = id; active = true; @@ -172,6 +177,11 @@ void SrsStatisticStream::publish(std::string id) void SrsStatisticStream::close() { + // To prevent duplicated close event. + if (!active) { + return; + } + has_video = false; has_audio = false; active = false; @@ -375,22 +385,6 @@ void SrsStatistic::on_stream_close(SrsRequest* req) SrsStatisticVhost* vhost = create_vhost(req); SrsStatisticStream* stream = create_stream(vhost, req); stream->close(); - - // TODO: FIXME: Should fix https://github.com/ossrs/srs/issues/803 - if (true) { - std::map::iterator it; - if ((it=streams.find(stream->id)) != streams.end()) { - streams.erase(it); - } - } - - // TODO: FIXME: Should fix https://github.com/ossrs/srs/issues/803 - if (true) { - std::map::iterator it; - if ((it = rstreams.find(stream->url)) != rstreams.end()) { - rstreams.erase(it); - } - } } srs_error_t SrsStatistic::on_client(std::string id, SrsRequest* req, ISrsExpire* conn, SrsRtmpConnType type) @@ -441,6 +435,40 @@ void SrsStatistic::on_disconnect(std::string id) stream->nb_clients--; vhost->nb_clients--; + + cleanup_stream(stream); +} + +void SrsStatistic::cleanup_stream(SrsStatisticStream* stream) +{ + // If stream has publisher(not active) or player(clients), never cleanup it. + if (stream->active || stream->nb_clients > 0) { + return; + } + + // There should not be any clients referring to the stream. + for (std::map::iterator it = clients.begin(); it != clients.end(); ++it) { + SrsStatisticClient* client = it->second; + srs_assert(client->stream != stream); + } + + // Do cleanup streams. + if (true) { + std::map::iterator it; + if ((it = streams.find(stream->id)) != streams.end()) { + streams.erase(it); + } + } + + if (true) { + std::map::iterator it; + if ((it = rstreams.find(stream->url)) != rstreams.end()) { + rstreams.erase(it); + } + } + + // It's safe to delete the stream now. + srs_freep(stream); } void SrsStatistic::kbps_add_delta(std::string id, ISrsKbpsDelta* delta) diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 6a25c6ec7..4285f3ced 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -173,6 +173,10 @@ public: // only got the request object, so the client specified by id maybe not // exists in stat. virtual void on_disconnect(std::string id); +private: + // Cleanup the stream if stream is not active and for the last client. + void cleanup_stream(SrsStatisticStream* stream); +public: // Sample the kbps, add delta bytes of conn. // Use kbps_sample() to get all result of kbps stat. virtual void kbps_add_delta(std::string id, ISrsKbpsDelta* delta); diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 5443b9c32..0ecbf255e 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 0 -#define VERSION_REVISION 255 +#define VERSION_REVISION 256 #endif