diff options
Diffstat (limited to 'src')
| -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 | ||