Added ability to configure thread functions through configuration file (#70)

* Added ability to configure thread functions through configuration file

* Updated with notes from review
diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp
index d40afb7..6d62d09 100644
--- a/src/main/cpp/domconfigurator.cpp
+++ b/src/main/cpp/domconfigurator.cpp
@@ -44,6 +44,7 @@
 #include <log4cxx/helpers/charsetdecoder.h>
 #include <log4cxx/net/smtpappender.h>
 #include <log4cxx/helpers/messagebuffer.h>
+#include <log4cxx/helpers/threadutility.h>
 
 #define LOG4CXX 1
 #include <log4cxx/helpers/aprinitializer.h>
@@ -113,6 +114,7 @@
 #define STRINGSTREAM_ATTR "stringstream"
 #define CONFIG_DEBUG_ATTR "configDebug"
 #define INTERNAL_DEBUG_ATTR "debug"
+#define THREAD_CONFIG_ATTR "threadConfiguration"
 
 DOMConfigurator::DOMConfigurator()
 	: props(), repository()
@@ -995,12 +997,12 @@
 
 	LogString debugAttrib = subst(getAttribute(utf8Decoder, element, INTERNAL_DEBUG_ATTR));
 
-	static const LogString NuLL(LOG4CXX_STR("NULL"));
+	static const LogString NULL_STRING(LOG4CXX_STR("NULL"));
 	LogLog::debug(LOG4CXX_STR("debug attribute= \"") + debugAttrib + LOG4CXX_STR("\"."));
 
 	// if the log4j.dtd is not specified in the XML file, then the
 	// "debug" attribute is returned as the empty string.
-	if (!debugAttrib.empty() && debugAttrib != NuLL)
+	if (!debugAttrib.empty() && debugAttrib != NULL_STRING)
 	{
 		LogLog::setInternalDebugging(OptionConverter::toBoolean(debugAttrib, true));
 	}
@@ -1012,7 +1014,7 @@
 
 	LogString confDebug = subst(getAttribute(utf8Decoder, element, CONFIG_DEBUG_ATTR));
 
-	if (!confDebug.empty() && confDebug != NuLL)
+	if (!confDebug.empty() && confDebug != NULL_STRING)
 	{
 		LogLog::warn(LOG4CXX_STR("The \"configDebug\" attribute is deprecated."));
 		LogLog::warn(LOG4CXX_STR("Use the \"internalDebug\" attribute instead."));
@@ -1022,7 +1024,7 @@
 	LogString thresholdStr = subst(getAttribute(utf8Decoder, element, THRESHOLD_ATTR));
 	LogLog::debug(LOG4CXX_STR("Threshold =\"") + thresholdStr + LOG4CXX_STR("\"."));
 
-	if (!thresholdStr.empty() && thresholdStr != NuLL)
+	if (!thresholdStr.empty() && thresholdStr != NULL_STRING)
 	{
 		repository->setThreshold(thresholdStr);
 	}
@@ -1030,11 +1032,24 @@
 	LogString strstrValue = subst(getAttribute(utf8Decoder, element, STRINGSTREAM_ATTR));
 	LogLog::debug(LOG4CXX_STR("Stringstream =\"") + strstrValue + LOG4CXX_STR("\"."));
 
-	if (!strstrValue.empty() && strstrValue != NuLL)
+	if (!strstrValue.empty() && strstrValue != NULL_STRING)
 	{
 		MessageBufferUseStaticStream();
 	}
 
+	LogString threadSignalValue = subst(getAttribute(utf8Decoder, element, THREAD_CONFIG_ATTR));
+	if( !threadSignalValue.empty() && threadSignalValue != NULL_STRING ){
+		if( threadSignalValue == LOG4CXX_STR("NoConfiguration") ){
+			helpers::ThreadUtility::configure( ThreadConfigurationType::NoConfiguration );
+		}else if( threadSignalValue == LOG4CXX_STR("BlockSignalsOnly") ){
+			helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsOnly );
+		}else if( threadSignalValue == LOG4CXX_STR("NameThreadOnly") ){
+			helpers::ThreadUtility::configure( ThreadConfigurationType::NameThreadOnly );
+		}else if( threadSignalValue == LOG4CXX_STR("BlockSignalsAndNameThread") ){
+			helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsAndNameThread );
+		}
+	}
+
 	apr_xml_elem* currentElement;
 
 	for (currentElement = element->first_child;
diff --git a/src/main/cpp/propertyconfigurator.cpp b/src/main/cpp/propertyconfigurator.cpp
index 39c3bea..49b998a 100644
--- a/src/main/cpp/propertyconfigurator.cpp
+++ b/src/main/cpp/propertyconfigurator.cpp
@@ -35,6 +35,7 @@
 #include <log4cxx/helpers/transcoder.h>
 #include <log4cxx/helpers/fileinputstream.h>
 #include <log4cxx/helpers/loader.h>
+#include <log4cxx/helpers/threadutility.h>
 
 #define LOG4CXX 1
 #include <log4cxx/helpers/aprinitializer.h>
@@ -183,6 +184,17 @@
 		MessageBufferUseStaticStream();
 	}
 
