Предположим, у нас есть небольшая программа, написанная на C ++, которая выглядит следующим образом.
Эта программа сама намеренно НЕ выполняет обработку сигналов с помощью вызова WinAPI SetConsoleCtrlHandler
- это важная часть вопроса.
#include <stdio.h>
#include <stdlib.h>
int main() {
while(true) {
int status = system("EXTERNAL COMMAND");
printf("RESULT STATUS = %d\n", status);
}
}
Когда на терминале была нажата комбинация клавиш Ctrl+C
, вышеуказанная программа имеет совершенно другое поведение, в зависимости от того, какой "EXTERNAL COMMAND"
был вызван
1) Если внешняя команда pause
, программа будет стоять в бесконечном цикле, вызывая pause
команду шаг за шагом, и будет печатать "RESULT STATUS = 0" many times
, в то время как не завершена принудительно из-за уничтожения процесса.
2) Если внешняя команда в choice
, программа будет завершена сразу послеCtrl+C
давление.Он ничего не печатает и не возвращает после вызова system
.
3) Если внешняя команда set /P VAR=
, программа имеет много интересного поведения.При нажатии Ctrl+C
программа печатает «RESULT STATUS = 1» и продолжает работать до тех пор, пока не будет выполнен первый асинхронный вызов.
Первый и второй случай можно объяснить следующим образом.Окна терминала - это прокс между пользовательским вводом и целевой программой, поэтому, когда пользователь нажимает Ctrl+C
, окно терминала выполняет сам диспетчерский сигнал для целевого процесса.
Таким образом, некоторые подпроцессы могут вручную обрабатывать обработчик терминала через hConsole = GetStdHandle(STD_OUTPUT_HANDLE)
и выполнять собственную обработку сигналов.Другой подпроцесс не делает этого, поэтому сигнал передается в родительский процесс и завершает его.
Но третий случай вызывает большой вопрос.Если дочерний процесс перехватывает SIGINT
, почему родительский процесс завершает работу после первого асинхронного вызова.Если нет, то почему он не завершается немедленно и почему и как он печатает `" RESULT STATUS = 1 "и продолжает работать.
Спасибо