【问题标题】:How to catch Ctrl-C signal inside an Objective-C function? [duplicate]如何在 Objective-C 函数中捕获 Ctrl-C 信号? [复制]
【发布时间】:2019-07-26 17:28:42
【问题描述】:

我的程序有一个 main 函数,它将执行一系列测试,其中包括一些需要在用户 Ctrl-C 时终止的进程。

以下代码是正确的工作流程

- (void)run {
   [process1 start];
   [process2 start];
   Running...
   [process1 stop];
   [process2 stop];
}

但是用户可能会使用 Ctrl-C 来停止我的程序,我不想让 process1 和 process2 继续运行,因为它们很危险。如何正确阻止它们? Kill 命令无法使用,因为我不知道动态进程名称,唯一的方法是在这两个 ObjC 对象上调用 stop

【问题讨论】:

    标签: objective-c objective-c-runtime


    【解决方案1】:

    从技术上讲,在您的 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 方法的开头设置此特殊终端模式,并在完成后恢复它。

    【讨论】:

    • 您根本不想在该信号处理程序中运行任何代码,当然也不想在 objc 中运行。相反,使用 dispatch_after() 来调度队列中的块。尽早退出信号处理程序。根本问题是在触发处理程序时运行时状态是不确定的。
    • Greg Parker 在这里详细介绍:stackoverflow.com/questions/24051879/…
    • @bbum 感谢您的意见。我还发现了这一点:stackoverflow.com/questions/25959056/… 我认为在进程终止之前,在运行sighandler 的线程中给予额外的时间是有意义的。
    • @bbum 所以我应该在 sighandler 中调用 dispatch_after() 吗?但是多久?这安全吗?
    • @FrankJoe 真的没关系;非常非常短就可以了。目标是摆脱信号处理程序,因为您不知道处理程序触发时的运行时状态是什么。从处理程序返回后,运行时状态就变得可预测了。根据要完成的工作,全局异步队列就可以了。如果您只需要主线程工作,请将其安排在主队列中,它将在下一次通过运行循环时进行处理。
    猜你喜欢
    • 2019-10-29
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2012-06-18
    • 2010-09-15
    • 2013-05-25
    相关资源
    最近更新 更多