+	LogString threadConfigurationValue(properties.getProperty(LOG4CXX_STR("log4j.threadConfiguration")));
+	if( threadConfigurationValue == LOG4CXX_STR("NoConfiguration") ){
+		helpers::ThreadUtility::configure( ThreadConfigurationType::NoConfiguration );
+	}else if( threadConfigurationValue == LOG4CXX_STR("BlockSignalsOnly") ){
+		helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsOnly );
+	}else if( threadConfigurationValue == LOG4CXX_STR("NameThreadOnly") ){
+		helpers::ThreadUtility::configure( ThreadConfigurationType::NameThreadOnly );
+	}else if( threadConfigurationValue == LOG4CXX_STR("BlockSignalsAndNameThread") ){
+		helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsAndNameThread );
+	}
+
 	configureRootLogger(properties, hierarchy);
 	configureLoggerFactory(properties);
 	parseCatsAndRenderers(properties, hierarchy);
diff --git a/src/main/cpp/threadutility.cpp b/src/main/cpp/threadutility.cpp
index 94dd7a7..b57ab66 100644
--- a/src/main/cpp/threadutility.cpp
+++ b/src/main/cpp/threadutility.cpp
@@ -48,7 +48,12 @@
 
 ThreadUtility::ThreadUtility() :
 	m_priv( new priv_data() )
-{}
+{
+	// Block signals by default.
+	configureFuncs( std::bind( &ThreadUtility::preThreadBlockSignals, this ),
+					nullptr,
+					std::bind( &ThreadUtility::postThreadUnblockSignals, this ) );
+}
 
 ThreadUtility::~ThreadUtility(){}
 
diff --git a/src/site/markdown/threading.md b/src/site/markdown/threading.md
index 41faaa5..ff37924 100644
--- a/src/site/markdown/threading.md
+++ b/src/site/markdown/threading.md
@@ -20,13 +20,15 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -->
-# Threading Notes with Log4cxx
+[TOC]
+
+# Threading Notes with Log4cxx {#threading-notes}
 
 Log4cxx is designed to be thread-safe under under normal usage.  This
 means that logging itself is always thread-safe, however there are
 certain circumstances that can cause threading issues with Log4cxx.
 
-## Unexpected Exit
+## Unexpected Exit {#unexpected-exit}
 
 In multithreaded applications, it is possible to call `exit()` from any
 thread in the application.  When this happens, other threads in the
@@ -38,14 +40,17 @@
 
 See [LOGCXX-322][3] for more information.
 
-## Signal Handling with Log4cxx
+## Signal Handling with Log4cxx {#signal-handling}
 
 Under certain configurations, Log4cxx may create new threads in order to do
 tasks(e.g. network comms, other async operations).  On Linux/POSIX systems,
 this can lead to undesirable signal delivery, as signals can be delivered to
 any thread in the process.  This can be most clearly seen if your application
 uses the [sigwait(3)][4] system call, as the thread that calls sigwait may
-not be the thread that actually gets the signal.
+not be the thread that actually gets the signal.  By default, Log4cxx
+configures itself to block all signals to new threads that it creates on
+Linux/POSIX systems.  See the [section on configuring](@ref configuring)
+for more details on how to configure.
 
 There are three main ways to handle signals coming to your process.   All
 of these ways of handling signals are supported by Log4cxx in order to
@@ -79,14 +84,29 @@
 [ThreadUtility::configure](@ref log4cxx.helpers.ThreadUtility.configure)
 method with several pre-defined configurations.
 In the event that you need special signal handling, you can implement your own
-functions, and use the ThreadUtility::configureFuncs method in order to
+functions, and use the [ThreadUtility::configureFuncs](@ref log4cxx.helpers.ThreadUtility.configureFuncs) method in order to
 customize exactly what happens.
 
-**NOTE:** It is very important that if you use the `ThreadUtility::preThreadBlockSignals`
-method, it must be paired with the equivalent `ThreadUtility::postThreadUnblockSignals`
-call, as there is an internal mutex that is locked and unlocked in order to ensure that
-only one thread can be started at a time.  Failure to do this may lead to deadlock.
-The ThreadUtility::configure method handles this automatically.
+### Configuring Thread {#configuring}
+
+To tell Log4cxx what to do by default when starting a new thread, the enum
+[ThreadConfigurationType](@ref log4cxx.helpers.ThreadConfigurationType) may be
+used to configure the library appropriately.  By default, all signals on POSIX
+systems will be blocked to ensure that other threads do not get signals.
+
+To change this default, a simple change to your configuration files may be done.
+
+Example to disable the automatic signal blocking with XML configuration:
+```
+<log4j:configuration threadConfiguration="NoConfiguration">
+...
+</log4j:configuration>
+```
+
+Example to disable the automatic signal blocking with properties configuration:
+```
+log4j.threadConfiguration=NoConfiguration
+```
 
 [1]: https://man7.org/linux/man-pages/man2/signalfd.2.html
 [2]: https://doc.qt.io/qt-5/unix-signals.html