changeset 21:cb33310566a5 draft

got rid of CheckForShutdown, replaced some thread-unsafe wxWidgets calls, Linux fixes, socket send MSG_NOSIGNAL, bind INADDR_ANY, works reliably on Linux now except if wxMessageBox is used in a thread other than the GUI thread git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@33 1a98c847-1fd6-4fd8-948a-caf3550aa51b
author s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
date Fri, 06 Nov 2009 05:50:05 +0000
parents e7d23a6baa44
children a08861e14f19
files db.cpp irc.cpp main.cpp main.h net.cpp net.h ui.cpp ui.h uibase.cpp uiproject.fbp util.cpp util.h
diffstat 12 files changed, 259 insertions(+), 234 deletions(-) [+]
line wrap: on
line diff
--- a/db.cpp
+++ b/db.cpp
@@ -550,7 +550,7 @@
                 //printf("LoadWallet  %s\n", wtx.GetHash().ToString().c_str());
                 //printf(" %12I64d  %s  %s  %s\n",
                 //    wtx.vout[0].nValue,
-                //    DateTimeStr(wtx.nTime).c_str(),
+                //    DateTimeStrFormat("%x %H:%M:%S", wtx.nTime).c_str(),
                 //    wtx.hashBlock.ToString().substr(0,14).c_str(),
                 //    wtx.mapValue["message"].c_str());
             }
--- a/irc.cpp
+++ b/irc.cpp
@@ -167,9 +167,12 @@
     while (!fShutdown)
     {
         CAddress addrConnect("216.155.130.130:6667");
-        struct hostent* phostent = gethostbyname("chat.freenode.net");
-        if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
-            addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(6667));
+        if (!(fUseProxy && addrProxy.port == htons(9050)))
+        {
+            struct hostent* phostent = gethostbyname("chat.freenode.net");
+            if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
+                addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(6667));
+        }
 
         SOCKET hSocket;
         if (!ConnectSocket(addrConnect, hSocket))
--- a/main.cpp
+++ b/main.cpp
@@ -1361,15 +1361,24 @@
 
 bool CheckDiskSpace(int64 nAdditionalBytes)
 {
-    wxLongLong nFreeBytesAvailable = 0;
-    if (!wxGetDiskSpace(GetDataDir(), NULL, &nFreeBytesAvailable))
+#ifdef __WXMSW__
+    uint64 nFreeBytesAvailable = 0;     // bytes available to caller
+    uint64 nTotalNumberOfBytes = 0;     // bytes on disk
+    uint64 nTotalNumberOfFreeBytes = 0; // free bytes on disk
+    if (!GetDiskFreeSpaceEx(GetDataDir().c_str(),
+            (PULARGE_INTEGER)&nFreeBytesAvailable,
+            (PULARGE_INTEGER)&nTotalNumberOfBytes,
+            (PULARGE_INTEGER)&nTotalNumberOfFreeBytes))
     {
-        printf("ERROR: wxGetDiskSpace() failed\n");
+        printf("ERROR: GetDiskFreeSpaceEx() failed\n");
         return true;
     }
+#else
+    uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
+#endif
 
     // Check for 15MB because database could create another 10MB log file at any time
-    if (nFreeBytesAvailable.GetValue() < (int64)15000000 + nAdditionalBytes)
+    if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes)
     {
         fShutdown = true;
         wxMessageBox("Warning: Your disk space is low  ", "Bitcoin", wxICON_EXCLAMATION);
@@ -1546,7 +1555,7 @@
             pindex->nFile,
             pindex->nBlockPos,
             block.GetHash().ToString().substr(0,14).c_str(),
-            DateTimeStr(block.nTime).c_str(),
+            DateTimeStrFormat("%x %H:%M:%S", block.nTime).c_str(),
             block.vtx.size());
 
         CRITICAL_BLOCK(cs_mapWallet)
@@ -1673,20 +1682,24 @@
         bool fRet = false;
         try
         {
-            CheckForShutdown(2);
             CRITICAL_BLOCK(cs_main)
                 fRet = ProcessMessage(pfrom, strCommand, vMsg);
-            CheckForShutdown(2);
+            if (fShutdown)
+                return true;
         }
