| 184 | } |
| 185 | |
| 186 | void Shutdown() |
| 187 | { |
| 188 | LogPrintf("%s: In progress...\n", __func__); |
| 189 | static CCriticalSection cs_Shutdown; |
| 190 | TRY_LOCK(cs_Shutdown, lockShutdown); |
| 191 | if (!lockShutdown) |
| 192 | return; |
| 193 | |
| 194 | /// Note: Shutdown() must be able to handle cases in which initialization failed part of the way, |
| 195 | /// for example if the data directory was found to be locked. |
| 196 | /// Be sure that anything that writes files or flushes caches only does this if the respective |
| 197 | /// module was initialized. |
| 198 | RenameThread("bitcoin-shutoff"); |
| 199 | mempool.AddTransactionsUpdated(1); |
| 200 | |
| 201 | StopHTTPRPC(); |
| 202 | StopREST(); |
| 203 | StopRPC(); |
| 204 | StopHTTPServer(); |
| 205 | g_wallet_init_interface.Flush(); |
| 206 | StopMapPort(); |
| 207 | |
| 208 | // Because these depend on each-other, we make sure that neither can be |
| 209 | // using the other before destroying them. |
| 210 | if (peerLogic) UnregisterValidationInterface(peerLogic.get()); |
| 211 | if (g_connman) g_connman->Stop(); |
| 212 | if (g_txindex) g_txindex->Stop(); |
| 213 | |
| 214 | StopTorControl(); |
| 215 | |
| 216 | // After everything has been shut down, but before things get flushed, stop the |
| 217 | // CScheduler/checkqueue threadGroup |
| 218 | threadGroup.interrupt_all(); |
| 219 | threadGroup.join_all(); |
| 220 | |
| 221 | // After the threads that potentially access these pointers have been stopped, |
| 222 | // destruct and reset all to nullptr. |
| 223 | peerLogic.reset(); |
| 224 | g_connman.reset(); |
| 225 | g_txindex.reset(); |
| 226 | |
| 227 | if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { |
| 228 | DumpMempool(); |
| 229 | } |
| 230 | |
| 231 | if (fFeeEstimatesInitialized) |
| 232 | { |
| 233 | ::feeEstimator.FlushUnconfirmed(); |
| 234 | fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; |
| 235 | CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION); |
| 236 | if (!est_fileout.IsNull()) |
| 237 | ::feeEstimator.Write(est_fileout); |
| 238 | else |
| 239 | LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string()); |
| 240 | fFeeEstimatesInitialized = false; |
| 241 | } |
| 242 | |
| 243 | // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing |
no test coverage detected