Skip to content

Commit 1b23a88

Browse files
committed
fix(Util): shutdown logging channels in LoggingSubsystem::uninitialize() to prevent AsyncChannel deadlock on exit #5228
1 parent 545940b commit 1b23a88

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

Util/src/LoggingSubsystem.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "Poco/Util/LoggingConfigurator.h"
1717
#include "Poco/Util/Application.h"
1818
#include "Poco/Logger.h"
19+
#include "Poco/LoggingRegistry.h"
1920

2021

2122
using Poco::Logger;
@@ -43,6 +44,8 @@ void LoggingSubsystem::initialize(Application& app)
4344

4445
void LoggingSubsystem::uninitialize()
4546
{
47+
Logger::shutdown();
48+
LoggingRegistry::defaultRegistry().clear();
4649
}
4750

4851

Util/testsuite/src/LoggingConfiguratorTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "Poco/FastLogger.h"
3030
#endif
3131
#include "Poco/NullChannel.h"
32+
#include "Poco/AsyncChannel.h"
33+
#include "Poco/Util/LoggingSubsystem.h"
3234
#include <sstream>
3335

3436

@@ -463,6 +465,39 @@ void LoggingConfiguratorTest::testBadConfiguration3()
463465
}
464466

465467

468+
void LoggingConfiguratorTest::testAsyncChannelShutdown()
469+
{
470+
// Test that LoggingSubsystem::uninitialize() properly shuts down
471+
// AsyncChannel without deadlocking (GitHub issue #5228).
472+
473+
static const std::string config =
474+
"logging.loggers.root.channel = asyncChan\n"
475+
"logging.loggers.root.level = debug\n"
476+
"logging.channels.asyncChan.class = AsyncChannel\n"
477+
"logging.channels.asyncChan.channel = nullChan\n"
478+
"logging.channels.nullChan.class = NullChannel\n";
479+
480+
std::istringstream istr(config);
481+
AutoPtr<PropertyFileConfiguration> pConfig = new PropertyFileConfiguration(istr);
482+
483+
LoggingConfigurator configurator;
484+
configurator.configure(pConfig);
485+
486+
Logger& root = Logger::get("");
487+
assertTrue (root.getLevel() == Message::PRIO_DEBUG);
488+
489+
// Log some messages to ensure the async thread is running
490+
root.information("Test message 1");
491+
root.information("Test message 2");
492+
root.information("Test message 3");
493+
494+
// Simulate what LoggingSubsystem::uninitialize() does.
495+
// This must not deadlock.
496+
Logger::shutdown();
497+
LoggingRegistry::defaultRegistry().clear();
498+
}
499+
500+
466501
void LoggingConfiguratorTest::testBadConfiguration4()
467502
{
468503
// this is mainly testing for memory leaks in case of
@@ -528,6 +563,7 @@ CppUnit::Test* LoggingConfiguratorTest::suite()
528563
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testFastLoggerWithRegistry);
529564
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testFastLoggerOptions);
530565
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testFastLoggerOptionsWarnings);
566+
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testAsyncChannelShutdown);
531567
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testBadConfiguration1);
532568
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testBadConfiguration2);
533569
CppUnit_addTest(pSuite, LoggingConfiguratorTest, testBadConfiguration3);

Util/testsuite/src/LoggingConfiguratorTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class LoggingConfiguratorTest: public CppUnit::TestCase
3434
void testBadConfiguration2();
3535
void testBadConfiguration3();
3636
void testBadConfiguration4();
37+
void testAsyncChannelShutdown();
3738

3839
void setUp();
3940
void tearDown();

0 commit comments

Comments
 (0)