-        catch (std::ios_base::failure& e) {
+        catch (std::ios_base::failure& e)
+        {
             if (strstr(e.what(), "CDataStream::read() : end of data"))
             {
                 // Allow exceptions from underlength message on vRecv
                 printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
             }
             else
+            {
                 PrintException(&e, "ProcessMessage()");
-        } catch (std::exception& e) {
+            }
+        }
+        catch (std::exception& e) {
             PrintException(&e, "ProcessMessage()");
         } catch (...) {
             PrintException(NULL, "ProcessMessage()");
@@ -2093,7 +2106,6 @@
 
 bool SendMessages(CNode* pto)
 {
-    CheckForShutdown(2);
     CRITICAL_BLOCK(cs_main)
     {
         // Don't send anything until we get their version message
@@ -2223,12 +2235,10 @@
 
 void ThreadBitcoinMiner(void* parg)
 {
-    vnThreadsRunning[3]++;
-    CheckForShutdown(3);
     try
     {
-        bool fRet = BitcoinMiner();
-        printf("BitcoinMiner returned %s\n", fRet ? "true" : "false");
+        vnThreadsRunning[3]++;
+        BitcoinMiner();
         vnThreadsRunning[3]--;
     }
     catch (std::exception& e) {
@@ -2238,6 +2248,8 @@
         vnThreadsRunning[3]--;
         PrintException(NULL, "ThreadBitcoinMiner()");
     }
+
+    printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
 }
 
 int FormatHashBlocks(void* pbuffer, unsigned int len)
@@ -2285,7 +2297,7 @@
 }
 
 
-bool BitcoinMiner()
+void BitcoinMiner()
 {
     printf("BitcoinMiner started\n");
 
@@ -2296,11 +2308,13 @@
     {
         SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
         Sleep(50);
-        CheckForShutdown(3);
+        if (fShutdown)
+            return;
         while (vNodes.empty())
         {
             Sleep(1000);
-            CheckForShutdown(3);
+            if (fShutdown)
+                return;
         }
 
         unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
@@ -2324,7 +2338,7 @@
         //
         auto_ptr<CBlock> pblock(new CBlock());
         if (!pblock.get())
-            return false;
+            return;
 
         // Add our coinbase tx as first transaction
         pblock->vtx.push_back(txNew);
@@ -2433,7 +2447,7 @@
                     {
                         // Save key
                         if (!AddKey(key))
-                            return false;
+                            return;
                         key.MakeNewKey();
 
                         // Process this block the same as if we had received it from another node
@@ -2450,7 +2464,12 @@
             // Update nTime every few seconds
             if ((++tmp.block.nNonce & 0xffff) == 0)
             {
-                CheckForShutdown(3);
+                if (fShutdown)
+                    return;
+                if (!fGenerateBitcoins)
+                    return;
+                if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
+                    return;
                 if (tmp.block.nNonce == 0)
                     break;
                 if (pindexPrev != pindexBest)
@@ -2459,16 +2478,10 @@
                     break;
                 if (vNodes.empty())
                     break;
-                if (!fGenerateBitcoins)
-                    return true;
-                if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
-                    return true;
                 tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
             }
         }
     }
-
-    return true;
 }
 
 
--- a/main.h
+++ b/main.h
@@ -68,7 +68,7 @@
 bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
 void GenerateBitcoins(bool fGenerate);
 void ThreadBitcoinMiner(void* parg);
-bool BitcoinMiner();
+void BitcoinMiner();
 
 
 
--- a/net.cpp
+++ b/net.cpp
@@ -48,6 +48,10 @@
     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (hSocket == INVALID_SOCKET)
         return false;
+#if defined(__BSD__) || defined(__WXOSX__)
+    int set = 1;
+    setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
+#endif
 
     bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
     bool fProxy = (fUseProxy && fRoutable);
@@ -68,7 +72,7 @@
         char* pszSocks4 = pszSocks4IP;
         int nSize = sizeof(pszSocks4IP);
 
-        int ret = send(hSocket, pszSocks4, nSize, 0);
+        int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
         if (ret != nSize)
         {
             closesocket(hSocket);
@@ -100,7 +104,7 @@
     if (!ConnectSocket(addrConnect, hSocket))
         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
 
-    send(hSocket, pszGet, strlen(pszGet), 0);
+    send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
 
     string strLine;
     while (RecvLine(hSocket, strLine))
@@ -124,7 +128,8 @@
             if (strLine.find("<"))
                 strLine = strLine.substr(0, strLine.find("<"));
             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
-            strLine = wxString(strLine).Trim();
+            while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
+                strLine.resize(strLine.size()-1);
             CAddress addr(strLine.c_str());
             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
@@ -492,24 +497,26 @@
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
 
-    loop
+    try
     {
         vnThreadsRunning[0]++;
-        CheckForShutdown(0);
-        try
-        {
-            ThreadSocketHandler2(parg);
-            vnThreadsRunning[0]--;
-        }
-        catch (std::exception& e) {
-            vnThreadsRunning[0]--;
-            PrintException(&e, "ThreadSocketHandler()");
-        } catch (...) {
-            vnThreadsRunning[0]--;
-            PrintException(NULL, "ThreadSocketHandler()");
-        }
-        Sleep(5000);
+        ThreadSocketHandler2(parg);
+        vnThreadsRunning[0]--;
     }
+    catch (std::exception& e) {
+        vnThreadsRunning[0]--;
+        PrintException(&e, "ThreadSocketHandler()");
+    } catch (...) {
+        vnThreadsRunning[0]--;
+        PrintException(NULL, "ThreadSocketHandler()");
+    }
+
+    foreach(CNode* pnode, vNodes)
+        closesocket(pnode->hSocket);
+    if (closesocket(hListenSocket) == SOCKET_ERROR)
+        printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
+
+    printf("ThreadSocketHandler exiting\n");
 }
 
 void ThreadSocketHandler2(void* parg)
@@ -600,7 +607,8 @@
         vnThreadsRunning[0]--;
         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
         vnThreadsRunning[0]++;
-        CheckForShutdown(0);
+        if (fShutdown)
+            return;
         if (nSelect == SOCKET_ERROR)
         {
             int nErr = WSAGetLastError();
@@ -659,7 +667,8 @@
             vNodesCopy = vNodes;
         foreach(CNode* pnode, vNodesCopy)
         {
-            CheckForShutdown(0);
+            if (fShutdown)
+                return;
             SOCKET hSocket = pnode->hSocket;
 
             //
@@ -708,7 +717,7 @@
                     CDataStream& vSend = pnode->vSend;
                     if (!vSend.empty())
                     {
-                        int nBytes = send(hSocket, &vSend[0], vSend.size(), 0);
+                        int nBytes = send(hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL);
                         if (nBytes > 0)
                         {
                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
@@ -747,24 +756,21 @@
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
 
-    loop
+    try
     {
         vnThreadsRunning[1]++;
-        CheckForShutdown(1);
-        try
-        {
-            ThreadOpenConnections2(parg);
-            vnThreadsRunning[1]--;
-        }
-        catch (std::exception& e) {
-            vnThreadsRunning[1]--;
-            PrintException(&e, "ThreadOpenConnections()");
-        } catch (...) {
-            vnThreadsRunning[1]--;
-            PrintException(NULL, "ThreadOpenConnections()");
-        }
-        Sleep(5000);
+        ThreadOpenConnections2(parg);
+        vnThreadsRunning[1]--;
     }
+    catch (std::exception& e) {
+        vnThreadsRunning[1]--;
+        PrintException(&e, "ThreadOpenConnections()");
+    } catch (...) {
+        vnThreadsRunning[1]--;
+        PrintException(NULL, "ThreadOpenConnections()");
+    }
+
+    printf("ThreadOpenConnections exiting\n");
 }
 
 void ThreadOpenConnections2(void* parg)
@@ -778,7 +784,8 @@
         for (int i = 0; i < 10; i++)
         {
             Sleep(1000);
-            CheckForShutdown(1);
+            if (fShutdown)
+                return;
         }
     }
 
@@ -792,7 +799,8 @@
             {
                 OpenNetworkConnection(addr);
                 Sleep(1000);
-                CheckForShutdown(1);
+                if (fShutdown)
+                    return;
             }
         }
     }
@@ -806,11 +814,13 @@
         const int nMaxConnections = 15;
         while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
         {
-            CheckForShutdown(1);
+            if (fShutdown)
+                return;
             Sleep(2000);
         }
         vnThreadsRunning[1]++;
-        CheckForShutdown(1);
+        if (fShutdown)
+            return;
 
         //
         // Choose an address to connect to based on most recently seen
@@ -869,14 +879,16 @@
     //
     // Initiate outbound network connection
     //
-    CheckForShutdown(1);
+    if (fShutdown)
+        return false;
     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
         return false;
 
     vnThreadsRunning[1]--;
     CNode* pnode = ConnectNode(addrConnect);
     vnThreadsRunning[1]++;
-    CheckForShutdown(1);
+    if (fShutdown)
+        return false;
     if (!pnode)
         return false;
     pnode->fNetworkNode = true;
@@ -914,24 +926,21 @@
 {
     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
 
-    loop
+    try
     {
         vnThreadsRunning[2]++;
-        CheckForShutdown(2);
-        try
-        {
-            ThreadMessageHandler2(parg);
-            vnThreadsRunning[2]--;
-        }
-        catch (std::exception& e) {
-            vnThreadsRunning[2]--;
-            PrintException(&e, "ThreadMessageHandler()");
-        } catch (...) {
-            vnThreadsRunning[2]--;
-            PrintException(NULL, "ThreadMessageHandler()");
-        }
-        Sleep(5000);
+        ThreadMessageHandler2(parg);
+        vnThreadsRunning[2]--;
     }
+    catch (std::exception& e) {
+        vnThreadsRunning[2]--;
+        PrintException(&e, "ThreadMessageHandler()");
+    } catch (...) {
+        vnThreadsRunning[2]--;
+        PrintException(NULL, "ThreadMessageHandler()");
+    }
+
+    printf("ThreadMessageHandler exiting\n");
 }
 
 void ThreadMessageHandler2(void* parg)
@@ -951,10 +960,14 @@
             // Receive messages
             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
                 ProcessMessages(pnode);
+            if (fShutdown)
+                return;
 
             // Send messages
             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
                 SendMessages(pnode);
+            if (fShutdown)
+                return;
 
             pnode->Release();
         }
@@ -963,7 +976,8 @@
         vnThreadsRunning[2]--;
         Sleep(100);
         vnThreadsRunning[2]++;
-        CheckForShutdown(2);
+        if (fShutdown)
+            return;
     }
 }
 
