异常进程终止时的资源清理

Posted

技术标签:

【中文标题】异常进程终止时的资源清理【英文标题】:Resource cleanup on abnormal process termination 【发布时间】:2013-11-09 13:14:59 【问题描述】:

我的问题是,当进程异常终止时(通过信号,它可能是 SIGKILL,因此我们无法拦截它),是否有任何保证释放其资源的顺序或原子性?特别是,我对文件锁和共享内存感兴趣。

例如:

1) 如果进程持有 2 个文件的锁并且异常终止,那么尝试锁定相同文件的另一个进程是否有可能看到一个文件被锁定而另一个文件被解锁?还是从其他进程的角度来看,释放文件锁的过程是原子的?

如果它不是原子的,是否至少有一个预定义的顺序,文件锁将被终止进程释放(例如,以它们最初被锁定的相反顺序)?

2) 我想使用文件锁来确保正确的共享内存初始化 - 映射到共享内存的进程将持有共享锁,并且想要映射到同一共享内存段的新进程将尝试测试该锁查看是否需要执行初始化(如果需要,我可以稍后提供更多详细信息)。

但是这里出现了同样的问题:如果一个持有文件锁并映射到共享内存段的进程异常终止,是否有可能在共享内存自动取消映射后,其他进程仍然会看到文件锁被锁定?还是从其他进程的角度来看,共享内存段的取消映射和文件解锁是原子的?

【问题讨论】:

我不知道,但我敢打赌 #1 中问题的答案是否定的。 你的意思是没有原子性? 我很确定,这取决于实现,例如具有内核抢占的实时内核可能会抢占解锁代码,因为只有解锁本身必须是原子的,而不是解锁多个资源。 【参考方案1】:

正如您的问题所暗示的,这取决于发送到程序的终止信号。 AFIK 实际上只有 KILL(即kill -kill)会终止进程,而不会让进程有机会正确关闭自己。其他信号如 TERM OR SIGINT 可以被程序本身挂钩,要么被忽略,要么用于启动一些干净的关闭过程。 I guess SIGHUP 等最温和的信号不会做任何事情,除非代码中有明确的钩子。所以我不知道你关于文件锁的问题的具体答案,但考虑到你在这里担心的可能只是kill -kill

【讨论】:

UNIX 中的进程无法捕获两个信号:SIGKILL 将终止进程,SIGSTOP 将暂停它(参见 [en.wikipedia.org/wiki/Unix_signal])。默认行为各不相同;例如 SIGQUIT 默认转储内核并终止(有时对调试有用)。 具体来说,这些信号是不可屏蔽的,这是一种俚语,应用程序无法处理它并在应用程序上执行最后仪式(如果有)。 kill 并不意味着杀戮。这意味着发送信号,尽管提到了两个信号,但信号是可以处理的。毕竟可能没有最后的仪式。这取决于程序的作者。【参考方案2】:

不,释放资源没有顺序。只有在进程终止后才会释放锁。

据我了解您的问题,您持有两个或多个相互关联的“锁”。不知何故,您的应用程序取决于锁的确切释放顺序。在不了解您的问题的详细信息的情况下,这似乎只是糟糕的设计

如果文件的锁,依赖于共享内存的锁,你应该以编程方式实现这个依赖。

另一种解决方案就是等待,例如100 毫秒,检查第二个锁。因为你可以假设,被终止进程的所有锁都会在很短的时间内被释放。如果您新启动的应用程序可以获取第一个锁,它将首先等待 100 毫秒,然后再尝试获取文件锁(或相反)。如果进程在此时终止,这会自动避免任何竞争条件

【讨论】:

以上是关于异常进程终止时的资源清理的主要内容,如果未能解决你的问题,请参考以下文章

《Linux应用进程控制 — 特殊的进程》

Oracle部分后台进程

如何清理僵尸进程(转载)

Linux 结束进程

《进程》

Linux 内核进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )