混合线程,叉子和互斥体,我应该注意什么?

Omn*_*ous 7 multithreading mutex fork

如果我fork是一个线程持有互斥锁的进程,如果我立刻exec在孩子身上,我相对安全吗?在我之前,孩子们可以做些什么事情exec

如果执行的线程fork然后子进程在调用之前继续释放互斥锁exec会导致问题吗?如果我尝试获取父进程之前拥有的子进程fork(并且可能或可能仍然拥有)的子进程,会发生什么?

不同平台上的答案有何不同?我主要关注的是Unix变体,特别是Linux.但我对NT感到好奇.当然,虽然NT(据我所知)没有fork.

Ant*_*nko 6

有关多线程环境中与之相关的问题的讨论,请参阅pthread_atfork,尤其是RATIONALE部分fork.它还提示了在fork孩子和父母之前和之后应该有效的内容.

更新:理论部分是非规范性的,结果证明与标准的其他部分相冲突.有关详细信息,请参阅Dave Butenhof的此缺陷报告.

立即exec之后fork应该是对多线程程序的任何国家安全(即持有的所有互斥锁的线程).由于之间可能存在的东西forkexec,情况是复杂的:

最重要的是fork在子进程中只复制一个线程(被调用的线程).因此,当前另一个线程持有的任何互斥fork锁都会永久锁定.这是(假设非进程共享的互斥锁)其子进程中的副本永远被锁定,因为没有线程可以解锁它.

fork在可能的情况下释放互斥锁是安全的,也就是说,如果forking线程首先拥有互斥锁.这就是pthread_atfork处理程序通常的工作方式:锁定互斥锁之前fork,解锁子级解锁父级.

获取一个在fork之前拥有进程的互斥锁(记住,我们在子地址空间中讨论一个副本):如果它由一个ing线程拥有fork,那么它是递归锁定(适用于PTHREAD_MUTEX_RECURSIVE); 如果它由另一个线程拥有,它将永远保持锁定状态,无法重新获取.

通过注册适当的pthread_atfork处理程序,第三方库可以保证在fork和之间安全使用exec.(我希望它主要来自编程语言运行时,而不是通用库).


一些研究之后,我会建议避免依赖任何方式pthread_atfork,无所事事,但异步信号安全的调用之间forkexec(放弃fork/ execposix_spawn会更好).

问题是,fork本身可以在信号处理程序中调用.它排除了任何重要的使用pthread_atfork,即使它的RATIONALE明确提到解锁互斥锁并在子进程中重新创建线程(!).

我认为不同可能解释的"灰色地带"仍然存在:

  1. 对于pthread_atfork其中的程序处理程序称为永远不会调用fork一个信号处理程序.
  2. 对于不在信号处理程序中的fork调用周围发生的非pthread-atfork操作.

但很清楚哪种读数将用于便携式应用.