栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在可可macOS应用程序中陷阱SIGINT

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在可可macOS应用程序中陷阱SIGINT

Charles的回答是正确的,但是他的警告(“确保仅从处理程序中调用可重入函数”)是一个极端的限制。使用

kqueue
和可以将信号处理重定向到更安全的环境
CFFileDescriptor

TN2050技术说明:在没有轮询的情况下观察过程寿命是另一个主题,但它说明了该技术。苹果在那里以这种方式描述了查尔斯的警告:

监听信号可能很棘手,因为与信号处理程序关联的执行环境很古怪。具体来说,如果您安装了信号处理程序(使用signal或sigaction),则必须非常小心在该处理程序中执行的操作。从信号处理程序调用的函数很少。例如,使用

malloc
!分配内存是不安全的。

sigaction手册页上列出了可从信号处理程序中 安全使用的 功能(
异步信号安全 功能)。

在大多数情况下,您必须采取额外的步骤将传入的信号重定向到更合理的环境。

我从那里获取了代码说明,并对其进行了修改以进行处理

SIGINT
。抱歉,是Objective-C。这是一次性设置代码:

// Ignore SIGINT so it doesn't terminate the process.signal(SIGINT, SIG_IGN);// Create the kqueue and set it up to watch for SIGINT. Use the // EV_RECEIPT flag to ensure that we get what we expect.int kq = kqueue();struct kevent changes;EV_SET(&changes, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL);(void) kevent(kq, &changes, 1, &changes, 1, NULL);// Wrap the kqueue in a CFFileDescriptor. Then create a run-loop source// from the CFFileDescriptor and add that to the runloop.CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL };CFFileDescriptorRef kqRef = CFFileDescriptorCreate(NULL, kq, true, sigint_handler, &context);CFRunLoopSourceRef rls = CFFileDescriptorCreateRunLoopSource(NULL, kqRef, 0);CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);CFRelease(rls);CFFileDescriptorEnableCallBacks(kqRef, kCFFileDescriptorReadCallBack);CFRelease(kqRef);

这是实现

sigint_handler
上面引用的回调的方法:

static void sigint_handler(CFFileDescriptorRef f,  CFOptionFlags callBackTypes, void *info){    struct kevent event;    (void) kevent(CFFileDescriptorGetNativeDescriptor(f), NULL, 0, &event, 1, NULL);    CFFileDescriptorEnableCallBacks(f, kCFFileDescriptorReadCallBack);    // You've been notified!}

请注意,此技术要求您在有兴趣处理

SIGINT
(也许是应用程序的生命周期)并维护/运行其运行循环的线程上运行安装代码。系统出于自身目的创建的线程(例如,服务于Grand
Central Dispatch队列的线程) 适合此目的。

该应用程序的主线程将正常工作,您可以使用它。 但是
,如果主线程锁定或变得无响应,则它不为运行循环提供服务,并且

SIGINT
不会调用处理程序。由于
SIGINT
经常用于恰好中断这种卡住的过程,因此主线程可能不适合。

因此,您可能想产生一个自己的线程只是为了监视此信号。它不应该做任何其他事情,因为其他任何事情也可能导致它卡住。即使在那里,也存在问题。您的处理程序函数将在您的该后台线程上被调用,并且主线程可能仍被锁定。在系统库中,有很多东西仅是主线程的,您将无能为力。但是,与POSIX样式的信号处理程序相比,您将拥有更大的灵活性。

我应该补充一点,GCD的调度源也可以监视UNIX信号,并且更易于使用,尤其是从Swift中。但是,它们不会预先创建运行该处理程序的专用线程。该处理程序将被提交到队列。现在,您可以指定一个高优先级/高QOS队列,但是我不确定如果该进程有多个运行中的失控线程正在运行,则该处理程序将运行。也就是说,实际上在高优先级队列上运行的任务将优先于低优先级线程或队列,但是启动新任务可能不会。我不确定。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/383405.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号