From 0b238b278686f8e0c6609b7c9360d36c3198105c Mon Sep 17 00:00:00 2001
From: Gavin Andresen <gavinandresen@gmail.com>
Date: Tue, 10 Dec 2013 13:19:18 +1000
Subject: [PATCH] Use thread-local storage for LogPrint(category...)

This prevents crashes at shutdown where a global destructor
calls LogPrint(category...) after mapMultiArgs has been
deleted.
---
 src/util.cpp | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/util.cpp b/src/util.cpp
index d975cc9bf..bedf59767 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -242,17 +242,23 @@ int LogPrint(const char* category, const char* pszFormat, ...)
         if (!fDebug)
             return 0;
 
-        const vector<string>& categories = mapMultiArgs["-debug"];
-        bool allCategories = count(categories.begin(), categories.end(), string(""));
-
-        // Only look for categories, if not -debug/-debug=1 was passed,
-        // as that implies every category should be logged.
-        if (!allCategories)
+        // Give each thread quick access to -debug settings.
+        // This helps prevent issues debugging global destructors,
+        // where mapMultiArgs might be deleted before another
+        // global destructor calls LogPrint()
+        static boost::thread_specific_ptr<set<string> > ptrCategory;
+        if (ptrCategory.get() == NULL)
         {
-            // Category was not found (not supplied via -debug=<category>)
-            if (find(categories.begin(), categories.end(), string(category)) == categories.end())
-                return 0;
+            const vector<string>& categories = mapMultiArgs["-debug"];
+            ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
+            // thread_specific_ptr automatically deletes the set when the thread ends.
         }
+        const set<string>& setCategories = *ptrCategory.get();
+
+        // if not debugging everything and not debugging specific category, LogPrint does nothing.
+        if (setCategories.count(string("")) == 0 &&
+            setCategories.count(string(category)) == 0)
+            return 0;
     }
 
     int ret = 0; // Returns total number of characters written