From df7faa16031aec8df877605f9478ab6f67331205 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 4 Nov 2021 08:47:40 +0800 Subject: [PATCH 1/6] For #2369, #1708, #1941: Add utest to cover fail for close or stop --- trunk/src/utest/srs_utest_service.cpp | 111 +++++++++++++++++++++----- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index c9d13ac3e..d9f381dba 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -69,28 +69,19 @@ class MockTcpHandler : public ISrsTcpHandler private: srs_netfd_t fd; public: - MockTcpHandler(); - virtual ~MockTcpHandler(); + MockTcpHandler() { + fd = NULL; + } + virtual ~MockTcpHandler() { + srs_close_stfd(fd); + } public: - virtual srs_error_t on_tcp_client(srs_netfd_t stfd); + virtual srs_error_t on_tcp_client(srs_netfd_t stfd) { + fd = stfd; + return srs_success; + } }; -MockTcpHandler::MockTcpHandler() -{ - fd = NULL; -} - -MockTcpHandler::~MockTcpHandler() -{ - srs_close_stfd(fd); -} - -srs_error_t MockTcpHandler::on_tcp_client(srs_netfd_t stfd) -{ - fd = stfd; - return srs_success; -} - VOID TEST(TCPServerTest, PingPong) { srs_error_t err; @@ -1459,7 +1450,7 @@ public: int r0; int r1; SrsFastCoroutine trd; - MockStopSelfThread() : trd("mock", this), r0(0), r1(0) { + MockStopSelfThread() : r0(0), r1(0), trd("mock", this) { } virtual ~MockStopSelfThread() { } @@ -1476,12 +1467,88 @@ public: } }; -VOID TEST(StopSelfThreadTest, ShouldFailWhenStopSelf) +VOID TEST(ThreadCriticalTest, ShouldFailWhenStopSelf) { + srs_error_t err; MockStopSelfThread trd; - trd.start(); + HELPER_EXPECT_SUCCESS(trd.start()); + + // Switch to thread cycle, should fail. srs_usleep(0); EXPECT_EQ(-1, trd.r0); EXPECT_EQ(EDEADLK, trd.r1); } +class MockAsyncReaderThread : public ISrsCoroutineHandler +{ +public: + SrsFastCoroutine trd; + srs_netfd_t fd; + MockAsyncReaderThread(srs_netfd_t v) : trd("mock", this), fd(v) { + } + virtual ~MockAsyncReaderThread() { + } + srs_error_t start() { + return trd.start(); + } + void stop() { + trd.stop(); + } + virtual srs_error_t cycle() { + srs_error_t err = srs_success; + while (true) { + if ((err = trd.pull()) != srs_success) { + return err; + } + char buf[16] = {0}; + if (st_read((st_netfd_t)fd, buf, sizeof(buf), SRS_UTIME_NO_TIMEOUT) <= 0) { + break; + } + } + return err; + } +}; + +VOID TEST(ThreadCriticalTest, FailIfCloseActiveFD) +{ + srs_error_t err; + + MockTcpHandler h; + SrsTcpListener l(&h, _srs_tmp_host, _srs_tmp_port); + HELPER_EXPECT_SUCCESS(l.listen()); + + SrsTcpClient c0(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); + HELPER_EXPECT_SUCCESS(c0.connect()); + + srs_usleep(30 * SRS_UTIME_MILLISECONDS); + EXPECT_TRUE(h.fd != NULL); + + MockAsyncReaderThread trd0(h.fd); + HELPER_EXPECT_SUCCESS(trd0.start()); + + MockAsyncReaderThread trd1(h.fd); + HELPER_EXPECT_SUCCESS(trd1.start()); + + // Wait for all threads to run. + srs_usleep(10 * SRS_UTIME_MILLISECONDS); + + // Should fail when close, because there is 2 threads reading fd. + int r0 = st_netfd_close((st_netfd_t)h.fd); + EXPECT_EQ(-1, r0); + EXPECT_EQ(EBUSY, errno); + + // Stop thread1, still fail because thread0 is reading fd. + trd1.stop(); + r0 = st_netfd_close((st_netfd_t)h.fd); + EXPECT_EQ(-1, r0); + EXPECT_EQ(EBUSY, errno); + + // Stop thread0, should success, no threads is reading fd. + trd0.stop(); + r0 = st_netfd_close((st_netfd_t)h.fd); + EXPECT_EQ(0, r0); + + // Set fd to NULL to avoid close fail for EBADF. + h.fd = NULL; +} + From 2c6ad53053bab0121f8d13b17aa5b30a5425e691 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 5 Nov 2021 07:55:16 +0800 Subject: [PATCH 2/6] Update Issue template --- .github/ISSUE_TEMPLATE | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 96836bbd7..fe603104d 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -3,26 +3,30 @@ name: File bug about: File bug to improve SRS title: '' labels: '' -assignees: '' +assignees: 'winlinvip' --- -> 注意:不提供以下信息的Issue会被直接删除(Please follow issue template, or we will delete it) - -> 注意:咨询和讨论请提交到SRS星球(Please ask question at) http://bbs.ossrs.net +> 注意:提问前,请先看FAQ(Please read FAQ before file an issue) #2716 **描述(Description)** > 描述你遇到了什么问题(Please description your issue here) 1. SRS版本(Version): `xxxxxx` + 1. SRS的日志如下(Log): ``` + xxxxxxxxxxxx + ``` + 1. SRS的配置如下(Config): ``` + xxxxxxxxxxxx + ``` **重现(Replay)** From 496a56fa479d22b6b615461bea8aab5f5b2acfe2 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 5 Nov 2021 08:02:20 +0800 Subject: [PATCH 3/6] Update Issue template --- .github/ISSUE_TEMPLATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index fe603104d..7fd21c9b4 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -7,7 +7,7 @@ assignees: 'winlinvip' --- -> 注意:提问前,请先看FAQ(Please read FAQ before file an issue) #2716 +> 注意:提问前,请先看FAQ(Please read FAQ before file an issue) https://github.com/ossrs/srs/issues/2716 **描述(Description)** From 84a16774b28f29ff2fd2856d17af0dd4d6ee038d Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 5 Nov 2021 18:32:06 +0800 Subject: [PATCH 4/6] Fix build fail for CentOS6, without SO_REUSEPORT --- trunk/src/app/srs_app_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 4873bdda5..12db502c3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3567,8 +3567,8 @@ int SrsConfig::get_rtc_server_reuseport() #if !defined(SO_REUSEPORT) if (v > 1) { - srs_warn("REUSEPORT not supported, reset %d to %d", reuseport, DEFAULT); - v = 1 + srs_warn("REUSEPORT not supported, reset to 1"); + v = 1; } #endif From b06661539c2d02b35b45e89df1bc23a43cabd0a3 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Sun, 7 Nov 2021 16:59:33 +0800 Subject: [PATCH 5/6] DVR: Copy req from publish. v4.0.193 (#2714) * DVR: copy req from publish * DVR: copy req from publish --- trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_dvr.cpp | 24 ++++++++++++++++-------- trunk/src/app/srs_app_dvr.hpp | 8 ++++---- trunk/src/app/srs_app_source.cpp | 5 +++-- trunk/src/core/srs_core_version4.hpp | 2 +- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 7428927d0..e73ef4772 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 4.0 Changelog +* v4.0, 2021-11-07, Merge [#2714](https://github.com/ossrs/srs/pull/2714): DVR: copy req from publish. v4.0.193 * v4.0, 2021-11-04, Merge [#2707](https://github.com/ossrs/srs/pull/2707): Refuse edge request when state is stopping. v4.0.192 * v4.0, 2021-11-02, Auto create package by github actions. v4.0.191 * v4.0, 2021-10-30, Merge [#2552](https://github.com/ossrs/srs/pull/2552): Script: Refine CentOS7 service script to restart SRS. v4.0.190 diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index 6a3932ca5..1675e12c6 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -598,8 +598,12 @@ srs_error_t SrsDvrPlan::initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsReque return err; } -srs_error_t SrsDvrPlan::on_publish() +srs_error_t SrsDvrPlan::on_publish(SrsRequest* r) { + // @see https://github.com/ossrs/srs/issues/1613#issuecomment-960623359 + srs_freep(req); + req = r->copy(); + return srs_success; } @@ -687,11 +691,11 @@ SrsDvrSessionPlan::~SrsDvrSessionPlan() { } -srs_error_t SrsDvrSessionPlan::on_publish() +srs_error_t SrsDvrSessionPlan::on_publish(SrsRequest* r) { srs_error_t err = srs_success; - if ((err = SrsDvrPlan::on_publish()) != srs_success) { + if ((err = SrsDvrPlan::on_publish(r)) != srs_success) { return err; } @@ -762,11 +766,11 @@ srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub* h, SrsDvrSegmenter* s, S return srs_success; } -srs_error_t SrsDvrSegmentPlan::on_publish() +srs_error_t SrsDvrSegmentPlan::on_publish(SrsRequest* r) { srs_error_t err = srs_success; - if ((err = SrsDvrPlan::on_publish()) != srs_success) { + if ((err = SrsDvrPlan::on_publish(r)) != srs_success) { return err; } @@ -913,13 +917,14 @@ SrsDvr::~SrsDvr() _srs_config->unsubscribe(this); srs_freep(plan); + srs_freep(req); } srs_error_t SrsDvr::initialize(SrsOriginHub* h, SrsRequest* r) { srs_error_t err = srs_success; - req = r; + req = r->copy(); hub = h; SrsConfDirective* conf = _srs_config->get_dvr_apply(r->vhost); @@ -945,7 +950,7 @@ srs_error_t SrsDvr::initialize(SrsOriginHub* h, SrsRequest* r) return err; } -srs_error_t SrsDvr::on_publish() +srs_error_t SrsDvr::on_publish(SrsRequest* r) { srs_error_t err = srs_success; @@ -954,9 +959,12 @@ srs_error_t SrsDvr::on_publish() return err; } - if ((err = plan->on_publish()) != srs_success) { + if ((err = plan->on_publish(r)) != srs_success) { return srs_error_wrap(err, "publish"); } + + srs_freep(req); + req = r->copy(); return err; } diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp index 18ee450ee..212616b92 100644 --- a/trunk/src/app/srs_app_dvr.hpp +++ b/trunk/src/app/srs_app_dvr.hpp @@ -167,7 +167,7 @@ public: virtual ~SrsDvrPlan(); public: virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r); - virtual srs_error_t on_publish(); + virtual srs_error_t on_publish(SrsRequest* r); virtual void on_unpublish(); virtual srs_error_t on_meta_data(SrsSharedPtrMessage* shared_metadata); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); @@ -187,7 +187,7 @@ public: SrsDvrSessionPlan(); virtual ~SrsDvrSessionPlan(); public: - virtual srs_error_t on_publish(); + virtual srs_error_t on_publish(SrsRequest* r); virtual void on_unpublish(); }; @@ -203,7 +203,7 @@ public: virtual ~SrsDvrSegmentPlan(); public: virtual srs_error_t initialize(SrsOriginHub* h, SrsDvrSegmenter* s, SrsRequest* r); - virtual srs_error_t on_publish(); + virtual srs_error_t on_publish(SrsRequest* r); virtual void on_unpublish(); virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format); virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format); @@ -237,7 +237,7 @@ public: // publish stream event, // when encoder start to publish RTMP stream. // @param fetch_sequence_header whether fetch sequence from source. - virtual srs_error_t on_publish(); + virtual srs_error_t on_publish(SrsRequest* r); // the unpublish event., // when encoder stop(unpublish) to publish RTMP stream. virtual void on_unpublish(); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index d6209b651..d297f0f4a 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1138,7 +1138,8 @@ srs_error_t SrsOriginHub::on_publish() return srs_error_wrap(err, "dash publish"); } - if ((err = dvr->on_publish()) != srs_success) { + // @see https://github.com/ossrs/srs/issues/1613#issuecomment-961657927 + if ((err = dvr->on_publish(req)) != srs_success) { return srs_error_wrap(err, "dvr publish"); } @@ -1401,7 +1402,7 @@ srs_error_t SrsOriginHub::on_reload_vhost_dvr(string vhost) } // start to publish by new plan. - if ((err = dvr->on_publish()) != srs_success) { + if ((err = dvr->on_publish(req)) != srs_success) { return srs_error_wrap(err, "dvr publish failed"); } diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index bf8b54c24..dbdbd02f7 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 192 +#define VERSION_REVISION 193 #endif From 1f4dad024e8e9e02b459c68e8225fc194af120bf Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 7 Nov 2021 17:39:58 +0800 Subject: [PATCH 6/6] Config: Guess config files by FHS. v4.0.194 (#2711) --- trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_config.cpp | 54 ++++++++++++++++++++-------- trunk/src/core/srs_core_version4.hpp | 2 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index e73ef4772..ad41718d9 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 4.0 Changelog +* v4.0, 2021-11-07, Merge [#2711](https://github.com/ossrs/srs/pull/2711): Config: Guess config files by [FHS](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard). v4.0.194 * v4.0, 2021-11-07, Merge [#2714](https://github.com/ossrs/srs/pull/2714): DVR: copy req from publish. v4.0.193 * v4.0, 2021-11-04, Merge [#2707](https://github.com/ossrs/srs/pull/2707): Refuse edge request when state is stopping. v4.0.192 * v4.0, 2021-11-02, Auto create package by github actions. v4.0.191 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 12db502c3..ae8989084 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1956,8 +1956,8 @@ srs_error_t SrsConfig::parse_options(int argc, char** argv) } } - // config - show_help = true; + // Show help if has any argv + show_help = argc > 1; for (int i = 1; i < argc; i++) { if ((err = parse_argv(i, argv)) != srs_success) { return srs_error_wrap(err, "parse argv"); @@ -1980,21 +1980,45 @@ srs_error_t SrsConfig::parse_options(int argc, char** argv) // first hello message. srs_trace(_srs_version); - - if (config_file.empty()) { - return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "no config, read help: %s -h", argv[0]); + + // Try config files as bellow: + // config_file Specified by user, like conf/srs.conf + // try_docker_config Guess by SRS, like conf/docker.conf + // try_fhs_config For FHS, try /etc/srs/srs.conf first, @see https://github.com/ossrs/srs/pull/2711 + if (!srs_path_exists(config_file)) { + vector try_config_files; + if (!config_file.empty()) { + try_config_files.push_back(config_file); + if (srs_string_ends_with(config_file, "docker.conf")) { + try_config_files.push_back(srs_string_replace(config_file, "docker.conf", "srs.conf")); + } + } + try_config_files.push_back(SRS_CONF_DEFAULT_COFNIG_FILE); + if (srs_string_ends_with(SRS_CONF_DEFAULT_COFNIG_FILE, "docker.conf")) { + try_config_files.push_back(srs_string_replace(SRS_CONF_DEFAULT_COFNIG_FILE, "docker.conf", "srs.conf")); + } + try_config_files.push_back("/etc/srs/srs.conf"); + + string exists_config_file; + for (int i = 0; i < (int) try_config_files.size(); i++) { + string try_config_file = try_config_files.at(i); + if (srs_path_exists(try_config_file)) { + exists_config_file = try_config_file; + break; + } + } + + if (exists_config_file.empty()) { + return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "no config file at %s", srs_join_vector_string(try_config_files, ", ").c_str()); + } + + if (config_file != exists_config_file) { + srs_warn("user config %s does not exists, use %s instead", config_file.c_str(), exists_config_file.c_str()); + config_file = exists_config_file; + } } - // For docker, if config is not specified, try srs.conf instead. - string try_config = srs_string_replace(config_file, "docker.conf", "srs.conf"); - if (!srs_path_exists(config_file) && try_config != config_file) { - if (!srs_path_exists(try_config)) { - return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "no config file %s or %s", config_file.c_str(), try_config.c_str()); - } - srs_warn("user config %s does not exists, use %s instead", config_file.c_str(), try_config.c_str()); - config_file = try_config; - } - + // Parse the matched config file. err = parse_file(config_file.c_str()); if (test_conf) { diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index dbdbd02f7..e23b3c149 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 193 +#define VERSION_REVISION 194 #endif