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/21 02:32:44 UTC

[logging-log4cxx] branch master updated: LOGCXX-537 avoid deadlock if socket fails (#82)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new b213a62  LOGCXX-537 avoid deadlock if socket fails (#82)
b213a62 is described below

commit b213a62361ed8b797d3a7de26ccc0c1c1e9774a5
Author: Robert Middleton <rm...@users.noreply.github.com>
AuthorDate: Mon Dec 20 21:32:39 2021 -0500

    LOGCXX-537 avoid deadlock if socket fails (#82)
    
    * LOGCXX-537 Changed to recursive mutex, and ensure that we don't wait too long for connections
    
    * added and then removed test that seems to deadlock sometimes
---
 src/main/cpp/appenderskeleton.cpp           | 14 ++++-----
 src/main/cpp/asyncappender.cpp              |  2 +-
 src/main/cpp/fileappender.cpp               | 26 +++++++--------
 src/main/cpp/rollingfileappender.cpp        |  4 +--
 src/main/cpp/socketappender.cpp             |  2 +-
 src/main/cpp/socketappenderskeleton.cpp     | 24 ++++++++------
 src/main/cpp/sockethubappender.cpp          |  6 ++--
 src/main/cpp/telnetappender.cpp             | 10 +++---
 src/main/cpp/writerappender.cpp             |  4 +--
 src/main/cpp/xmlsocketappender.cpp          |  2 +-
 src/main/include/log4cxx/appenderskeleton.h |  2 +-
 src/test/cpp/net/socketappendertestcase.cpp | 49 +++++++++++++++++++++++++++++
 12 files changed, 99 insertions(+), 46 deletions(-)

diff --git a/src/main/cpp/appenderskeleton.cpp b/src/main/cpp/appenderskeleton.cpp
index 6df2551..0705c6e 100644
--- a/src/main/cpp/appenderskeleton.cpp
+++ b/src/main/cpp/appenderskeleton.cpp
@@ -39,7 +39,7 @@ AppenderSkeleton::AppenderSkeleton()
 		tailFilter(),
 		pool()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	closed = false;
 }
 
@@ -52,7 +52,7 @@ AppenderSkeleton::AppenderSkeleton(const LayoutPtr& layout1)
 	  tailFilter(),
 	  pool()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	closed = false;
 }
 
@@ -70,7 +70,7 @@ void AppenderSkeleton::finalize()
 
 void AppenderSkeleton::addFilter(const spi::FilterPtr& newFilter)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	if (headFilter == 0)
 	{
@@ -85,7 +85,7 @@ void AppenderSkeleton::addFilter(const spi::FilterPtr& newFilter)
 
 void AppenderSkeleton::clearFilters()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	headFilter = tailFilter = 0;
 }
 
@@ -96,7 +96,7 @@ bool AppenderSkeleton::isAsSevereAsThreshold(const LevelPtr& level) const
 
 void AppenderSkeleton::doAppend(const spi::LoggingEventPtr& event, Pool& pool1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	doAppendImpl(event, pool1);
 }
@@ -139,7 +139,7 @@ void AppenderSkeleton::doAppendImpl(const spi::LoggingEventPtr& event, Pool& poo
 
 void AppenderSkeleton::setErrorHandler(const spi::ErrorHandlerPtr errorHandler1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	if (errorHandler1 == 0)
 	{
@@ -155,7 +155,7 @@ void AppenderSkeleton::setErrorHandler(const spi::ErrorHandlerPtr errorHandler1)
 
 void AppenderSkeleton::setThreshold(const LevelPtr& threshold1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	this->threshold = threshold1;
 }
 
diff --git a/src/main/cpp/asyncappender.cpp b/src/main/cpp/asyncappender.cpp
index d357ff0..876c257 100644
--- a/src/main/cpp/asyncappender.cpp
+++ b/src/main/cpp/asyncappender.cpp
@@ -92,7 +92,7 @@ void AsyncAppender::setOption(const LogString& option,
 
 void AsyncAppender::doAppend(const spi::LoggingEventPtr& event, Pool& pool1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	doAppendImpl(event, pool1);
 }
diff --git a/src/main/cpp/fileappender.cpp b/src/main/cpp/fileappender.cpp
index cca1abb..e04d730 100644
--- a/src/main/cpp/fileappender.cpp
+++ b/src/main/cpp/fileappender.cpp
@@ -36,7 +36,7 @@ IMPLEMENT_LOG4CXX_OBJECT(FileAppender)
 
 FileAppender::FileAppender()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	fileAppend = true;
 	bufferedIO = false;
 	bufferSize = 8 * 1024;
@@ -47,7 +47,7 @@ FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1,
 	: WriterAppender(layout1)
 {
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		fileAppend = append1;
 		fileName = fileName1;
 		bufferedIO = bufferedIO1;
@@ -62,7 +62,7 @@ FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1,
 	: WriterAppender(layout1)
 {
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		fileAppend = append1;
 		fileName = fileName1;
 		bufferedIO = false;
@@ -76,7 +76,7 @@ FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1)
 	: WriterAppender(layout1)
 {
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		fileAppend = true;
 		fileName = fileName1;
 		bufferedIO = false;
@@ -93,13 +93,13 @@ FileAppender::~FileAppender()
 
 void FileAppender::setAppend(bool fileAppend1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	this->fileAppend = fileAppend1;
 }
 
 void FileAppender::setFile(const LogString& file)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	setFileInternal(file);
 }
 
@@ -110,7 +110,7 @@ void FileAppender::setFileInternal(const LogString& file)
 
 void FileAppender::setBufferedIO(bool bufferedIO1)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	this->bufferedIO = bufferedIO1;
 
 	if (bufferedIO1)
@@ -125,27 +125,27 @@ void FileAppender::setOption(const LogString& option,
 	if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILE"), LOG4CXX_STR("file"))
 		|| StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILENAME"), LOG4CXX_STR("filename")))
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		fileName = stripDuplicateBackslashes(value);
 	}
 	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("APPEND"), LOG4CXX_STR("append")))
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		fileAppend = OptionConverter::toBoolean(value, true);
 	}
 	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFEREDIO"), LOG4CXX_STR("bufferedio")))
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		bufferedIO = OptionConverter::toBoolean(value, true);
 	}
 	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("IMMEDIATEFLUSH"), LOG4CXX_STR("immediateflush")))
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		bufferedIO = !OptionConverter::toBoolean(value, false);
 	}
 	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		bufferSize = OptionConverter::toFileSize(value, 8 * 1024);
 	}
 	else