@@ -996,7 +1010,7 @@
 
     // Get local host ip
     char pszHostName[255];
-    if (gethostname(pszHostName, 255) == SOCKET_ERROR)
+    if (gethostname(pszHostName, sizeof(pszHostName)) == SOCKET_ERROR)
     {
         strError = strprintf("Error: Unable to get IP address of this computer (gethostname returned error %d)", WSAGetLastError());
         printf("%s\n", strError.c_str());
@@ -1009,9 +1023,16 @@
         printf("%s\n", strError.c_str());
         return false;
     }
-    addrLocalHost = CAddress(*(long*)(phostent->h_addr_list[0]),
-                             DEFAULT_PORT,
-                             nLocalServices);
+
+    // Take the first IP that isn't loopback 127.x.x.x
+    for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
+        printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
+    for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
+    {
+        addrLocalHost = CAddress(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);
+        if (addrLocalHost.IsValid() && addrLocalHost.GetByte(3) != 127)
+            break;
+    }
     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
 
     // Create socket for listening for incoming connections
@@ -1022,6 +1043,10 @@
         printf("%s\n", strError.c_str());
         return false;
     }
+#if defined(__BSD__) || defined(__WXOSX__)
+    int set = 1;
+    setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
+#endif
 
     // Set to nonblocking, incoming connections will also inherit this
 #ifdef __WXMSW__
