From 21169636a72174f1d757eb3f0d5d37e4f587a33e Mon Sep 17 00:00:00 2001 From: Mikolaj Malecki Date: Mon, 13 Jan 2025 15:57:48 +0100 Subject: [PATCH] [DRAFT] Add test and some future API changes for startup/cleanup #3100 --- srtcore/api.cpp | 37 +++++++++++++++++++++++-------------- srtcore/api.h | 15 +++++++++++++-- test/test_common.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/srtcore/api.cpp b/srtcore/api.cpp index bb5dd64fe..c9fb4f918 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -198,13 +198,8 @@ srt::CUDTUnited::CUDTUnited() srt::CUDTUnited::~CUDTUnited() { - // Call it if it wasn't called already. - // This will happen at the end of main() of the application, - // when the user didn't call srt_cleanup(). - if (m_bGCStatus) - { - cleanup(); - } + // force cleanup, even if the instance count is > 1 + cleanup(true); releaseMutex(m_GlobControlLock); releaseMutex(m_IDLock); @@ -233,13 +228,19 @@ string srt::CUDTUnited::CONID(SRTSOCKET sock) return os.str(); } -int srt::CUDTUnited::startup() +int srt::CUDTUnited::startup(bool implicit) { ScopedLock gcinit(m_InitLock); - if (m_bGCStatus) + + if (implicit && m_iInstanceCount > 0) + // [reinstate in 1.6.0] return m_iInstanceCount; return 1; if (m_iInstanceCount++ > 0) + return m_iInstanceCount; + + if (m_bGCStatus) + // [reinstate in 1.6.0] return m_iInstanceCount; return 1; // Global initialization code @@ -268,7 +269,7 @@ int srt::CUDTUnited::startup() return 0; } -int srt::CUDTUnited::cleanup() +int srt::CUDTUnited::cleanup(bool force) { // IMPORTANT!!! // In this function there must be NO LOGGING AT ALL. This function may @@ -280,9 +281,14 @@ int srt::CUDTUnited::cleanup() // executing this procedure. ScopedLock gcinit(m_InitLock); - if (--m_iInstanceCount > 0) - return 0; + if (!force) + { + if (m_iInstanceCount == 0 || --m_iInstanceCount > 0) + // [reinstate in 1.6.0] return m_iInstanceCount; + return 0; + } + // Cleanup done before already if (!m_bGCStatus) return 0; @@ -298,6 +304,8 @@ int srt::CUDTUnited::cleanup() CSync::notify_one_relaxed(m_GCStopCond); m_GCThread.join(); + if (force) + m_iInstanceCount = 0; m_bGCStatus = false; // Global destruction code @@ -305,6 +313,7 @@ int srt::CUDTUnited::cleanup() WSACleanup(); #endif + // Cleanup done at all. return 0; } @@ -3469,7 +3478,7 @@ int srt::CUDT::cleanup() SRTSOCKET srt::CUDT::socket() { - uglobal().startup(); + uglobal().startup(true); try { @@ -3519,7 +3528,7 @@ srt::CUDTGroup& srt::CUDT::newGroup(const int type) SRTSOCKET srt::CUDT::createGroup(SRT_GROUP_TYPE gt) { // Doing the same lazy-startup as with srt_create_socket() - uglobal().startup(); + uglobal().startup(true); try { diff --git a/srtcore/api.h b/srtcore/api.h index 48e7827f8..1eefcb2bc 100644 --- a/srtcore/api.h +++ b/srtcore/api.h @@ -257,12 +257,14 @@ class CUDTUnited static std::string CONID(SRTSOCKET sock); /// initialize the UDT library. + /// @param [in] implicit should be set to true for internal implicit startup() calls. /// @return 0 if success, otherwise -1 is returned. - int startup(); + int startup(bool implicit = false); /// release the UDT library. + /// @param [in] force cleanup regardless of the instance count. /// @return 0 if success, otherwise -1 is returned. - int cleanup(); + int cleanup(bool force = false); /// Create a new UDT socket. /// @param [out] pps Variable (optional) to which the new socket will be written, if succeeded @@ -542,6 +544,15 @@ class CUDTUnited int m_iInstanceCount; // number of startup() called by application SRT_ATTR_GUARDED_BY(m_InitLock) bool m_bGCStatus; // if the GC thread is working (true) +public: + + std::pair getInstanceStatus() + { + sync::ScopedLock lk(m_InitLock); + return std::make_pair(m_iInstanceCount, m_bGCStatus); + } + +private: SRT_ATTR_GUARDED_BY(m_InitLock) sync::CThread m_GCThread; diff --git a/test/test_common.cpp b/test/test_common.cpp index 1a8cca061..a9ed421a3 100644 --- a/test/test_common.cpp +++ b/test/test_common.cpp @@ -5,9 +5,39 @@ #include "test_env.h" #include "utilities.h" #include "common.h" +#include "api.h" using namespace srt; +TEST(General, Startup) +{ + // Should return 0 if it was run for the first time + // and actually performed the initialization. + EXPECT_EQ(srt_startup(), 0); + + EXPECT_EQ(srt::CUDT::uglobal().getInstanceStatus(), std::make_pair(1, true)); + + // Every next one should return the number of nested instances + EXPECT_EQ(srt_startup(), 2); + + // Now let's pair the first instance, should NOT execute + // [reinstate in 1.6.0] EXPECT_EQ(srt_cleanup(), 1); + srt_cleanup(); + + EXPECT_EQ(srt_cleanup(), 0); + + // Second cleanup, should report successful cleanup even if nothing is done. + EXPECT_EQ(srt_cleanup(), 0); + + // Now let's start with getting the number of instances + // from implicitly created ones. + SRTSOCKET sock = srt_create_socket(); + + EXPECT_EQ(srt::CUDT::uglobal().getInstanceStatus(), std::make_pair(1, true)); + + EXPECT_EQ(srt_close(sock), 0); +} + void test_cipaddress_pton(const char* peer_ip, int family, const uint32_t (&ip)[4]) { const int port = 4200;