Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Objective-C函数中捕获Ctrl-C信号?_Objective C_Objective C Runtime - Fatal编程技术网

如何在Objective-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命令无法使用,因为我

我的程序有一个主功能,它将执行一系列测试,其中包括一些在用户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;
}
#导入
无效信号发生器(内部信号){
//正如@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-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;
}
#导入
无效信号发生器(内部信号){
//正如@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()?但是要多久?“这安全吗?”弗兰克乔说,这真的没关系;很短就可以了。目标是退出信号处理程序,因为您不知道启动处理程序时的运行时状态。从处理程序返回后,运行时状态将变得可预测。根据要完成的工作,可以使用全局异步队列。如果您只需要执行主线程工作,那么在主队列上安排它,它将在运行循环的下一次传递中被处理。