diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/init.cpp | 16 | ||||
-rw-r--r-- | src/prevector.h | 6 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 3 | ||||
-rw-r--r-- | src/wallet/test/wallet_tests.cpp | 2 |
4 files changed, 27 insertions, 0 deletions
diff --git a/src/init.cpp b/src/init.cpp index 7c108ac4a6..5820d8f57c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -801,6 +801,19 @@ ServiceFlags nLocalServices = NODE_NETWORK; } +[[noreturn]] static void new_handler_terminate() +{ + // Rather than throwing std::bad-alloc if allocation fails, terminate + // immediately to (try to) avoid chain corruption. + // Since LogPrintf may itself allocate memory, set the handler directly + // to terminate first. + std::set_new_handler(std::terminate); + LogPrintf("Error: Out of memory. Terminating.\n"); + + // The log was successful, terminate now. + std::terminate(); +}; + bool AppInitBasicSetup() { // ********************************************************* Step 1: setup @@ -853,6 +866,9 @@ bool AppInitBasicSetup() // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly signal(SIGPIPE, SIG_IGN); #endif + + std::set_new_handler(new_handler_terminate); + return true; } diff --git a/src/prevector.h b/src/prevector.h index 6b2f578f5c..cba2e30057 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -5,6 +5,7 @@ #ifndef _BITCOIN_PREVECTOR_H_ #define _BITCOIN_PREVECTOR_H_ +#include <assert.h> #include <stdlib.h> #include <stdint.h> #include <string.h> @@ -170,10 +171,15 @@ private: } } else { if (!is_direct()) { + /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert + success. These should instead use an allocator or new/delete so that handlers + are called as necessary, but performance would be slightly degraded by doing so. */ _union.indirect = static_cast<char*>(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity)); + assert(_union.indirect); _union.capacity = new_capacity; } else { char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity)); + assert(new_indirect); T* src = direct_ptr(0); T* dst = reinterpret_cast<T*>(new_indirect); memcpy(dst, src, size() * sizeof(T)); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 45b572aa2e..510b2d6ebc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -819,6 +819,9 @@ UniValue sendfrom(const JSONRPCRequest& request) + HelpRequiringPassphrase() + "\n" "\nArguments:\n" "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n" + " Specifying an account does not influence coin selection, but it does associate the newly created\n" + " transaction with the account, so the account's balance computation and transaction history can reflect\n" + " the spend.\n" "2. \"toaddress\" (string, required) The bitcoin address to send funds to.\n" "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index d32e8ba06a..43d7e3c617 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -397,6 +397,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { CWallet wallet; + CWallet *backup = ::pwalletMain; ::pwalletMain = &wallet; UniValue key; key.setObject(); @@ -412,6 +413,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) UniValue response = importmulti(request); BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}}]", newTip->GetBlockTimeMax())); + ::pwalletMain = backup; } } |