@@ -156,7 +156,7 @@ void FileAppender::setOption(const LogString& option,
 
 void FileAppender::activateOptions(Pool& p)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	activateOptionsInternal(p);
 }
 
diff --git a/src/main/cpp/rollingfileappender.cpp b/src/main/cpp/rollingfileappender.cpp
index 7d236f4..48aad5f 100644
--- a/src/main/cpp/rollingfileappender.cpp
+++ b/src/main/cpp/rollingfileappender.cpp
@@ -94,7 +94,7 @@ void RollingFileAppenderSkeleton::activateOptions(Pool& p)
 	}
 
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 		triggeringPolicy->activateOptions(p);
 		rollingPolicy->activateOptions(p);
 
@@ -183,7 +183,7 @@ void RollingFileAppenderSkeleton::releaseFileLock(apr_file_t* lock_file)
  */
 bool RollingFileAppenderSkeleton::rollover(Pool& p)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	return rolloverInternal(p);
 }
 
diff --git a/src/main/cpp/socketappender.cpp b/src/main/cpp/socketappender.cpp
index 57f8ade..4809a35 100644
--- a/src/main/cpp/socketappender.cpp
+++ b/src/main/cpp/socketappender.cpp
@@ -78,7 +78,7 @@ int SocketAppender::getDefaultPort() const
 
 void SocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	SocketOutputStreamPtr sock = SocketOutputStreamPtr(new SocketOutputStream(socket));
 	oos = ObjectOutputStreamPtr(new ObjectOutputStream(sock, p));
