* Console interrupt handler --- runs in a newly-started thread. * * After stopping other threads and sending cancel requests on all open * connections, we return FALSE which will allow the default ExitProcess() * action to be taken. */
| 636 | * action to be taken. |
| 637 | */ |
| 638 | static BOOL WINAPI |
| 639 | consoleHandler(DWORD dwCtrlType) |
| 640 | { |
| 641 | int i; |
| 642 | char errbuf[1]; |
| 643 | |
| 644 | if (dwCtrlType == CTRL_C_EVENT || |
| 645 | dwCtrlType == CTRL_BREAK_EVENT) |
| 646 | { |
| 647 | /* Critical section prevents changing data we look at here */ |
| 648 | EnterCriticalSection(&signal_info_lock); |
| 649 | |
| 650 | /* |
| 651 | * If in parallel mode, stop worker threads and send QueryCancel to |
| 652 | * their connected backends. The main point of stopping the worker |
| 653 | * threads is to keep them from reporting the query cancels as errors, |
| 654 | * which would clutter the user's screen. We needn't stop the leader |
| 655 | * thread since it won't be doing much anyway. Do this before |
| 656 | * canceling the main transaction, else we might get invalid-snapshot |
| 657 | * errors reported before we can stop the workers. Ignore errors, |
| 658 | * there's not much we can do about them anyway. |
| 659 | */ |
| 660 | if (signal_info.pstate != NULL) |
| 661 | { |
| 662 | for (i = 0; i < signal_info.pstate->numWorkers; i++) |
| 663 | { |
| 664 | ParallelSlot *slot = &(signal_info.pstate->parallelSlot[i]); |
| 665 | ArchiveHandle *AH = slot->AH; |
| 666 | HANDLE hThread = (HANDLE) slot->hThread; |
| 667 | |
| 668 | /* |
| 669 | * Using TerminateThread here may leave some resources leaked, |
| 670 | * but it doesn't matter since we're about to end the whole |
| 671 | * process. |
| 672 | */ |
| 673 | if (hThread != INVALID_HANDLE_VALUE) |
| 674 | TerminateThread(hThread, 0); |
| 675 | |
| 676 | if (AH != NULL && AH->connCancel != NULL) |
| 677 | (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf)); |
| 678 | } |
| 679 | } |
| 680 | |
| 681 | /* |
| 682 | * Send QueryCancel to leader connection, if enabled. Ignore errors, |
| 683 | * there's not much we can do about them anyway. |
| 684 | */ |
| 685 | if (signal_info.myAH != NULL && signal_info.myAH->connCancel != NULL) |
| 686 | (void) PQcancel(signal_info.myAH->connCancel, |
| 687 | errbuf, sizeof(errbuf)); |
| 688 | |
| 689 | LeaveCriticalSection(&signal_info_lock); |
| 690 | |
| 691 | /* |
| 692 | * Report we're quitting, using nothing more complicated than |
| 693 | * write(2). (We might be able to get away with using pg_log_*() |
| 694 | * here, but since we terminated other threads uncleanly above, it |
| 695 | * seems better to assume as little as possible.) |
nothing calls this directly
no test coverage detected