Skip to content

Commit c20bce9

Browse files
committed
RTX: Fix race condition for timer. v6.0.176 (#4470) (#4474)
1 parent c1a8a5f commit c20bce9

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

trunk/doc/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The changelog for SRS.
77
<a name="v6-changes"></a>
88

99
## SRS 6.0 Changelog
10+
* v6.0, 2025-09-05, RTX: Fix race condition for timer. v6.0.176 (#4470) (#4474)
1011
* v6.0, 2025-08-26, Merge [#4451](https://github.com/ossrs/srs/pull/4451): RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v6.0.175 (#4451)
1112
* v6.0, 2025-08-16, Merge [#4441](https://github.com/ossrs/srs/pull/4441): fix err memory leak in rtc to rtmp bridge. v6.0.174 (#4441)
1213
* v6.0, 2025-08-14, Merge [#4161](https://github.com/ossrs/srs/pull/4161): fix hls & dash segments cleanup. v6.0.173 (#4161)

trunk/src/app/srs_app_rtc_conn.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -945,18 +945,29 @@ srs_error_t SrsRtcPlayStream::do_request_keyframe(uint32_t ssrc, SrsContextId ci
945945

946946
SrsRtcPublishRtcpTimer::SrsRtcPublishRtcpTimer(SrsRtcPublishStream* p) : p_(p)
947947
{
948+
lock_ = srs_mutex_new();
948949
_srs_hybrid->timer1s()->subscribe(this);
949950
}
950951

951952
SrsRtcPublishRtcpTimer::~SrsRtcPublishRtcpTimer()
952953
{
953-
_srs_hybrid->timer1s()->unsubscribe(this);
954+
if (true) {
955+
SrsLocker(lock_);
956+
_srs_hybrid->timer1s()->unsubscribe(this);
957+
}
958+
srs_mutex_destroy(lock_);
954959
}
955960

956961
srs_error_t SrsRtcPublishRtcpTimer::on_timer(srs_utime_t interval)
957962
{
958963
srs_error_t err = srs_success;
959964

965+
// This is a very heavy function, and it may potentially cause a coroutine switch.
966+
// Therefore, during this function, the 'this' pointer might become invalid because
967+
// the object could be freed by another thread. As a result, we must lock the object
968+
// to prevent it from being freed.
969+
SrsLocker(lock_);
970+
960971
++_srs_pps_pub->sugar;
961972

962973
if (!p_->is_started) {
@@ -981,18 +992,29 @@ srs_error_t SrsRtcPublishRtcpTimer::on_timer(srs_utime_t interval)
981992

982993
SrsRtcPublishTwccTimer::SrsRtcPublishTwccTimer(SrsRtcPublishStream* p) : p_(p)
983994
{
995+
lock_ = srs_mutex_new();
984996
_srs_hybrid->timer100ms()->subscribe(this);
985997
}
986998

987999
SrsRtcPublishTwccTimer::~SrsRtcPublishTwccTimer()
9881000
{
989-
_srs_hybrid->timer100ms()->unsubscribe(this);
1001+
if (true) {
1002+
SrsLocker(lock_);
1003+
_srs_hybrid->timer100ms()->unsubscribe(this);
1004+
}
1005+
srs_mutex_destroy(lock_);
9901006
}
9911007

9921008
srs_error_t SrsRtcPublishTwccTimer::on_timer(srs_utime_t interval)
9931009
{
9941010
srs_error_t err = srs_success;
9951011

1012+
// This is a very heavy function, and it may potentially cause a coroutine switch.
1013+
// Therefore, during this function, the 'this' pointer might become invalid because
1014+
// the object could be freed by another thread. As a result, we must lock the object
1015+
// to prevent it from being freed.
1016+
SrsLocker(lock_);
1017+
9961018
++_srs_pps_pub->sugar;
9971019

9981020
if (!p_->is_started) {
@@ -1739,12 +1761,17 @@ void SrsRtcPublishStream::update_send_report_time(uint32_t ssrc, const SrsNtp& n
17391761

17401762
SrsRtcConnectionNackTimer::SrsRtcConnectionNackTimer(SrsRtcConnection* p) : p_(p)
17411763
{
1764+
lock_ = srs_mutex_new();
17421765
_srs_hybrid->timer20ms()->subscribe(this);
17431766
}
17441767

17451768
SrsRtcConnectionNackTimer::~SrsRtcConnectionNackTimer()
17461769
{
1747-
_srs_hybrid->timer20ms()->unsubscribe(this);
1770+
if (true) {
1771+
SrsLocker(lock_);
1772+
_srs_hybrid->timer20ms()->unsubscribe(this);
1773+
}
1774+
srs_mutex_destroy(lock_);
17481775
}
17491776

17501777
srs_error_t SrsRtcConnectionNackTimer::on_timer(srs_utime_t interval)
@@ -1755,6 +1782,12 @@ srs_error_t SrsRtcConnectionNackTimer::on_timer(srs_utime_t interval)
17551782
return err;
17561783
}
17571784

1785+
// This is a very heavy function, and it may potentially cause a coroutine switch.
1786+
// Therefore, during this function, the 'this' pointer might become invalid because
1787+
// the object could be freed by another thread. As a result, we must lock the object
1788+
// to prevent it from being freed.
1789+
SrsLocker(lock_);
1790+
17581791
++_srs_pps_conn->sugar;
17591792

17601793
// If circuit-breaker is enabled, disable nack.

trunk/src/app/srs_app_rtc_conn.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class SrsRtcPublishRtcpTimer : public ISrsFastTimer
283283
{
284284
private:
285285
SrsRtcPublishStream* p_;
286+
srs_mutex_t lock_;
286287
public:
287288
SrsRtcPublishRtcpTimer(SrsRtcPublishStream* p);
288289
virtual ~SrsRtcPublishRtcpTimer();
@@ -296,6 +297,7 @@ class SrsRtcPublishTwccTimer : public ISrsFastTimer
296297
{
297298
private:
298299
SrsRtcPublishStream* p_;
300+
srs_mutex_t lock_;
299301
public:
300302
SrsRtcPublishTwccTimer(SrsRtcPublishStream* p);
301303
virtual ~SrsRtcPublishTwccTimer();
@@ -406,6 +408,7 @@ class SrsRtcConnectionNackTimer : public ISrsFastTimer
406408
{
407409
private:
408410
SrsRtcConnection* p_;
411+
srs_mutex_t lock_;
409412
public:
410413
SrsRtcConnectionNackTimer(SrsRtcConnection* p);
411414
virtual ~SrsRtcConnectionNackTimer();

trunk/src/core/srs_core_version6.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 6
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 175
12+
#define VERSION_REVISION 176
1313

1414
#endif

0 commit comments

Comments
 (0)