diff --git a/src/main/cpp/socketappenderskeleton.cpp b/src/main/cpp/socketappenderskeleton.cpp
index e3e1375..b0b73b4 100644
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -78,7 +78,7 @@ void SocketAppenderSkeleton::activateOptions(Pool& p)
 
 void SocketAppenderSkeleton::close()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	if (closed)
 	{
@@ -157,7 +157,14 @@ void SocketAppenderSkeleton::setOption(const LogString& option, const LogString&
 
 void SocketAppenderSkeleton::fireConnector()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
+
+	if( thread.joinable() ){
+		// This should only get called if the thread has already exited.
+		// We could have a potential bug if fireConnector is called while
+		// the thread is waiting for a connection
+		thread.join();
+	}
 
 	if ( !thread.joinable() )
 	{
@@ -176,12 +183,6 @@ void SocketAppenderSkeleton::monitor()
 	{
 		try
 		{
-			std::this_thread::sleep_for( std::chrono::milliseconds( reconnectionDelay ) );
-
-			std::unique_lock<std::mutex> lock( interrupt_mutex );
-			interrupt.wait_for( lock, std::chrono::milliseconds( reconnectionDelay ),
-				std::bind(&SocketAppenderSkeleton::is_closed, this) );
-
 			if (!closed)
 			{
 				LogLog::debug(LogString(LOG4CXX_STR("Attempting connection to "))
@@ -190,9 +191,8 @@ void SocketAppenderSkeleton::monitor()
 				Pool p;
 				setSocket(socket, p);
 				LogLog::debug(LOG4CXX_STR("Connection established. Exiting connector thread."));
+				return;
 			}
-
-			return;
 		}
 		catch (InterruptedException&)
 		{
@@ -216,6 +216,10 @@ void SocketAppenderSkeleton::monitor()
 				+ exmsg);
 		}
 
+		std::unique_lock<std::mutex> lock( interrupt_mutex );
+		interrupt.wait_for( lock, std::chrono::milliseconds( reconnectionDelay ),
+			std::bind(&SocketAppenderSkeleton::is_closed, this) );
+
 		isClosed = closed;
 	}
 
diff --git a/src/main/cpp/sockethubappender.cpp b/src/main/cpp/sockethubappender.cpp
index 7d83a23..6a8a0aa 100644
--- a/src/main/cpp/sockethubappender.cpp
+++ b/src/main/cpp/sockethubappender.cpp
@@ -84,7 +84,7 @@ void SocketHubAppender::setOption(const LogString& option,
 void SocketHubAppender::close()
 {
 	{
-		std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 
 		if (closed)
 		{
@@ -104,7 +104,7 @@ void SocketHubAppender::close()
 		thread.join();
 	}
 
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	// close all of the connections
 	LogLog::debug(LOG4CXX_STR("closing client connections"));
 
@@ -234,7 +234,7 @@ void SocketHubAppender::monitor()
 					+ LOG4CXX_STR(")"));
 
 				// add it to the oosList.
-				std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+				std::lock_guard<std::recursive_mutex> lock(mutex);
 				OutputStreamPtr os(new SocketOutputStream(socket));
 				Pool p;
 				ObjectOutputStreamPtr oos(new ObjectOutputStream(os, p));
diff --git a/src/main/cpp/telnetappender.cpp b/src/main/cpp/telnetappender.cpp
index 9087242..2a880ee 100644
--- a/src/main/cpp/telnetappender.cpp
+++ b/src/main/cpp/telnetappender.cpp
@@ -84,13 +84,13 @@ void TelnetAppender::setOption(const LogString& option,
 
 LogString TelnetAppender::getEncoding() const
 {
-	log4cxx::shared_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	return encoding;
 }
 
 void TelnetAppender::setEncoding(const LogString& value)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	encoder = CharsetEncoder::getEncoder(value);
 	encoding = value;
 }
@@ -98,7 +98,7 @@ void TelnetAppender::setEncoding(const LogString& value)
 
 void TelnetAppender::close()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	if (closed)
 	{
@@ -195,7 +195,7 @@ void TelnetAppender::append(const spi::LoggingEventPtr& event, Pool& p)
 		LogString::const_iterator msgIter(msg.begin());
 		ByteBuffer buf(bytes, bytesSize);
 
-		log4cxx::shared_lock<log4cxx::shared_mutex> lock(mutex);
+		std::lock_guard<std::recursive_mutex> lock(mutex);
 
 		while (msgIter != msg.end())
 		{
@@ -251,7 +251,7 @@ void TelnetAppender::acceptConnections()
 				//
 				//   find unoccupied connection
 				//
-				std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+				std::lock_guard<std::recursive_mutex> lock(mutex);
 
 				for (ConnectionList::iterator iter = connections.begin();
 					iter != connections.end();
diff --git a/src/main/cpp/writerappender.cpp b/src/main/cpp/writerappender.cpp
index 57996f5..1d4303d 100644
--- a/src/main/cpp/writerappender.cpp
+++ b/src/main/cpp/writerappender.cpp
@@ -151,7 +151,7 @@ bool WriterAppender::checkEntryConditions() const
    */
 void WriterAppender::close()
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 
 	if (closed)
 	{
@@ -278,7 +278,7 @@ void WriterAppender::writeHeader(Pool& p)
 
 void WriterAppender::setWriter(const WriterPtr& newWriter)
 {
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	setWriterInternal(newWriter);
 }
 
diff --git a/src/main/cpp/xmlsocketappender.cpp b/src/main/cpp/xmlsocketappender.cpp
index d5b9942..36fdfce 100644
--- a/src/main/cpp/xmlsocketappender.cpp
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -84,7 +84,7 @@ void XMLSocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p)
 {
 	OutputStreamPtr os(new SocketOutputStream(socket));
 	CharsetEncoderPtr charset(CharsetEncoder::getUTF8Encoder());
-	std::unique_lock<log4cxx::shared_mutex> lock(mutex);
+	std::lock_guard<std::recursive_mutex> lock(mutex);
 	writer = OutputStreamWriterPtr(new OutputStreamWriter(os, charset));
 }
 
diff --git a/src/main/include/log4cxx/appenderskeleton.h b/src/main/include/log4cxx/appenderskeleton.h
index b89b09e..3b7af8b 100644
--- a/src/main/include/log4cxx/appenderskeleton.h
+++ b/src/main/include/log4cxx/appenderskeleton.h
@@ -74,7 +74,7 @@ class LOG4CXX_EXPORT AppenderSkeleton :
 		bool closed;
 
 		log4cxx::helpers::Pool pool;
-		mutable log4cxx::shared_mutex mutex;
+		mutable std::recursive_mutex mutex;
 
 		/**
 		Subclasses of <code>AppenderSkeleton</code> should implement this
diff --git a/src/test/cpp/net/socketappendertestcase.cpp b/src/test/cpp/net/socketappendertestcase.cpp
index fe3753c..fe5c8e0 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>(LOG4CXX_STR("%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);