You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rm...@apache.org on 2021/12/11 23:22:57 UTC

[logging-log4cxx] 01/01: LOGCXX-537 avoid deadlock if socket fails

This is an automated email from the ASF dual-hosted git repository.

rmiddleton pushed a commit to branch LOGCXX-537
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit d3ce7942082e918ed2a38ffab9a8523b19d6a60a
Author: Robert Middleton <ro...@rm5248.com>
AuthorDate: Sat Dec 11 18:22:40 2021 -0500

    LOGCXX-537 avoid deadlock if socket fails
---
 src/main/cpp/socketappender.cpp                    |  2 +-
 src/main/cpp/socketappenderskeleton.cpp            |  4 ++
 src/main/cpp/xmlsocketappender.cpp                 |  2 +-
 .../include/log4cxx/net/socketappenderskeleton.h   |  5 +++
 src/test/cpp/net/socketappendertestcase.cpp        | 49 ++++++++++++++++++++++
 5 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/src/main/cpp/socketappender.cpp b/src/main/cpp/socketappender.cpp
index 57f8ade..5f9fb8b 100644
--- a/src/main/cpp/socketappender.cpp
+++ b/src/main/cpp/socketappender.cpp
@@ -124,7 +124,7 @@ void SocketAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers:
 
 		if (getReconnectionDelay() > 0)
 		{
-			fireConnector();
+			fireConnectorInternal();
 		}
 	}
 }
diff --git a/src/main/cpp/socketappenderskeleton.cpp b/src/main/cpp/socketappenderskeleton.cpp
index e3e1375..27f9643 100644
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -159,6 +159,10 @@ void SocketAppenderSkeleton::fireConnector()
 {
 	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
 
+	fireConnectorInternal();
+}
+
+void SocketAppenderSkeleton::fireConnectorInternal(){
 	if ( !thread.joinable() )
 	{
 		LogLog::debug(LOG4CXX_STR("Connector thread not alive: starting monitor."));
diff --git a/src/main/cpp/xmlsocketappender.cpp b/src/main/cpp/xmlsocketappender.cpp
index d5b9942..4c1c70d 100644
--- a/src/main/cpp/xmlsocketappender.cpp
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -122,7 +122,7 @@ void XMLSocketAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpe
 
 			if (getReconnectionDelay() > 0)
 			{
-				fireConnector();
+				fireConnectorInternal();
 			}
 		}
 	}
diff --git a/src/main/include/log4cxx/net/socketappenderskeleton.h b/src/main/include/log4cxx/net/socketappenderskeleton.h
index 88d2a15..8020613 100644
--- a/src/main/include/log4cxx/net/socketappenderskeleton.h
+++ b/src/main/include/log4cxx/net/socketappenderskeleton.h
@@ -178,6 +178,11 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public AppenderSkeleton
 
 		virtual int getDefaultPort() const = 0;
 
+		/**
+		 * Fire the connector.  Caller must have mutex locked.
+		 */
+		void fireConnectorInternal();
+
 	private:
 		void connect(log4cxx::helpers::Pool& p);
 		/**
diff --git a/src/test/cpp/net/socketappendertestcase.cpp b/src/test/cpp/net/socketappendertestcase.cpp
index fe3753c..66d74fc 100644
--- a/src/test/cpp/net/socketappendertestcase.cpp
+++ b/src/test/cpp/net/socketappendertestcase.cpp
@@ -16,6 +16,9 @@
  */
 
 #include <log4cxx/net/socketappender.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/helpers/serversocket.h>
 #include "../appenderskeletontestcase.h"
 #include "apr.h"
 
@@ -34,16 +37,62 @@ class SocketAppenderTestCase : public AppenderSkeletonTestCase
 		//
 		LOGUNIT_TEST(testDefaultThreshold);
 		LOGUNIT_TEST(testSetOptionThreshold);
+		LOGUNIT_TEST(testInvalidHost);
 
 		LOGUNIT_TEST_SUITE_END();
 
 
 	public:
 
+		void setUp()
+		{
+		}
+
+		void tearDown()
+		{
+			BasicConfigurator::resetConfiguration();
+		}
+
 		AppenderSkeleton* createAppenderSkeleton() const
 		{
 			return new log4cxx::net::SocketAppender();
 		}
+
+		void testInvalidHost(){
+			log4cxx::net::SocketAppenderPtr appender = std::make_shared<log4cxx::net::SocketAppender>();
+			log4cxx::PatternLayoutPtr layout = std::make_shared<log4cxx::PatternLayout>("%m%n");
+
+			log4cxx::helpers::ServerSocket serverSocket(4445);
+
+			appender->setLayout(layout);
+			appender->setRemoteHost(LOG4CXX_STR("localhost"));
+			appender->setReconnectionDelay(1);
+			appender->setPort(4445);
+			log4cxx::helpers::Pool pool;
+			appender->activateOptions(pool);
+
+			BasicConfigurator::configure(appender);
+
+			log4cxx::Logger::getRootLogger()->setLevel(log4cxx::Level::getAll());
+
+			std::thread th1( [](){
+				for( int x = 0; x < 3000; x++ ){
+					LOG4CXX_INFO(Logger::getLogger(LOG4CXX_STR("test")), "Some message" );
+				}
+			});
+			std::thread th2( [](){
+				for( int x = 0; x < 3000; x++ ){
+					LOG4CXX_INFO(Logger::getLogger(LOG4CXX_STR("test")), "Some message" );
+				}
+			});
+
+			SocketPtr incomingSocket = serverSocket.accept();
+			incomingSocket->close();
+
+			// If we do not get here, we have deadlocked
+			th1.join();
+			th2.join();
+		}
 };
 
 LOGUNIT_TEST_SUITE_REGISTRATION(SocketAppenderTestCase);