@@ -1038,19 +1063,22 @@
 
     // The sockaddr_in structure specifies the address family,
     // IP address, and port for the socket that is being bound
-    int nRetryLimit = 15;
-    struct sockaddr_in sockaddr = addrLocalHost.GetSockAddr();
+    struct sockaddr_in sockaddr;
+    memset(&sockaddr, 0, sizeof(sockaddr));
+    sockaddr.sin_family = AF_INET;
+    sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
+    sockaddr.sin_port = DEFAULT_PORT;
     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
     {
         int nErr = WSAGetLastError();
         if (nErr == WSAEADDRINUSE)
-            strError = strprintf("Error: Unable to bind to port %s on this computer. The program is probably already running.", addrLocalHost.ToString().c_str());
+            strError = strprintf("Error: Unable to bind to port %d on this computer. The program is probably already running.", ntohs(sockaddr.sin_port));
         else
-            strError = strprintf("Error: Unable to bind to port %s on this computer (bind returned error %d)", addrLocalHost.ToString().c_str(), nErr);
+            strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
         printf("%s\n", strError.c_str());
         return false;
     }
-    printf("bound to addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
+    printf("bound to port %d\n", ntohs(sockaddr.sin_port));
 
     // Listen for incoming connections
     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
@@ -1065,6 +1093,7 @@
     {
         // Proxies can't take incoming connections
         addrLocalHost.ip = CAddress("0.0.0.0").ip;
+        printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
     }
     else
     {
@@ -1115,17 +1144,17 @@
     fShutdown = true;
     nTransactionsUpdated++;
     int64 nStart = GetTime();
-    while (vnThreadsRunning[0] || vnThreadsRunning[2] || vnThreadsRunning[3])
+    while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0)
     {
         if (GetTime() - nStart > 15)
             break;
         Sleep(20);
     }
-    if (vnThreadsRunning[0]) printf("ThreadSocketHandler still running\n");
-    if (vnThreadsRunning[1]) printf("ThreadOpenConnections still running\n");
-    if (vnThreadsRunning[2]) printf("ThreadMessageHandler still running\n");
-    if (vnThreadsRunning[3]) printf("ThreadBitcoinMiner still running\n");
-    while (vnThreadsRunning[2])
+    if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
+    if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
+    if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
+    if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
+    while (vnThreadsRunning[2] > 0)
         Sleep(20);
     Sleep(50);
 
@@ -1135,21 +1164,3 @@
 #endif
     return true;
 }
-
-void CheckForShutdown(int n)
-{
-    if (fShutdown)
-    {
-        if (n != -1)
-            if (--vnThreadsRunning[n] < 0)
-                vnThreadsRunning[n] = 0;
-        if (n == 0)
-        {
-            foreach(CNode* pnode, vNodes)
-                closesocket(pnode->hSocket);
-            closesocket(hListenSocket);
-        }
-        printf("Thread %d exiting\n", n);
-        _endthread();
-    }
-}
--- a/net.h
+++ b/net.h
@@ -30,7 +30,6 @@
 bool AnySubscribed(unsigned int nChannel);
 bool StartNode(string& strError=REF(string()));
 bool StopNode();
-void CheckForShutdown(int n);
 
 
 
@@ -268,6 +267,7 @@
     struct sockaddr_in GetSockAddr() const
     {
         struct sockaddr_in sockaddr;
+        memset(&sockaddr, 0, sizeof(sockaddr));
         sockaddr.sin_family = AF_INET;
         sockaddr.sin_addr.s_addr = ip;
         sockaddr.sin_port = port;
--- a/ui.cpp
+++ b/ui.cpp
@@ -65,11 +65,13 @@
 
 string DateStr(int64 nTime)
 {
+    // Can only be used safely here in the UI
     return (string)wxDateTime((time_t)nTime).FormatDate();
 }
 
 string DateTimeStr(int64 nTime)
 {
+    // Can only be used safely here in the UI
     wxDateTime datetime((time_t)nTime);
     if (Is24HourTime())
         return (string)datetime.Format("%x %H:%M");
@@ -283,6 +285,7 @@
     fRefreshListCtrl = false;
     fRefreshListCtrlRunning = false;
     fOnSetFocusAddress = false;
+    fRefresh = false;
     m_choiceFilter->SetSelection(0);
     m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
     m_listCtrl->SetFocus();
@@ -350,7 +353,7 @@
         StopNode();
         DBFlush(true);
 
-        printf("Bitcoin exiting\n");
+        printf("Bitcoin exiting\n\n");
         exit(0);
     }
 }
