diff options
| author | Bitflash <admin@bitflash.network> | 2026-08-07 18:40:19 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-07 18:40:19 -0300 |
| commit | 534cdc2675378a1213b4999fbd6b03f6f0b6ffbc (patch) | |
| tree | c607f9b16e3d5bd455c410437180e605f6137b97 /src/main_gui.cpp | |
| parent | b1eb8b66b8d7b47c7fb2e85d5d4db86a11823366 (diff) | |
shutdown: flush wallet.dat on Windows headless stop
The headless loop installed SIGINT/SIGTERM handlers only under #ifndef _WIN32,
so a headless node on Windows never reached the clean StopNode()+DBFlush() path:
Ctrl-C, closing the console window, a service stop and OS shutdown all killed it
mid-write, and a Berkeley DB wallet.dat left unflushed will not reopen.
Install a SetConsoleCtrlHandler that mirrors the POSIX path: set fShutdown and,
because the OS terminates us shortly after the handler returns on
CLOSE/LOGOFF/SHUTDOWN, block until the main loop signals the flush is done.
A 'taskkill /F' is still an uncatchable hard kill by design.
Closes #16.
Diffstat (limited to 'src/main_gui.cpp')
| -rw-r--r-- | src/main_gui.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 7ad2075..b036ac9 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -363,6 +363,36 @@ static void FatalStartupError(bool fHeadless, const string& strWhat, const strin | |||
| 363 | #endif | 363 | #endif |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | #ifdef _WIN32 | ||
| 367 | // Windows equivalent of the SIGINT/SIGTERM handler the headless loop installs on | ||
| 368 | // POSIX. Without it a headless node on Windows had no way to reach the clean | ||
| 369 | // StopNode()+DBFlush() path: Ctrl-C, closing the console window, a service stop | ||
| 370 | // and OS shutdown all killed it mid-write, and a wallet.dat left unflushed by | ||
| 371 | // Berkeley DB will not reopen. For CLOSE/LOGOFF/SHUTDOWN the OS terminates us | ||
| 372 | // shortly after the handler returns, so we set fShutdown and then block until the | ||
| 373 | // main loop signals the flush is done -- returning any sooner throws the flush | ||
| 374 | // away, which is the whole bug. (A `taskkill /F` is still an uncatchable hard | ||
| 375 | // kill; nothing can help there, and nothing should pretend to.) | ||
| 376 | static volatile bool g_fHeadlessShutdownDone = false; | ||
| 377 | static BOOL WINAPI HeadlessConsoleCtrlHandler(DWORD dwCtrlType) | ||
| 378 | { | ||
| 379 | switch (dwCtrlType) | ||
| 380 | { | ||
| 381 | case CTRL_C_EVENT: | ||
| 382 | case CTRL_BREAK_EVENT: | ||
| 383 | case CTRL_CLOSE_EVENT: | ||
| 384 | case CTRL_LOGOFF_EVENT: | ||
| 385 | case CTRL_SHUTDOWN_EVENT: | ||
| 386 | fShutdown = true; | ||
| 387 | while (!g_fHeadlessShutdownDone) | ||
| 388 | Sleep(50); | ||
| 389 | return TRUE; | ||
| 390 | default: | ||
| 391 | return FALSE; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | #endif | ||
| 395 | |||
| 366 | int main(int argc, char* argv[]) | 396 | int main(int argc, char* argv[]) |
| 367 | { | 397 | { |
| 368 | if (arg(argc,argv,"/help") || arg(argc,argv,"-help") || | 398 | if (arg(argc,argv,"/help") || arg(argc,argv,"-help") || |
| @@ -662,7 +692,9 @@ int main(int argc, char* argv[]) | |||
| 662 | #endif | 692 | #endif |
| 663 | 693 | ||
| 664 | if (fHeadless) { | 694 | if (fHeadless) { |
| 665 | #ifndef _WIN32 | 695 | #ifdef _WIN32 |
| 696 | SetConsoleCtrlHandler(HeadlessConsoleCtrlHandler, TRUE); | ||
| 697 | #else | ||
| 666 | auto sig=[](int){fShutdown=true;}; | 698 | auto sig=[](int){fShutdown=true;}; |
| 667 | signal(SIGINT,sig); signal(SIGTERM,sig); | 699 | signal(SIGINT,sig); signal(SIGTERM,sig); |
| 668 | #endif | 700 | #endif |
| @@ -674,6 +706,11 @@ int main(int argc, char* argv[]) | |||
| 674 | // called here, which is why a wallet.dat copied elsewhere would not | 706 | // called here, which is why a wallet.dat copied elsewhere would not |
| 675 | // open -- issue #40. Not optional. | 707 | // open -- issue #40. Not optional. |
| 676 | DBFlush(true); | 708 | DBFlush(true); |
| 709 | #ifdef _WIN32 | ||
| 710 | // wallet.dat is safely flushed and closed now; let a pending console | ||
| 711 | // control handler (CLOSE/LOGOFF/SHUTDOWN) return so the OS can finish. | ||
| 712 | g_fHeadlessShutdownDone = true; | ||
| 713 | #endif | ||
| 677 | return 0; | 714 | return 0; |
| 678 | } | 715 | } |
| 679 | 716 | ||