【发布时间】:2019-06-19 03:16:13
【问题描述】:
假设我们有一个用 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,而不是通过进程kill强制终止。
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”并继续工作。
谢谢
【问题讨论】:
-
@eryksun 谢谢!答案的关键是
create a new thread in each attached process- 在这种情况下,很清楚进程终止如何以异步方式执行。
标签: c++ windows cmd signals windows-console