如何在Objective-C函数中捕获Ctrl-C信号?
我的程序有一个主功能,它将执行一系列测试,其中包括一些在用户Ctrl-C时需要终止的进程 以下代码是正确的工作流如何在Objective-C函数中捕获Ctrl-C信号?,objective-c,objective-c-runtime,Objective C,Objective C Runtime,我的程序有一个主功能,它将执行一系列测试,其中包括一些在用户Ctrl-C时需要终止的进程 以下代码是正确的工作流 - (void)run { [process1 start]; [process2 start]; Running... [process1 stop]; [process2 stop]; } 但是用户可以使用Ctrl-C停止我的程序,我不想让process1和process2继续运行,因为它们很危险。怎样才能正确地阻止他们Kill命令无法使用,因为我
- (void)run {
[process1 start];
[process2 start];
Running...
[process1 stop];
[process2 stop];
}
但是用户可以使用Ctrl-C停止我的程序,我不想让process1和process2继续运行,因为它们很危险。怎样才能正确地阻止他们
Kill
命令无法使用,因为我不知道动态进程名称,唯一的方法是对这两个ObjC对象调用stop
。从技术上讲,在Objective-C方法中,您无法捕捉到SIGINT
信号(由用户按CTRL-C时生成)-您的程序被中断。
此时的流控制由内核处理。执行objective-crun
方法期间有效的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;
}
#导入
无效信号发生器(内部信号){
//正如@bbum所指出的,sighandler中具有保证行为的函数列表非常有限
//obj-c运行时肯定不在列表中
调度异步(调度获取全局队列(调度队列优先级默认为0),^(无效){
[进程1停止];
[进程2停止];
});
//为异步部分提供额外的运行时间
usleep(50);
}
int main(int argc,const char*argv[]{
信号(SIGINT、sigHandler);
@自动释放池{
//你的正常程序启动在这里
}
返回0;
}
如果你有一个控制台应用程序,你可以考虑路由。
所以基本上禁用CTRL-C触发
SIGINT
,并自己异步处理CTRL-C的键盘读取。主要缺点是,如果您的程序将遇到无休止的循环,则不能使用CTRL-C中断。因此,为了最大限度地减少这种影响,您可以在run
方法开始时设置此特殊的终端模式,并在完成后将其还原 从技术上讲,在Objective-C方法中,您无法捕捉到SIGINT
信号(由用户按CTRL-C生成)-您的程序被中断。
此时的流控制由内核处理。执行objective-crun
方法期间有效的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;
}
#导入
无效信号发生器(内部信号){
//正如@bbum所指出的,sighandler中具有保证行为的函数列表非常有限
//obj-c运行时肯定不在列表中
调度异步(调度获取全局队列(调度队列优先级默认为0),^(无效){
[进程1停止];
[进程2停止];
});
//为异步部分提供额外的运行时间
usleep(50);
}
int main(int argc,const char*argv[]{
信号(SIGINT、sigHandler);
@自动释放池{
//你的正常程序启动在这里
}
返回0;
}
如果你有一个控制台应用程序,你可以考虑路由。
所以基本上禁用CTRL-C触发
SIGINT
,并自己异步处理CTRL-C的键盘读取。主要缺点是,如果您的程序将遇到无休止的循环,则不能使用CTRL-C中断。因此,为了最大限度地减少这种影响,您可以在run
方法开始时设置此特殊的终端模式,并在完成后将其还原 您根本不想在该信号处理程序中运行任何代码,当然也不想在objc中运行。相反,使用dispatch_after()在队列上调度块。尽早离开信号处理器。根本的问题是,在启动处理程序时,运行时状态是不确定的。Greg Parker在这里详细介绍:@bbum感谢您的输入。我还发现:我认为在进程终止之前,在运行sighandler
的线程中留出额外的时间是有意义的。@bbum所以我应该在sighandler中调用dispatch\u after()?但是要多久?“这安全吗?”弗兰克乔说,这真的没关系;很短就可以了。目标是退出信号处理程序,因为您不知道启动处理程序时的运行时状态。从处理程序返回后,运行时状态将变得可预测。根据要完成的工作,可以使用全局异步队列。如果您只需要执行主线程工作,请在主队列上安排它,它将在下一次通过运行循环时进行处理。您根本不希望在该信号处理程序中运行任何代码,当然也不希望在objc中运行任何代码。相反,使用dispatch_after()在队列上调度块。尽早离开信号处理器。根本的问题是,在启动处理程序时,运行时状态是不确定的。Greg Parker在这里详细介绍:@bbum感谢您的输入。我还发现:我认为在进程终止之前,在运行sighandler
的线程中留出额外的时间是有意义的。@bbum所以我应该在sighandler中调用dispatch\u after()?但是要多久?“这安全吗?”弗兰克乔说,这真的没关系;很短就可以了。目标是退出信号处理程序,因为您不知道启动处理程序时的运行时状态。从处理程序返回后,运行时状态将变得可预测。根据要完成的工作,可以使用全局异步队列。如果您只需要执行主线程工作,那么在主队列上安排它,它将在运行循环的下一次传递中被处理。