upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main_gui.cpp
diff options
context:
space:
mode:
authorBitflash <admin@bitflash.network>2026-08-07 18:40:19 -0300
committerBitflash <admin@bitflash.network>2026-08-07 18:40:19 -0300
commit534cdc2675378a1213b4999fbd6b03f6f0b6ffbc (patch)
treec607f9b16e3d5bd455c410437180e605f6137b97 /src/main_gui.cpp
parentb1eb8b66b8d7b47c7fb2e85d5d4db86a11823366 (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.cpp39
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.)
376static volatile bool g_fHeadlessShutdownDone = false;
377static 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
366int main(int argc, char* argv[]) 396int 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