在Cocoa应用程序退出之前确保Objective-C代码执行

pje*_*pje 5 macos cocoa exception-handling objective-c

假设cocoa应用程序必须在退出之前执行一些非常重要的objective-c操作(出于任何原因 - 崩溃或退出).

是否可以确保执行任意Objective-c代码以响应每个崩溃事件?(SIGINT,SIGBUS,SIGSEGV等,忽略了"uncatchables"( ,SIGSTOP,SIGKILL闪电的螺栓等))


知道你的钩子试图做什么会很有帮助.

例如:假设要让应用程序运行,它绝对必须更改某个可变系统范围配置变量X的值.在启动时,应用程序会获取X当前状态的快照,然后对其进行修改.当应用程序成功退出时,它只会在终止之前将X恢复为隐藏的原始值.我的问题是:即使应用程序崩溃,是否可以确保X得到恢复?

bbu*_*bum 6

不,没有办法保证任何给定的代码片段将在应用程序终止时执行,因为用户可能以应用程序无法捕获的方式终止应用程序(例如,拔掉桌面上的插件机).

您的代码绝对必须加强以防意外终止.

你需要多少硬化它取决于你的应用程序.在基于文档的应用程序中(在现代自动保存 - 频繁模型之前),在上次保存之后丢失数据是预期的(并且令人讨厌).

对于您的应用,您需要平衡持久性成本与持久数据的价值.


我只对可以捕获的终止信号感兴趣.

"可以捕获"和"可以做任何有用的事情"之间存在差异.正如您所指出的,可以捕获大量信号.

但是,你真的无法在信号处理程序中做任何事情.从技术上讲,你甚至无法分配内存.

同样,通常会生成信号或异常,因为应用程序已进入未定义的,灾难性的损坏状态.因此,您不能指望应用程序中的任何内部状态可用.

我已经看到很多情况,当崩溃发生时,应用程序将尝试保存用户状态,只是非常愉快地写入最终导致用户丢失更多数据的损坏状态.

知道你的钩子试图做什么会很有帮助.


有关更多信息,请参见sigaction手册页.

具体来说,可以安全调用的函数列表包括_exit(),access(),alarm(),cfgetispeed(),cfgetospeed(),cfsetispeed(),cfsetospeed(),chdir(),chmod(),chown( ),close(),creat(),dup(),dup2(),execle(),execve(),fcntl(),fork(),fpathconf(),fstat(),fsync(),getegid(), geteuid(),getgid(),getgroups(),getpgrp(),getpid(),getppid(),getuid(),kill(),link(),lseek(),mkdir(),mkfifo(),open( ),pathconf(),pause(),pipe(),raise(),read(),rename(),rmdir(),setgid(),setpgid(),setsid(),setuid(),sigaction(), sigaddset(),sigdelset(),sigemptyset(),sigfillset(),sigismember(),signal(),sigpending(),sigprocmask(),sigsuspend(),sleep(),stat(),sysconf(),tcdrain( ),tcflow(),tcflush(),tcgetattr(),tcgetpgrp(),tcsendbreak(),tcsetattr(),tcsetpgrp(),time(),times(),umask(),uname(),unlink(), utime(),wait(),waitpid(),write(),aio_error(),sigpause(),aio_return(),aio_suspend(),sem_post(),sigset(),strcpy(),strcat(),strncpy( ),strncat(),strlcpy()和strlcat().

不在上述列表中的所有功能被认为对于信号是不安全的.也就是说,从信号处理程序调用时这些函数的行为是未定义的.一般来说,信号处理程序应该只设置一个标志; 大多数其他行动都不安全.

翻译:你真的无法在信号处理程序中做任何有用的事情.

Mpte a; sp tjat sogma; ,au ne de; overed pm amu tjread amd,ogjt ne de; overed nu打断当前正在执行的功能.

我打算键入的内容:请记住,信号处理程序可能在随机线程上传递,也可能会中断当前正在执行的函数.即你的应用程序的状态可能有点不确定.

  • pje:问题是malloc在许多情况下都会锁定,所以如果你的信号处理程序在持有锁时中断了一个已经在进行中的malloc,那么任何分配的尝试都会死锁. (3认同)
  • 很有趣的是弄清楚最后一句话应该读什么. (2认同)

CRD*_*CRD 3

最简洁的答案是不。

更长的答案仍然是“否”,但是您可以最大限度地减少无法重置系统范围可变配置变量的机会。概要:

  • 启动时让您的应用程序生成一个不露面的后台进程;
  • 不露面的后台进程应该改变你的变量,然后等待(如wait(2)&friends)直到它的父进程过期;
  • 在其父级到期时,它会重置变量,然后自行到期。

您的匿名后台应用程序应该简短,因此希望很强大。这远非万无一失,也不是对那些有杀婴念头的用户安全的,但它缩小了阻止变量重置的机会。