Merge #13161: wallet: Reset BerkeleyDB handle after connection fails

b6f0b4d wallet: Improve logging when BerkeleyDB environment fails to close (Tim Ruffing)
264c643 wallet: Reset BerkeleyDB handle after connection fails (Tim Ruffing)

Pull request description:

  According to the BerkeleyDB docs, the DbEnv handle may not be accessed
  after close() has been called. This change ensures that we create a new
  handle after close() is called. This avoids a segfault when the first
  connection attempt fails and then a second connection attempt tries to
  call open() on the already closed DbEnv handle.

  Without the patch, bitcoindd reliably crashes in the second call to `set_lg_dir()` after `close()` if
  there is an issue with the database:
  ```
  2018-05-03T13:27:21Z Bitcoin Core version v0.16.99.0-a024a1841-dirty (debug build)
  [...]
  2018-05-03T13:27:21Z Using wallet directory /home/tim/.bitcoin
  2018-05-03T13:27:21Z init message: Verifying wallet(s)...
  2018-05-03T13:27:21Z Using BerkeleyDB version Berkeley DB 4.8.30: (April  9, 2010)
  2018-05-03T13:27:21Z Using wallet wallet.dat
  2018-05-03T13:27:21Z BerkeleyEnvironment::Open: LogDir=/home/tim/.bitcoin/database
  2018-05-03T13:27:21Z BerkeleyEnvironment::Open: Error -30974 opening database environment: DB_RUNRECOVERY: Fatal error, run database recovery
  2018-05-03T13:27:21Z Moved old /home/tim/.bitcoin/database to /home/tim/.bitcoin/database.1525354041.bak. Retrying.
  2018-05-03T13:27:21Z BerkeleyEnvironment::Open: LogDir=/home/tim/.bitcoin/database ErrorFile=/home/tim/.bitcoin/db.log
  [1]    14533 segmentation fault (core dumped)  ./src/bitcoind
  ```

  After the fix:
  ```
  2018-05-03T17:19:32Z Bitcoin Core version v0.16.99.0-cc09e3bd0-dirty (release build)
  [...]
  2018-05-03T17:19:32Z Using wallet directory /home/tim/.bitcoin
  2018-05-03T17:19:32Z init message: Verifying wallet(s)...
  2018-05-03T17:19:32Z Using BerkeleyDB version Berkeley DB 4.8.30: (April  9, 2010)
  2018-05-03T17:19:32Z Using wallet wallet.dat
  2018-05-03T17:19:32Z BerkeleyEnvironment::Open: LogDir=/home/tim/.bitcoin/database ErrorFile=/home/tim/.bitcoin/db.log
  2018-05-03T17:19:32Z scheduler thread start
  2018-05-03T17:19:32Z BerkeleyEnvironment::Open: Error -30974 opening database environment: DB_RUNRECOVERY: Fatal error, run database recovery
  2018-05-03T17:19:32Z Moved old /home/tim/.bitcoin/database to /home/tim/.bitcoin/database.1525367972.bak. Retrying.
  2018-05-03T17:19:32Z BerkeleyEnvironment::Open: LogDir=/home/tim/.bitcoin/database ErrorFile=/home/tim/.bitcoin/db.log
  2018-05-03T17:19:32Z Cache configuration:
  2018-05-03T17:19:32Z * Using 2.0MiB for block index database
  2018-05-03T17:19:32Z * Using 8.0MiB for chain state database
  2018-05-03T17:19:32Z * Using 440.0MiB for in-memory UTXO set (plus up to 286.1MiB of unused mempool space)
  2018-05-03T17:19:32Z init message: Loading block index..
  [...]
  ```

Tree-SHA512: b809b318e5014ec47d023dc3dc40826b9706bfb211fa08bc2d29f36971b96caa10ad48d9a3f96c03933be46fa4ff7e00e952ac77bfffb6563767fb08aa4f23d6
This commit is contained in:
Wladimir J. van der Laan 2018-05-14 14:54:23 +02:00
commit 7cc1bd3aae
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D
1 changed files with 6 additions and 2 deletions

View File

@ -102,7 +102,7 @@ void BerkeleyEnvironment::Close()
int ret = dbenv->close(0);
if (ret != 0)
LogPrintf("BerkeleyEnvironment::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
LogPrintf("BerkeleyEnvironment::Close: Error %d closing database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
DbEnv((u_int32_t)0).remove(strPath.c_str(), 0);
}
@ -168,8 +168,12 @@ bool BerkeleyEnvironment::Open(bool retry)
nEnvFlags,
S_IRUSR | S_IWUSR);
if (ret != 0) {
dbenv->close(0);
LogPrintf("BerkeleyEnvironment::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));
int ret2 = dbenv->close(0);
if (ret2 != 0) {
LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2));
}
Reset();
if (retry) {
// try moving the database env out of the way
fs::path pathDatabaseBak = pathIn / strprintf("database.%d.bak", GetTime());