Fix deadlocks in setaccount, sendfrom RPC calls
SendMoney*() now requires caller to acquire cs_main.
GetAccountAddress() now requires caller to acquire cs_main, cs_mapWallet.
Ordering is intended to match these two callchains[1]:
1. CRITICAL_BLOCK(cs_main)
ProcessMessage(pfrom, strCommand, vMsg)
AddToWalletIfMine()
AddToWallet(wtx)
CRITICAL_BLOCK(cs_mapWallet)
2. CRITICAL_BLOCK(cs_main)
ProcessMessage(pfrom, strCommand, vMsg)
AddToWalletIfMine()
AddToWallet(wtx)
CRITICAL_BLOCK(cs_mapWallet)
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "")
CRITICAL_BLOCK(cs_mapAddressBook)
Spotted by ArtForz. Additional deadlock fixes by Gavin.
[1] http://www.bitcoin.org/smf/index.php?topic=4904.msg71897#msg71897
This commit is contained in:
38
main.cpp
38
main.cpp
@@ -4046,35 +4046,35 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
|
||||
|
||||
|
||||
// requires cs_main lock
|
||||
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CReserveKey reservekey;
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||
{
|
||||
CReserveKey reservekey;
|
||||
int64 nFeeRequired;
|
||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||
{
|
||||
string strError;
|
||||
if (nValue + nFeeRequired > GetBalance())
|
||||
strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str());
|
||||
else
|
||||
strError = _("Error: Transaction creation failed ");
|
||||
printf("SendMoney() : %s", strError.c_str());
|
||||
return strError;
|
||||
}
|
||||
|
||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||
return "ABORTED";
|
||||
|
||||
if (!CommitTransaction(wtxNew, reservekey))
|
||||
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
||||
string strError;
|
||||
if (nValue + nFeeRequired > GetBalance())
|
||||
strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str());
|
||||
else
|
||||
strError = _("Error: Transaction creation failed ");
|
||||
printf("SendMoney() : %s", strError.c_str());
|
||||
return strError;
|
||||
}
|
||||
|
||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||
return "ABORTED";
|
||||
|
||||
if (!CommitTransaction(wtxNew, reservekey))
|
||||
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
||||
|
||||
MainFrameRepaint();
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// requires cs_main lock
|
||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||
{
|
||||
// Check amount
|
||||
|
||||
Reference in New Issue
Block a user