如何在 Objective-C 函数中捕获 Ctrl-C 信号?
How to catch Ctrl-C signal inside an Objective-C function?
我的程序有一个主要功能,将执行一系列测试,其中将包括一些需要在用户 Ctrl-C 时终止的进程。
以下代码是正确的工作流程
- (void)run {
[process1 start];
[process2 start];
Running...
[process1 stop];
[process2 stop];
}
但是用户可能会使用 Ctrl-C 来停止我的程序,我不想离开 process1 和 process2 运行 因为它们很危险。如何正确阻止它们? Kill
命令无法使用,因为我不知道动态进程名称,唯一的方法是在这两个 ObjC 对象上调用 stop
。
从技术上讲,在您的 Objective-C 方法中您无法捕获 SIGINT
信号(由用户在按下 CTRL-C 时生成)- 您的程序会 中断 .
此时的流程控制由内核处理。在执行 objective-c run
方法期间有效的 cpu 寄存器状态不可避免地会丢失。因此你不能继续执行你的run
方法了。
您可以做的是使用 C API.
注册自定义 SIGINT
处理程序
#import <signal.h>
void sigHandler(int sig) {
//as noted by @bbum list of functions with guaranteed behavior in sighandler is very limited
//obj-c runtime is definitely NOT on the list
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[process1 stop];
[process2 stop];
});
//give extra time for the async part to run
usleep(50);
}
int main(int argc, const char * argv[]) {
signal(SIGINT, sigHandler);
@autoreleasepool {
//your normal program launch goes here
}
return 0;
}
如果你有一个控制台应用程序,你可以考虑路由 here
所以基本上禁用 CTRL-C 触发 SIGINT
并自己异步处理 CTRL-C 的键盘读取。主要的缺点是如果你的程序会遇到无限循环,它不能用 CTRL-C 中断。因此,为了尽量减少这种影响,您可以在 run
方法的开头设置这种特殊的终端模式,并在完成后恢复它。
我的程序有一个主要功能,将执行一系列测试,其中将包括一些需要在用户 Ctrl-C 时终止的进程。
以下代码是正确的工作流程
- (void)run {
[process1 start];
[process2 start];
Running...
[process1 stop];
[process2 stop];
}
但是用户可能会使用 Ctrl-C 来停止我的程序,我不想离开 process1 和 process2 运行 因为它们很危险。如何正确阻止它们? Kill
命令无法使用,因为我不知道动态进程名称,唯一的方法是在这两个 ObjC 对象上调用 stop
。
从技术上讲,在您的 Objective-C 方法中您无法捕获 SIGINT
信号(由用户在按下 CTRL-C 时生成)- 您的程序会 中断 .
此时的流程控制由内核处理。在执行 objective-c run
方法期间有效的 cpu 寄存器状态不可避免地会丢失。因此你不能继续执行你的run
方法了。
您可以做的是使用 C API.
注册自定义SIGINT
处理程序
#import <signal.h>
void sigHandler(int sig) {
//as noted by @bbum list of functions with guaranteed behavior in sighandler is very limited
//obj-c runtime is definitely NOT on the list
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[process1 stop];
[process2 stop];
});
//give extra time for the async part to run
usleep(50);
}
int main(int argc, const char * argv[]) {
signal(SIGINT, sigHandler);
@autoreleasepool {
//your normal program launch goes here
}
return 0;
}
如果你有一个控制台应用程序,你可以考虑路由 here
所以基本上禁用 CTRL-C 触发 SIGINT
并自己异步处理 CTRL-C 的键盘读取。主要的缺点是如果你的程序会遇到无限循环,它不能用 CTRL-C 中断。因此,为了尽量减少这种影响,您可以在 run
方法的开头设置这种特殊的终端模式,并在完成后恢复它。