diff --git a/README.md b/README.md
index 9b6f31f00..7e94b13bd 100755
--- a/README.md
+++ b/README.md
@@ -146,6 +146,7 @@ For previous versions, please read:
## V3 changes
+* v3.0, 2020-02-17, For [#1601][bug #1601], flush async on_dvr/on_hls events before stop. 3.0.118
* v3.0, 2020-02-14, [3.0 beta1(3.0.117)][r3.0b1] released. 121964 lines.
* v3.0, 2020-02-14, For [#1595][bug #1595], migrating streaming from ossrs.net to r.ossrs.net. 3.0.117
* v3.0, 2020-02-05, For [#665][bug #665], fix HTTP-FLV reloading bug. 3.0.116
@@ -1649,6 +1650,7 @@ Winlin
[bug #1592]: https://github.com/ossrs/srs/issues/1592
[bug #665]: https://github.com/ossrs/srs/issues/665
[bug #1595]: https://github.com/ossrs/srs/issues/1595
+[bug #1601]: https://github.com/ossrs/srs/issues/1601
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
[exo #828]: https://github.com/google/ExoPlayer/pull/828
diff --git a/trunk/src/app/srs_app_async_call.cpp b/trunk/src/app/srs_app_async_call.cpp
index 42df06b5d..271964d99 100644
--- a/trunk/src/app/srs_app_async_call.cpp
+++ b/trunk/src/app/srs_app_async_call.cpp
@@ -40,6 +40,7 @@ SrsAsyncCallWorker::SrsAsyncCallWorker()
{
trd = new SrsDummyCoroutine();
wait = srs_cond_new();
+ lock = srs_mutex_new();
}
SrsAsyncCallWorker::~SrsAsyncCallWorker()
@@ -54,6 +55,7 @@ SrsAsyncCallWorker::~SrsAsyncCallWorker()
tasks.clear();
srs_cond_destroy(wait);
+ srs_mutex_destroy(lock);
}
srs_error_t SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t)
@@ -87,6 +89,7 @@ srs_error_t SrsAsyncCallWorker::start()
void SrsAsyncCallWorker::stop()
{
+ flush_tasks();
srs_cond_signal(wait);
trd->stop();
}
@@ -103,23 +106,40 @@ srs_error_t SrsAsyncCallWorker::cycle()
if (tasks.empty()) {
srs_cond_wait(wait);
}
-
- std::vector copy = tasks;
- tasks.clear();
-
- std::vector::iterator it;
- for (it = copy.begin(); it != copy.end(); ++it) {
- ISrsAsyncCallTask* task = *it;
-
- if ((err = task->call()) != srs_success) {
- srs_warn("ignore task failed %s", srs_error_desc(err).c_str());
- srs_freep(err);
- }
- srs_freep(task);
- }
+
+ flush_tasks();
}
return err;
}
+void SrsAsyncCallWorker::flush_tasks()
+{
+ srs_error_t err = srs_success;
+
+ // Avoid the async call blocking other coroutines.
+ std::vector copy;
+ if (true) {
+ SrsLocker(lock);
+
+ if (tasks.empty()) {
+ return;
+ }
+
+ copy = tasks;
+ tasks.clear();
+ }
+
+ std::vector::iterator it;
+ for (it = copy.begin(); it != copy.end(); ++it) {
+ ISrsAsyncCallTask* task = *it;
+
+ if ((err = task->call()) != srs_success) {
+ srs_warn("ignore task failed %s", srs_error_desc(err).c_str());
+ srs_freep(err);
+ }
+ srs_freep(task);
+ }
+}
+
diff --git a/trunk/src/app/srs_app_async_call.hpp b/trunk/src/app/srs_app_async_call.hpp
index 4576f312e..7cc183f4a 100644
--- a/trunk/src/app/srs_app_async_call.hpp
+++ b/trunk/src/app/srs_app_async_call.hpp
@@ -61,6 +61,7 @@ private:
protected:
std::vector tasks;
srs_cond_t wait;
+ srs_mutex_t lock;
public:
SrsAsyncCallWorker();
virtual ~SrsAsyncCallWorker();
@@ -73,6 +74,8 @@ public:
// Interface ISrsReusableThreadHandler
public:
virtual srs_error_t cycle();
+private:
+ virtual void flush_tasks();
};
#endif
diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp
index aca14581a..cb281e7bd 100644
--- a/trunk/src/app/srs_app_dvr.cpp
+++ b/trunk/src/app/srs_app_dvr.cpp
@@ -740,8 +740,6 @@ srs_error_t SrsDvrSessionPlan::on_publish()
void SrsDvrSessionPlan::on_unpublish()
{
- SrsDvrPlan::on_unpublish();
-
// support multiple publish.
if (!dvr_enabled) {
return;
@@ -754,6 +752,10 @@ void SrsDvrSessionPlan::on_unpublish()
}
dvr_enabled = false;
+
+ // We should notify the on_dvr, then stop the async.
+ // @see https://github.com/ossrs/srs/issues/1601
+ SrsDvrPlan::on_unpublish();
}
SrsDvrSegmentPlan::SrsDvrSegmentPlan()
@@ -815,14 +817,16 @@ void SrsDvrSegmentPlan::on_unpublish()
{
srs_error_t err = srs_success;
- SrsDvrPlan::on_unpublish();
-
if ((err = segment->close()) != srs_success) {
srs_warn("ignore err %s", srs_error_desc(err).c_str());
srs_freep(err);
}
dvr_enabled = false;
+
+ // We should notify the on_dvr, then stop the async.
+ // @see https://github.com/ossrs/srs/issues/1601
+ SrsDvrPlan::on_unpublish();
}
srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp
index 5ffe4b0cd..98bfcd5fc 100644
--- a/trunk/src/app/srs_app_rtmp_conn.cpp
+++ b/trunk/src/app/srs_app_rtmp_conn.cpp
@@ -406,7 +406,7 @@ srs_error_t SrsRtmpConn::service_cycle()
rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT);
rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT);
- srs_trace("rtmp: retry for republish");
+ srs_info("rtmp: retry for republish");
srs_freep(err);
continue;
}
diff --git a/trunk/src/core/srs_core_version3.hpp b/trunk/src/core/srs_core_version3.hpp
index c8793a0a8..4ddcca91c 100644
--- a/trunk/src/core/srs_core_version3.hpp
+++ b/trunk/src/core/srs_core_version3.hpp
@@ -24,6 +24,6 @@
#ifndef SRS_CORE_VERSION3_HPP
#define SRS_CORE_VERSION3_HPP
-#define SRS_VERSION3_REVISION 117
+#define SRS_VERSION3_REVISION 118
#endif