@@ -391,6 +394,30 @@
         event.Veto();
 }
 
+int CMainFrame::GetSortIndex(const string& strSort)
+{
+#ifdef __WXMSW__
+    return 0;
+#else
+    // The wx generic listctrl implementation used on GTK doesn't sort,
+    // so we have to do it ourselves.  Remember, we sort in reverse order.
+    // In the wx generic implementation, they store the list of items
+    // in a vector, so indexed lookups are fast, but inserts are slower
+    // the closer they are to the top.
+    int low = 0;
+    int high = m_listCtrl->GetItemCount();
+    while (low < high)
+    {
+        int mid = low + ((high - low) / 2);
+        if (strSort.compare(m_listCtrl->GetItemText(mid).c_str()) >= 0)
+            high = mid;
+        else
+            low = mid + 1;
+    }
+    return low;
+#endif
+}
+
 void CMainFrame::InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5, const wxString& str6)
 {
     string str0 = strSort;
@@ -407,7 +434,7 @@
     // fNew is for blind insert, only use if you're sure it's new
     if (fNew || nIndex == -1)
     {
-        nIndex = m_listCtrl->InsertItem(0, str0);
+        nIndex = m_listCtrl->InsertItem(GetSortIndex(strSort), str0);
     }
     else
     {
@@ -415,7 +442,7 @@
         if (GetItemText(m_listCtrl, nIndex, 0) != str0)
         {
             m_listCtrl->DeleteItem(nIndex);
-            nIndex = m_listCtrl->InsertItem(0, str0);
+            nIndex = m_listCtrl->InsertItem(GetSortIndex(strSort), str0);
         }
     }
 
@@ -826,6 +853,11 @@
 
 void CMainFrame::OnPaint(wxPaintEvent& event)
 {
+    if (fRefresh)
+    {
+        fRefresh = false;
+        Refresh();
+    }
     event.Skip();
 }
 
@@ -846,7 +878,7 @@
             {
                 printf("DelayedRepaint\n");
                 wxPaintEvent event;
-                pframeMain->Refresh();
+                pframeMain->fRefresh = true;
                 pframeMain->AddPendingEvent(event);
             }
         }
@@ -871,7 +903,7 @@
 
         printf("MainFrameRepaint\n");
         wxPaintEvent event;
-        pframeMain->Refresh();
+        pframeMain->fRefresh = true;
         pframeMain->AddPendingEvent(event);
     }
 }
@@ -907,7 +939,7 @@
                 }
                 vWalletUpdated.clear();
                 if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
-                    m_listCtrl->ScrollList(0, INT_MAX);
+                    m_listCtrl->ScrollList(0, INT_MIN/2);
             }
         }
 
@@ -943,9 +975,10 @@
     string strStatus = strprintf("     %d connections     %d blocks     %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
     m_statusBar->SetStatusText(strStatus, 2);
 
-#ifdef __WXMSW__
-    m_listCtrl->OnPaint(event);
-#endif
+    // Pass through to listctrl to actually do the paint, we're just hooking the message
+    m_listCtrl->Disconnect(wxEVT_PAINT, (wxObjectEventFunction)NULL, NULL, this);
+    m_listCtrl->GetEventHandler()->ProcessEvent(event);
+    m_listCtrl->Connect(wxEVT_PAINT, wxPaintEventHandler(CMainFrame::OnPaintListCtrl), NULL, this);
 }
 
 
@@ -3331,7 +3364,11 @@
     g_isPainting = 10000;
 #endif
     wxImage::AddHandler(new wxPNGHandler);
+#ifdef __WXMSW__
     SetAppName("Bitcoin");
+#else
+    SetAppName("bitcoin");
+#endif
 
     ParseParameters(argc, argv);
     if (mapArgs.count("-?") || mapArgs.count("--help"))
@@ -3355,7 +3392,10 @@
     // Limit to single instance per user
     // Required to protect the database files if we're going to keep deleting log.*
     //
-    wxString strMutexName = wxString("Bitcoin.") + getenv("HOMEPATH");
+#ifdef __WXMSW__
+    // todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
+    //  maybe should go by whether successfully bind port 8333 instead
+    wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
     for (int i = 0; i < strMutexName.size(); i++)
         if (!isalnum(strMutexName[i]))
             strMutexName[i] = '.';
@@ -3367,7 +3407,6 @@
         loop
         {
             // TODO: find out how to do this in Linux, or replace with wxWidgets commands
-#ifdef __WXMSW__
             // Show the previous instance and exit
             HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");
             if (hwndPrev)
@@ -3377,7 +3416,6 @@
                 SetForegroundWindow(hwndPrev);
                 return false;
             }
-#endif
 
             if (GetTime() > nStart + 60)
                 return false;
@@ -3390,6 +3428,7 @@
                 break;
         }
     }
+#endif
 
     //
     // Parameters
