changeset 3226:2876d790d9bb draft

Merge branch 'master' of git://github.com/fanquake/bitcoin
author Gavin Andresen <gavinandresen@gmail.com>
date Tue, 17 Jul 2012 20:33:03 -0400
parents 13158535565e (diff) 935fc8de4a94 (current diff)
children 981b2d3581ad
files
diffstat 18 files changed, 211 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -1569,11 +1569,17 @@
 
 void ThreadTopUpKeyPool(void* parg)
 {
+    // Make this thread recognisable as the key-topping-up thread
+    RenameThread("bitcoin-key-top");
+
     pwalletMain->TopUpKeyPool();
 }
 
 void ThreadCleanWalletPassphrase(void* parg)
 {
+    // Make this thread recognisable as the wallet relocking thread
+    RenameThread("bitcoin-lock-wa");
+
     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
 
     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
@@ -2479,6 +2485,10 @@
 void ThreadRPCServer(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
+
+    // Make this thread recognisable as the RPC listener
+    RenameThread("bitcoin-rpclist");
+
     try
     {
         vnThreadsRunning[THREAD_RPCLISTENER]++;
@@ -2762,6 +2772,10 @@
 void ThreadRPCServer3(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer3(parg));
+
+    // Make this thread recognisable as the RPC handler
+    RenameThread("bitcoin-rpchand");
+
     {
         LOCK(cs_THREAD_RPCHANDLER);
         vnThreadsRunning[THREAD_RPCHANDLER]++;
@@ -2943,8 +2957,9 @@
     {
         // reinterpret string as unquoted json value
         Value value2;
-        if (!read_string(value.get_str(), value2))
-            throw runtime_error("type mismatch");
+        string strJSON = value.get_str();
+        if (!read_string(strJSON, value2))
+            throw runtime_error(string("Error parsing JSON:")+strJSON);
         value = value2.get_value<T>();
     }
     else
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -53,6 +53,10 @@
 {
     static CCriticalSection cs_Shutdown;
     static bool fTaken;
+
+    // Make this thread recognisable as the shutdown thread
+    RenameThread("bitcoin-shutoff");
+
     bool fFirstThread = false;
     {
         TRY_LOCK(cs_Shutdown, lockShutdown);
--- a/src/irc.cpp
+++ b/src/irc.cpp
@@ -189,6 +189,10 @@
 void ThreadIRCSeed(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg));
+
+    // Make this thread recognisable as the IRC seeding thread
+    RenameThread("bitcoin-ircseed");
+
     try
     {
         ThreadIRCSeed2(parg);
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3594,6 +3594,9 @@
     printf("BitcoinMiner started\n");
     SetThreadPriority(THREAD_PRIORITY_LOWEST);
 
+    // Make this thread recognisable as the mining thread
+    RenameThread("bitcoin-miner");
+
     // Each thread has its own key and counter
     CReserveKey reservekey(pwallet);
     unsigned int nExtraNonce = 0;
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -66,13 +66,14 @@
     # Make some important things such as the global offset table read only as soon as
     # the dynamic linker is finished building it. This will prevent overwriting of addresses
     # which would later be jumped to.
-    HARDENING+=-Wl,-z,relro -Wl,-z,now
+    LDHARDENING+=-Wl,-z,relro -Wl,-z,now
 
     # Build position independent code to take advantage of Address Space Layout Randomization
     # offered by some kernels.
     # see doc/build-unix.txt for more information.
     ifdef PIE
-        HARDENING+=-fPIE -pie
+        HARDENING+=-fPIE
+        LDHARDENING+=-pie
     endif
 
     # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in
@@ -88,6 +89,10 @@
 xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
     $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
 
+# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
+# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
+xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
+
 OBJS= \
     obj/version.o \
     obj/checkpoints.o \
@@ -133,7 +138,7 @@
 	  rm -f $(@:%.o=%.d)
 
 bitcoind: $(OBJS:obj/%=obj/%)
-	$(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
+	$(CXX) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS)
 
 TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
 
@@ -145,7 +150,7 @@
 	  rm -f $(@:%.o=%.d)
 
 test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
-	$(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
+	$(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(xLDFLAGS) $(LIBS)
 
 clean:
 	-rm -f bitcoind test_bitcoin
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -407,6 +407,9 @@
 
 void ThreadGetMyExternalIP(void* parg)
 {
+    // Make this thread recognisable as the external IP detection thread
+    RenameThread("bitcoin-ext-ip");
+
     CNetAddr addrLocalHost;
     if (GetMyExternalIP(addrLocalHost))
     {
@@ -636,6 +639,10 @@
 void ThreadSocketHandler(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
+
+    // Make this thread recognisable as the networking thread
+    RenameThread("bitcoin-net");
+
     try
     {
         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
@@ -988,6 +995,10 @@
 void ThreadMapPort(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
+
+    // Make this thread recognisable as the UPnP thread
+    RenameThread("bitcoin-UPnP");
+
     try
     {
         vnThreadsRunning[THREAD_UPNP]++;
@@ -1146,6 +1157,10 @@
 void ThreadDNSAddressSeed(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
+
+    // Make this thread recognisable as the DNS seeding thread
+    RenameThread("bitcoin-dnsseed");
+
     try
     {
         vnThreadsRunning[THREAD_DNSSEED]++;
@@ -1315,6 +1330,10 @@
 void ThreadDumpAddress(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadDumpAddress(parg));
+
+    // Make this thread recognisable as the address dumping thread
+    RenameThread("bitcoin-adrdump");
+
     try
     {
         ThreadDumpAddress2(parg);
@@ -1328,6 +1347,10 @@
 void ThreadOpenConnections(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
+
+    // Make this thread recognisable as the connection opening thread
+    RenameThread("bitcoin-opencon");
+
     try
     {
         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
@@ -1481,6 +1504,10 @@
 void ThreadOpenAddedConnections(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
+
+    // Make this thread recognisable as the connection opening thread
+    RenameThread("bitcoin-opencon");
+
     try
     {
         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
@@ -1610,6 +1637,10 @@
 void ThreadMessageHandler(void* parg)
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
+
+    // Make this thread recognisable as the message handling thread
+    RenameThread("bitcoin-msghand");
+
     try
     {
         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
@@ -1852,6 +1883,9 @@
 
 void StartNode(void* parg)
 {
+    // Make this thread recognisable as the startup thread
+    RenameThread("bitcoin-start");
+
     if (semOutbound == NULL) {
         // initialize semaphore
         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -126,13 +126,21 @@
             const char *strURI = argv[i];
             try {
                 boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
-                if(mq.try_send(strURI, strlen(strURI), 0))
+                if (mq.try_send(strURI, strlen(strURI), 0))
+                    // if URI could be sent to the message queue exit here
                     exit(0);
                 else
+                    // if URI could not be sent to the message queue do a normal Bitcoin-Qt startup
                     break;
             }
             catch (boost::interprocess::interprocess_exception &ex) {
-                break;
+                // don't log the "file not found" exception, because that's normal for
+                // the first start of the first instance
+                if (ex.get_error_code() != boost::interprocess::not_found_error)
+                {
+                    printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
+                    break;
+                }
             }
         }
     }
@@ -278,6 +286,8 @@
                             mq.try_send(strURI, strlen(strURI), 0);
                         }
                         catch (boost::interprocess::interprocess_exception &ex) {
+                            printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
+                            break;
                         }
                     }
                 }
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -51,7 +51,6 @@
 #include <QFileDialog>
 #include <QDesktopServices>
 #include <QTimer>
-
 #include <QDragEnterEvent>
 #include <QUrl>
 
@@ -69,7 +68,7 @@
     rpcConsole(0)
 {
     resize(850, 550);
-    setWindowTitle(tr("Bitcoin Wallet"));
+    setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
 #ifndef Q_WS_MAC
     qApp->setWindowIcon(QIcon(":icons/bitcoin"));
     setWindowIcon(QIcon(":icons/bitcoin"));
@@ -255,7 +254,7 @@
     quitAction->setToolTip(tr("Quit application"));
     quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
     quitAction->setMenuRole(QAction::QuitRole);
-    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About %1").arg(qApp->applicationName()), this);
+    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
     aboutAction->setToolTip(tr("Show information about Bitcoin"));
     aboutAction->setMenuRole(QAction::AboutRole);
     aboutQtAction = new QAction(tr("About &Qt"), this);
@@ -345,6 +344,7 @@
     this->clientModel = clientModel;
     if(clientModel)
     {
+        // Replace some strings and icons, when using the testnet
         if(clientModel->isTestNet())
         {
             setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]"));
@@ -360,6 +360,8 @@
                 trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
                 toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet"));
             }
+
+            aboutAction->setIcon(QIcon(":/icons/toolbar_testnet"));
         }
 
         // Keep up to date with client
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Bitcoin debug window</string>
+   <string>Bitcoin - Debug window</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
@@ -36,7 +36,7 @@
           </font>
          </property>
          <property name="text">
-          <string>Client</string>
+          <string>Bitcoin Core</string>
          </property>
         </widget>
        </item>
--- a/src/qt/forms/signverifymessagedialog.ui
+++ b/src/qt/forms/signverifymessagedialog.ui
@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Messaging - Sign / Verify a Message</string>
+   <string>Signatures - Sign / Verify a Message</string>
   </property>
   <property name="modal">
    <bool>true</bool>
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -4,10 +4,10 @@
 /* Milliseconds between model updates */
 static const int MODEL_UPDATE_DELAY = 500;
 
-/* Maximum  passphrase length */
+/* AskPassphraseDialog -- Maximum passphrase length */
 static const int MAX_PASSPHRASE_SIZE = 1024;
 
-/* Size of icons in status bar */
+/* BitcoinGUI -- Size of icons in status bar */
 static const int STATUSBAR_ICONSIZE = 16;
 
 /* Invalid field background style */
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -68,13 +68,23 @@
         /** check if the locale name consists of 2 parts (language_country) */
         if(langStr.contains("_"))
         {
+#if QT_VERSION >= 0x040800
+            /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
+            ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
+#else
             /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
             ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
+#endif
         }
         else
         {
+#if QT_VERSION >= 0x040800
+            /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
+            ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
+#else
             /** display language strings as "language (locale name)", e.g. "German (de)" */
             ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
+#endif
         }
     }
 
--- a/src/qt/qtipcserver.cpp
+++ b/src/qt/qtipcserver.cpp
@@ -2,76 +2,96 @@
 // Distributed under the MIT/X11 software license, see the accompanying
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
-#include <boost/algorithm/string.hpp>
+#include "qtipcserver.h"
+#include "guiconstants.h"
+#include "ui_interface.h"
+#include "util.h"
+
+#include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/interprocess/ipc/message_queue.hpp>
-#include <boost/tokenizer.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/version.hpp>
 
 #if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
 #warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392
 #endif
 
-#include "ui_interface.h"
-#include "qtipcserver.h"
-
+using namespace boost;
 using namespace boost::interprocess;
 using namespace boost::posix_time;
-using namespace boost;
-using namespace std;
+
+static void ipcThread2(void* pArg);
 
 #ifdef MAC_OSX
 // URI handling not implemented on OSX yet
 
 void ipcInit() { }
-void ipcShutdown() { }
 
 #else
 
-void ipcShutdown()
+static void ipcThread(void* pArg)
 {
-    message_queue::remove(BITCOINURI_QUEUE_NAME);
+    IMPLEMENT_RANDOMIZE_STACK(ipcThread(pArg));
+	
+    // Make this thread recognisable as the GUI-IPC thread
+    RenameThread("bitcoin-gui-ipc");
+	
+    try
+    {
+        ipcThread2(pArg);
+    }
+    catch (std::exception& e) {
+        PrintExceptionContinue(&e, "ipcThread()");
+    } catch (...) {
+        PrintExceptionContinue(NULL, "ipcThread()");
+    }
+    printf("ipcThread exited\n");
 }
 
-void ipcThread(void* parg)
+static void ipcThread2(void* pArg)
 {
-    message_queue* mq = (message_queue*)parg;
-    char strBuf[257];
-    size_t nSize;
-    unsigned int nPriority;
+    printf("ipcThread started\n");
+
+    message_queue* mq = (message_queue*)pArg;
+    char buffer[MAX_URI_LENGTH + 1] = "";
+    size_t nSize = 0;
+    unsigned int nPriority = 0;
+
     loop
     {
         ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
-        if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
+        if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
         {
-            uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
+            uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
             Sleep(1000);
         }
+
         if (fShutdown)
-        {
-            ipcShutdown();
             break;
-        }
     }
-    ipcShutdown();
+
+    // Remove message queue
+    message_queue::remove(BITCOINURI_QUEUE_NAME);
+    // Cleanup allocated memory
+    delete mq;
 }
 
 void ipcInit()
 {
-    message_queue* mq;
-    char strBuf[257];
-    size_t nSize;
-    unsigned int nPriority;
+    message_queue* mq = NULL;
+    char buffer[MAX_URI_LENGTH + 1] = "";
+    size_t nSize = 0;
+    unsigned int nPriority = 0;
+
     try {
-        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
+        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
 
         // Make sure we don't lose any bitcoin: URIs
         for (int i = 0; i < 2; i++)
         {
             ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
-            if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
+            if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
             {
-                uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize));
+                uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
             }
             else
                 break;
@@ -79,14 +99,19 @@
 
         // Make sure only one bitcoin instance is listening
         message_queue::remove(BITCOINURI_QUEUE_NAME);
-        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
+        delete mq;
+
+        mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
     }
     catch (interprocess_exception &ex) {
+        printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
         return;
     }
+
     if (!CreateThread(ipcThread, mq))
     {
         delete mq;
+        return;
     }
 }
 
--- a/src/qt/qtipcserver.h
+++ b/src/qt/qtipcserver.h
@@ -1,4 +1,9 @@
+#ifndef QTIPCSERVER_H
+#define QTIPCSERVER_H
+
+// Define Bitcoin-Qt message queue name
 #define BITCOINURI_QUEUE_NAME "BitcoinURI"
 
 void ipcInit();
-void ipcShutdown();
+
+#endif // QTIPCSERVER_H
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -276,14 +276,16 @@
 
 Value signrawtransaction(const Array& params, bool fHelp)
 {
-    if (fHelp || params.size() < 1 || params.size() > 3)
+    if (fHelp || params.size() < 1 || params.size() > 4)
         throw runtime_error(
-            "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...]\n"
+            "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
             "Sign inputs for raw transaction (serialized, hex-encoded).\n"
             "Second optional argument is an array of previous transaction outputs that\n"
             "this transaction depends on but may not yet be in the blockchain.\n"
             "Third optional argument is an array of base58-encoded private\n"
             "keys that, if given, will be the only keys used to sign the transaction.\n"
+            "Fourth option is a string that is one of six values; ALL, NONE, SINGLE or\n"
+            "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
             "Returns json object with keys:\n"
             "  hex : raw transaction with signature(s) (hex-encoded string)\n"
             "  complete : 1 if transaction has a complete set of signature (0 if not)"
@@ -402,6 +404,25 @@
     }
     const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
 
+    int nHashType = SIGHASH_ALL;
+    if (params.size() > 3)
+    {
+        static map<string, int> mapSigHashValues =
+            boost::assign::map_list_of
+            (string("ALL"), int(SIGHASH_ALL))
+            (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
+            (string("NONE"), int(SIGHASH_NONE))
+            (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
+            (string("SINGLE"), int(SIGHASH_SINGLE))
+            (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
+            ;
+        string strHashType = params[3].get_str();
+        if (mapSigHashValues.count(strHashType))
+            nHashType = mapSigHashValues[strHashType];
+        else
+            throw JSONRPCError(-8, "Invalid sighash param");
+    }
+
     // Sign what we can:
     for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
     {
@@ -414,7 +435,7 @@
         const CScript& prevPubKey = mapPrevOut[txin.prevout];
 
         txin.scriptSig.clear();
-        SignSignature(keystore, prevPubKey, mergedTx, i);
+        SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
 
         // ... and merge in other signatures:
         BOOST_FOREACH(const CTransaction& txv, txVariants)
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -51,6 +51,8 @@
 #endif
 #include <io.h> /* for _commit */
 #include "shlobj.h"
+#elif defined(__linux__)
+# include <sys/prctl.h>
 #endif
 
 using namespace std;
@@ -1275,3 +1277,20 @@
         printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr);
 }
 
+void RenameThread(const char* name)
+{
+#if defined(PR_SET_NAME)
+    // Only the first 15 characters are used (16 - NUL terminator)
+    ::prctl(PR_SET_NAME, name, 0, 0, 0);
+#elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__))
+    // TODO: This is currently disabled because it needs to be verified to work
+    //       on FreeBSD or OpenBSD first. When verified the '0 &&' part can be
+    //       removed.
+    pthread_set_name_np(pthread_self(), name);
+#elif defined(MAC_OSX)
+    pthread_setname_np(name);
+#else
+    // Prevent warnings for unused parameters...
+    (void)name;
+#endif
+}
--- a/src/util.h
+++ b/src/util.h
@@ -621,9 +621,7 @@
 }
 #endif
 
-
-
-
+void RenameThread(const char* name);
 
 inline uint32_t ByteReverse(uint32_t value)
 {
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -323,6 +323,9 @@
 
 void ThreadFlushWalletDB(void* parg)
 {
+    // Make this thread recognisable as the wallet flushing thread
+    RenameThread("bitcoin-wallet");
+
     const string& strFile = ((const string*)parg)[0];
     static bool fOneThread;
     if (fOneThread)