C fork(应该)在线程程序中不受信号处理程序的影响吗?
我真的不确定POSIX在线程和信号存在的情况下对C fork(应该)在线程程序中不受信号处理程序的影响吗?,c,pthreads,deadlock,fork,signals,C,Pthreads,Deadlock,Fork,Signals,我真的不确定POSIX在线程和信号存在的情况下对fork安全性的要求fork被列为异步信号安全函数之一,但如果库代码可能已注册了非异步信号安全的pthread\u atfork处理程序,这是否会否定fork的安全性?答案是否取决于信号处理程序运行的线程是否在使用AtDoc处理程序所需的资源的中间?或者用另一种方式说,如果atfork处理程序使用同步资源(互斥体等),但是fork是从一个信号处理程序调用的,该信号处理程序在一个从未访问这些资源的线程中执行,那么该程序符合要求吗 基于这个问题,如果使
fork
安全性的要求fork
被列为异步信号安全函数之一,但如果库代码可能已注册了非异步信号安全的pthread\u atfork
处理程序,这是否会否定fork
的安全性?答案是否取决于信号处理程序运行的线程是否在使用AtDoc处理程序所需的资源的中间?或者用另一种方式说,如果atfork处理程序使用同步资源(互斥体等),但是fork
是从一个信号处理程序调用的,该信号处理程序在一个从未访问这些资源的线程中执行,那么该程序符合要求吗
基于这个问题,如果使用pthread_atfork
建议的惯用法在系统库内部实现“线程安全”分叉(获取prefork处理程序中的所有锁,并释放父和子postfork处理程序中的所有锁),那么,在线程程序中从信号处理程序使用fork是否安全?不可能处理信号的线程是否在调用<代码> MALLC/<代码>或<代码> fOpen< /COD> >代码> fCXS/<代码>,并持有全局锁,导致在<代码> For < /C> >死锁>
最后,即使在信号处理程序中fork
是安全的,在信号处理程序中fork
然后从信号处理程序返回是否安全,或者在信号处理程序中调用fork
是否总是需要在信号处理程序返回之前调用\u exit
或exec
函数族中的一个?在信号处理程序中使用fork()应该可以
pthread_atfork听起来是个坏主意
为了回答您最初的问题,pthread无法保证调用任何pthread_atfork函数的安全性是异步信号安全的,因为内核的信号实现使得这一点不可能实现
哦,如果您在信号处理程序中分叉,则不允许子级从信号处理程序返回。这是未定义的。据我所知,它使用信号状态临界部分来确保分叉过程不会被信号中断
ss = _hurd_self_sigstate ();
__spin_lock (&ss->critical_section_lock);
作为在关键段锁定后执行的pthread\u atfork
处理程序,它们会自动成为信号安全的
也许我错了,我会感谢你的更正。这里
fork被列为异步信号安全型,因此可以使用它
POSIX
下表将从“打开”菜单中删除
组基本规范[开放组
定义了一组函数,这些函数
异步信号是安全的。
应用程序可以调用这些
功能,不受限制,来自
信号处理器
异步信号安全功能
fork()
尽我所能回答所有的子问题;我很抱歉,其中有些内容比理想情况下更模糊: 如果有 库代码具有 已注册的pthread_atfork处理程序 不是异步信号安全的,是吗 这否定了叉子的安全性 对。报告明确提到这一点:
When the application calls fork() from a signal handler and any of the
fork handlers registered by pthread_atfork() calls a function that is
not asynch-signal-safe, the behavior is undefined.
当然,这意味着您不能实际使用pthread_atfork()
来达到使多线程库对相信它们是单线程的进程透明的目的,因为pthread同步函数都不是异步信号安全的;这是规范中的一个缺陷,请参见(搜索“L16723”)
做
答案取决于
执行信号处理程序的线程
跑步可能在中间。
使用atfork支持的资源
你需要什么?或者说另一种说法
如果atfork处理程序使用
同步资源(互斥体,
等等),但fork是从
在
从不访问这些文件的线程
资源,程序是否符合要求
严格地说,答案是否定的,因为根据规范,函数要么是异步信号安全的,要么不是;没有“在某些情况下安全”的概念。在实践中,您可能会侥幸逃脱,但您很容易受到笨重但正确的实现的攻击,该实现没有按照您期望的方式对其资源进行分区
基于这个问题,如果
实现了“线程安全”分叉
在系统库内部使用
pthread_atfork建议的习语
(获取预工作中的所有锁
处理程序并释放两个中的所有锁
父和子postfork
那么fork对你来说安全吗
从线程中的信号处理程序使用
节目?难道这不可能吗
处理信号的线程可能处于
调用malloc或
fopen/fclose和举行全球会议
锁定,导致进程中出现死锁
叉子
如果它是以这种方式实现的,那么您是对的,来自信号处理程序的fork()
将永远不会安全,因为如果调用线程已经持有锁,尝试获取锁可能会死锁。但这意味着使用这种方法的实现将不符合要求
以glibc为例,它并没有做到这一点——相反,它采取了两种方法:首先,它确实获得的锁是递归的(因此,如果当前线程已经拥有它们,它们的锁计数将简单地增加);此外,在子进程中,它只是单方面地覆盖所有锁—请参阅nptl/sysdeps/unix/sysv/linux/fork.c
中的摘录:
/* Reset the file list. These are recursive mutexes. */
fresetlockfiles ();
/* Reset locks in the I/O code. */
_IO_list_resetlock ();
/* Reset the lock the dynamic loader uses to protect its data. */
__rtld_lock_initialize (GL(dl_load_lock));
其中,resetlock
和lock\u initialize
函数最终调用glibc的内部等价物pthread\u mutex\u init()
,有效地重置互斥体,而不考虑任何等待者
我认为理论是,由奥塔尼