--- a/ui.h
+++ b/ui.h
@@ -32,7 +32,6 @@
 
 
 extern void HandleCtrlA(wxKeyEvent& event);
-extern string DateTimeStr(int64 nTime);
 extern string FormatTxStatus(const CWalletTx& wtx);
 extern void CrossThreadCall(int nID, void* pdata);
 extern void MainFrameRepaint();
@@ -84,8 +83,10 @@
     bool fRefreshListCtrlRunning;
     bool fOnSetFocusAddress;
     unsigned int nListViewUpdated;
+    bool fRefresh;
 
     void OnCrossThreadCall(wxCommandEvent& event);
+    int GetSortIndex(const string& strSort);
     void InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5);
     bool DeleteLine(uint256 hashKey);
     bool InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
--- a/uibase.cpp
+++ b/uibase.cpp
@@ -84,7 +84,7 @@
 	m_staticText32->Wrap( -1 );
 	bSizer85->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
 	
-	m_textCtrlAddress = new wxTextCtrl( this, wxID_TEXTCTRLADDRESS, wxEmptyString, wxDefaultPosition, wxSize( 250,-1 ), wxTE_READONLY );
+	m_textCtrlAddress = new wxTextCtrl( this, wxID_TEXTCTRLADDRESS, wxEmptyString, wxDefaultPosition, wxSize( 340,-1 ), wxTE_READONLY );
 	m_textCtrlAddress->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) );
 	
 	bSizer85->Add( m_textCtrlAddress, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
@@ -143,7 +143,7 @@
 	wxBoxSizer* bSizer157;
 	bSizer157 = new wxBoxSizer( wxVERTICAL );
 	
-	m_listCtrl = new wxListCtrl( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxALWAYS_SHOW_SB );
+	m_listCtrl = new wxListCtrl( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxVSCROLL );
 	bSizer157->Add( m_listCtrl, 1, wxEXPAND|wxALL, 5 );
 	
 	m_panel7->SetSizer( bSizer157 );
@@ -343,7 +343,7 @@
 	wxBoxSizer* bSizer65;
 	bSizer65 = new wxBoxSizer( wxVERTICAL );
 	
-	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( 85,25 ), 0 );
+	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
 	bSizer65->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	bSizer64->Add( bSizer65, 0, wxALIGN_RIGHT, 5 );
@@ -520,17 +520,13 @@
 	wxBoxSizer* bSizer58;
 	bSizer58 = new wxBoxSizer( wxHORIZONTAL );
 	
-	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( 85,25 ), 0 );
+	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
 	bSizer58->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer58->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	m_buttonApply = new wxButton( this, wxID_APPLY, wxT("&Apply"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonApply->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer58->Add( m_buttonApply, 0, wxALL, 5 );
 	
 	bSizer55->Add( bSizer58, 0, wxALIGN_RIGHT, 5 );
@@ -622,7 +618,7 @@
 	
 	bSizer61->Add( 0, 0, 1, wxEXPAND, 5 );
 	
-	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( 85,25 ), 0 );
+	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
 	bSizer61->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	bSizer60->Add( bSizer61, 0, wxALIGN_RIGHT|wxEXPAND, 5 );
@@ -767,13 +763,10 @@
 	
 	m_buttonSend = new wxButton( this, wxID_BUTTONSEND, wxT("&Send"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
 	m_buttonSend->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
-	m_buttonSend->SetMinSize( wxSize( 85,25 ) );
 	
 	bSizer23->Add( m_buttonSend, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer23->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer21->Add( bSizer23, 0, wxEXPAND, 5 );
@@ -833,13 +826,10 @@
 	
 	m_buttonOK = new wxButton( this, wxID_ANY, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 );
 	m_buttonOK->Enable( false );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
 	
 	bSizer69->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer68->Add( bSizer69, 0, wxEXPAND, 5 );
@@ -887,28 +877,19 @@
 	bSizer69->Add( 0, 0, 1, wxEXPAND, 5 );
 	
 	m_buttonRename = new wxButton( this, wxID_BUTTONRENAME, wxT("&Edit..."), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonRename->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonRename, 0, wxALL, 5 );
 	
 	m_buttonNew = new wxButton( this, wxID_BUTTONNEW, wxT("&New Address..."), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonNew->SetMinSize( wxSize( 110,25 ) );
-	
 	bSizer69->Add( m_buttonNew, 0, wxALL, 5 );
 	
 	m_buttonCopy = new wxButton( this, wxID_BUTTONCOPY, wxT("&Copy to Clipboard"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonCopy->SetMinSize( wxSize( 120,25 ) );
-	
 	bSizer69->Add( m_buttonCopy, 0, wxALL, 5 );
 	
 	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
 	m_buttonCancel->Hide();
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
 	
 	bSizer69->Add( m_buttonCancel, 0, wxALL, 5 );
 	
@@ -969,28 +950,18 @@
 	bSizer69->Add( 0, 0, 1, wxEXPAND, 5 );
 	
 	m_buttonEdit = new wxButton( this, wxID_BUTTONEDIT, wxT("&Edit..."), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonEdit->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonEdit, 0, wxALL, 5 );
 	
 	m_buttonNew = new wxButton( this, wxID_BUTTONNEW, wxT("&New Address..."), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonNew->SetMinSize( wxSize( 110,25 ) );
-	
 	bSizer69->Add( m_buttonNew, 0, wxALL, 5 );
 	
 	m_buttonDelete = new wxButton( this, wxID_BUTTONDELETE, wxT("&Delete"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonDelete->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonDelete, 0, wxALL, 5 );
 	
 	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer69->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer68->Add( bSizer69, 0, wxEXPAND, 5 );
@@ -1389,18 +1360,12 @@
 	bSizer26 = new wxBoxSizer( wxHORIZONTAL );
 	
 	m_buttonOK = new wxButton( this, wxID_BUTTONSEND, wxT("&Send"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonPreview = new wxButton( this, wxID_BUTTONPREVIEW, wxT("&Preview"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonPreview->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonPreview, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer20->Add( bSizer26, 0, wxALIGN_RIGHT, 5 );
@@ -1605,18 +1570,13 @@
 	
 	m_buttonBack = new wxButton( this, wxID_BUTTONBACK, wxT("< &Back  "), wxDefaultPosition, wxDefaultSize, 0 );
 	m_buttonBack->Enable( false );
-	m_buttonBack->SetMinSize( wxSize( 85,25 ) );
 	
 	bSizer26->Add( m_buttonBack, 0, wxALL, 5 );
 	
 	m_buttonNext = new wxButton( this, wxID_BUTTONNEXT, wxT("  &Next >"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonNext->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonNext, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer20->Add( bSizer26, 0, wxALIGN_RIGHT, 5 );
@@ -1662,8 +1622,6 @@
 	bSizer26 = new wxBoxSizer( wxHORIZONTAL );
 	
 	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer26->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	bSizer20->Add( bSizer26, 0, wxALIGN_RIGHT, 5 );
@@ -1720,13 +1678,9 @@
 	bSizer113 = new wxBoxSizer( wxHORIZONTAL );
 	
 	m_buttonSubmit = new wxButton( this, wxID_SUBMIT, wxT("&Submit"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonSubmit->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer113->Add( m_buttonSubmit, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer113->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer112->Add( bSizer113, 0, wxALIGN_RIGHT, 5 );
@@ -1951,13 +1905,9 @@
 	bSizer80->Add( 0, 0, 1, wxEXPAND, 5 );
 	
 	m_buttonOK = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
-	m_buttonOK->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer80->Add( m_buttonOK, 0, wxALL, 5 );
 	
 	m_buttonCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
-	m_buttonCancel->SetMinSize( wxSize( 85,25 ) );
-	
 	bSizer80->Add( m_buttonCancel, 0, wxALL, 5 );
 	
 	bSizer79->Add( bSizer80, 0, wxEXPAND, 5 );
--- a/uiproject.fbp
+++ b/uiproject.fbp
@@ -70,7 +70,7 @@
             <event name="OnSetFocus"></event>
             <event name="OnSize"></event>
             <event name="OnUpdateUI"></event>
-            <object class="wxMenuBar" expanded="1">
+            <object class="wxMenuBar" expanded="0">
                 <property name="bg">240,240,240</property>
                 <property name="context_help"></property>
                 <property name="enabled">1</property>
@@ -225,7 +225,7 @@
                     </object>
                 </object>
             </object>
-            <object class="wxToolBar" expanded="1">
+            <object class="wxToolBar" expanded="0">
                 <property name="bg"></property>
                 <property name="bitmapsize">20,20</property>
                 <property name="context_help"></property>
@@ -439,7 +439,7 @@
                                 <property name="name">m_textCtrlAddress</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
-                                <property name="size">250,-1</property>
+                                <property name="size">340,-1</property>
                                 <property name="style">wxTE_READONLY</property>
                                 <property name="subclass"></property>
                                 <property name="tooltip"></property>
@@ -944,7 +944,7 @@
                                             <property name="tooltip"></property>
                                             <property name="window_extra_style"></property>
                                             <property name="window_name"></property>
-                                            <property name="window_style">wxALWAYS_SHOW_SB</property>
+                                            <property name="window_style">wxVSCROLL</property>
                                             <event name="OnChar"></event>
                                             <event name="OnEnterWindow"></event>
                                             <event name="OnEraseBackground"></event>
@@ -1648,7 +1648,7 @@
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
-                                <property name="size">85,25</property>
+                                <property name="size">-1,-1</property>
                                 <property name="style"></property>
                                 <property name="subclass"></property>
                                 <property name="tooltip"></property>
@@ -3031,7 +3031,7 @@
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
-                                <property name="size">85,25</property>
+                                <property name="size">-1,-1</property>
                                 <property name="style"></property>
                                 <property name="subclass"></property>
                                 <property name="tooltip"></property>
@@ -3079,7 +3079,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -3131,7 +3131,7 @@
                                 <property name="id">wxID_APPLY</property>
                                 <property name="label">&amp;Apply</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonApply</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -3493,7 +3493,7 @@
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
-                                <property name="size">85,25</property>
+                                <property name="size">-1,-1</property>
                                 <property name="style"></property>
                                 <property name="subclass"></property>
                                 <property name="tooltip"></property>
@@ -4485,7 +4485,7 @@
                                 <property name="id">wxID_BUTTONSEND</property>
                                 <property name="label">&amp;Send</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonSend</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -4537,7 +4537,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -4775,7 +4775,7 @@
                                 <property name="id">wxID_ANY</property>
                                 <property name="label">OK</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -4827,7 +4827,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5089,7 +5089,7 @@
                                 <property name="id">wxID_BUTTONRENAME</property>
                                 <property name="label">&amp;Edit...</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonRename</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5141,7 +5141,7 @@
                                 <property name="id">wxID_BUTTONNEW</property>
                                 <property name="label">&amp;New Address...</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">110,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonNew</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5193,7 +5193,7 @@
                                 <property name="id">wxID_BUTTONCOPY</property>
                                 <property name="label">&amp;Copy to Clipboard</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">120,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCopy</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5245,7 +5245,7 @@
                                 <property name="id">wxID_OK</property>
                                 <property name="label">OK</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5297,7 +5297,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5559,7 +5559,7 @@
                                 <property name="id">wxID_BUTTONEDIT</property>
                                 <property name="label">&amp;Edit...</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonEdit</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5611,7 +5611,7 @@
                                 <property name="id">wxID_BUTTONNEW</property>
                                 <property name="label">&amp;New Address...</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">110,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonNew</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5663,7 +5663,7 @@
                                 <property name="id">wxID_BUTTONDELETE</property>
                                 <property name="label">&amp;Delete</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonDelete</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5715,7 +5715,7 @@
                                 <property name="id">wxID_OK</property>
                                 <property name="label">OK</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -5767,7 +5767,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">public</property>
                                 <property name="pos"></property>
@@ -10225,7 +10225,7 @@
                                 <property name="id">wxID_BUTTONSEND</property>
                                 <property name="label">&amp;Send</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -10277,7 +10277,7 @@
                                 <property name="id">wxID_BUTTONPREVIEW</property>
                                 <property name="label">&amp;Preview</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonPreview</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -10329,7 +10329,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -10798,7 +10798,7 @@
                                 <property name="id">wxID_BUTTONBACK</property>
                                 <property name="label">&lt; &amp;Back  </property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonBack</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -10850,7 +10850,7 @@
                                 <property name="id">wxID_BUTTONNEXT</property>
                                 <property name="label">  &amp;Next &gt;</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonNext</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -10902,7 +10902,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -11087,7 +11087,7 @@
                                 <property name="id">wxID_OK</property>
                                 <property name="label">OK</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -11488,7 +11488,7 @@
                                 <property name="id">wxID_SUBMIT</property>
                                 <property name="label">&amp;Submit</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonSubmit</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -11540,7 +11540,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -12907,7 +12907,7 @@
                                 <property name="id">wxID_OK</property>
                                 <property name="label">OK</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonOK</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
@@ -12959,7 +12959,7 @@
                                 <property name="id">wxID_CANCEL</property>
                                 <property name="label">Cancel</property>
                                 <property name="maximum_size"></property>
-                                <property name="minimum_size">85,25</property>
+                                <property name="minimum_size">-1,-1</property>
                                 <property name="name">m_buttonCancel</property>
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
--- a/util.cpp
+++ b/util.cpp
@@ -96,12 +96,7 @@
         hash = 0;
         memset(pdata, 0, nSize);
 
-        time_t nTime;
-        time(&nTime);
-        struct tm* ptmTime = gmtime(&nTime);
-        char pszTime[200];
-        strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime);
-        printf("%s RandAddSeed() %d bytes\n", pszTime, nSize);
+        printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str(), nSize);
     }
 #endif
 }
@@ -350,7 +345,9 @@
     pszModule[0] = '\0';
     GetModuleFileName(NULL, pszModule, sizeof(pszModule));
 #else
-    const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
+    // might not be thread safe, uses wxString
+    //const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
+    const char* pszModule = "bitcoin";
 #endif
     if (pex)
         snprintf(pszMessage, 1000,
@@ -425,7 +422,6 @@
         }
         strlcpy(pszDir, pszCachedDir, MAX_PATH);
     }
-
 }
 
 string GetDataDir()
--- a/util.h
+++ b/util.h
@@ -84,6 +84,10 @@
 #define THREAD_PRIORITY_NORMAL          0
 #define THREAD_PRIORITY_ABOVE_NORMAL    0
 #endif
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL        0
+#endif
+
 
 
 
@@ -379,6 +383,14 @@
     return wxGetLocalTimeMillis().GetValue();
 }
 
+inline string DateTimeStrFormat(const char* pszFormat, int64 nTime)
+{
+    time_t n = nTime;
+    struct tm* ptmTime = gmtime(&n);
+    char pszTime[200];
+    strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime);
+    return pszTime;
+}
 
 
 
@@ -400,7 +412,7 @@
     {                                                               \
         static char nLoops;                                         \
         if (nLoops <= 0)                                            \
-            nLoops = GetRand(50) + 1;                               \
+            nLoops = GetRand(20) + 1;                               \
         if (nLoops-- > 1)                                           \
         {                                                           \
             ThreadFn;                                               \