From dad31724ed90a24f07c40df12e1fc0b59a8c6091 Mon Sep 17 00:00:00 2001 From: Paul-Louis Ageneau Date: Thu, 27 Feb 2025 11:00:10 +0100 Subject: [PATCH] Fix possible crash on program exit with libnice --- src/impl/icetransport.cpp | 38 ++++++++++++++++++++++++-------------- src/impl/icetransport.hpp | 13 +++++++++++-- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/impl/icetransport.cpp b/src/impl/icetransport.cpp index e2a0b1e70..f28422c47 100644 --- a/src/impl/icetransport.cpp +++ b/src/impl/icetransport.cpp @@ -392,8 +392,22 @@ void IceTransport::LogCallback(juice_log_level_t level, const char *message) { #else // USE_NICE == 1 -unique_ptr IceTransport::MainLoop(nullptr, nullptr); -std::thread IceTransport::MainLoopThread; +IceTransport::MainLoopWrapper *IceTransport::MainLoop = nullptr; + +IceTransport::MainLoopWrapper::MainLoopWrapper() + : mMainLoop(g_main_loop_new(nullptr, FALSE), g_main_loop_unref) { + if (!mMainLoop) + throw std::runtime_error("Failed to create the glib main loop"); + + mThread = std::thread(g_main_loop_run, mMainLoop.get()); +} + +IceTransport::MainLoopWrapper::~MainLoopWrapper() { + g_main_loop_quit(mMainLoop.get()); + mThread.join(); +} + +GMainLoop *IceTransport::MainLoopWrapper::get() const { return mMainLoop.get(); } void IceTransport::Init() { g_log_set_handler("libnice", G_LOG_LEVEL_MASK, LogCallback, nullptr); @@ -402,17 +416,12 @@ void IceTransport::Init() { nice_debug_enable(false); // do not output STUN debug messages } - MainLoop = decltype(MainLoop)(g_main_loop_new(nullptr, FALSE), g_main_loop_unref); - if (!MainLoop) - throw std::runtime_error("Failed to create the main loop"); - - MainLoopThread = std::thread(g_main_loop_run, MainLoop.get()); + MainLoop = new MainLoopWrapper; } void IceTransport::Cleanup() { - g_main_loop_quit(MainLoop.get()); - MainLoopThread.join(); - MainLoop.reset(); + delete MainLoop; + MainLoop = nullptr; } static void closeNiceAgentCallback(GObject *niceAgent, GAsyncResult *, gpointer) { @@ -447,7 +456,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi // Create agent mNiceAgent = decltype(mNiceAgent)( nice_agent_new_full( - g_main_loop_get_context(MainLoop.get()), + g_main_loop_get_context(MainLoop->get()), NICE_COMPATIBILITY_RFC5245, // RFC 5245 was obsoleted by RFC 8445 but this should be OK flags), closeNiceAgent); @@ -580,12 +589,13 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi nice_agent_set_port_range(mNiceAgent.get(), mStreamId, 1, config.portRangeBegin, config.portRangeEnd); - nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(MainLoop.get()), + nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(MainLoop->get()), RecvCallback, this); } void IceTransport::setIceAttributes([[maybe_unused]] string uFrag, [[maybe_unused]] string pwd) { - PLOG_WARNING << "Setting custom ICE attributes is not supported with libnice, please use libjuice"; + PLOG_WARNING + << "Setting custom ICE attributes is not supported with libnice, please use libjuice"; } void IceTransport::addIceServer(IceServer server) { @@ -647,7 +657,7 @@ void IceTransport::addIceServer(IceServer server) { IceTransport::~IceTransport() { PLOG_DEBUG << "Destroying ICE transport"; - nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(MainLoop.get()), + nice_agent_attach_recv(mNiceAgent.get(), mStreamId, 1, g_main_loop_get_context(MainLoop->get()), NULL, NULL); nice_agent_remove_stream(mNiceAgent.get(), mStreamId); mNiceAgent.reset(); diff --git a/src/impl/icetransport.hpp b/src/impl/icetransport.hpp index 69d0c99af..5d74aabab 100644 --- a/src/impl/icetransport.hpp +++ b/src/impl/icetransport.hpp @@ -90,8 +90,17 @@ class IceTransport : public Transport { static void RecvCallback(juice_agent_t *agent, const char *data, size_t size, void *user_ptr); static void LogCallback(juice_log_level_t level, const char *message); #else - static unique_ptr MainLoop; - static std::thread MainLoopThread; + class MainLoopWrapper { + public: + MainLoopWrapper(); + ~MainLoopWrapper(); + GMainLoop *get() const; + + private: + unique_ptr mMainLoop; + std::thread mThread; + }; + static MainLoopWrapper *MainLoop; unique_ptr mNiceAgent; uint32_t mStreamId = 0;