C++ fork()的神秘pthread问题

C++ fork()的神秘pthread问题,c++,posix,pthreads,C++,Posix,Pthreads,我有一个计划: 有一个主线程(1),它启动一个服务器线程(2)和另一个线程(4) 服务器线程(2)执行一个accept(),然后创建一个新线程(3)来处理连接 在某个时刻,线程(4)执行fork/exec来运行另一个程序,该程序应该连接到线程(2)正在侦听的套接字。有时,这会失败或花费不合理的时间,而且诊断起来非常困难。如果我扫描系统,看起来fork/exec已经工作,accept已经发生,新线程(4)已经创建。。但是该线程中没有发生任何事情(使用strace-ff,相关pid的文件为空)

我有一个计划:

  • 有一个主线程(1),它启动一个服务器线程(2)和另一个线程(4)
  • 服务器线程(2)执行一个accept(),然后创建一个新线程(3)来处理连接
在某个时刻,线程(4)执行fork/exec来运行另一个程序,该程序应该连接到线程(2)正在侦听的套接字。有时,这会失败或花费不合理的时间,而且诊断起来非常困难。如果我扫描系统,看起来fork/exec已经工作,accept已经发生,新线程(4)已经创建。。但是该线程中没有发生任何事情(使用strace-ff,相关pid的文件为空)


有什么想法吗?

将代码减小到仍然具有该行为的尽可能小的大小,并将其发布到此处。要么你会找到答案,要么我们就能找到答案

顺便说一句,exec的pthread行为似乎没有得到很好的定义,这可能取决于您的操作系统


在fork和exec之间有代码吗?这可能是个问题。

看起来像是死锁状态。寻找阻塞函数,如accept(),问题应该在那里。

使用多线程和fork时要非常小心。大多数glibc/libstdc++都是线程安全的。如果分叉线程以外的线程在分叉执行时持有锁,分叉进程将继承当前锁定状态下的互斥锁。新进程将永远不会看到这些互斥锁被解锁。有关更多信息,请参见
man pthread_atfork

我得出结论,可能是这种现象:

因为在我们的开发系统上很难触发bug,但通常由在大型共享机器上运行的用户报告;另外,分叉应用程序启动一个JVM,JVM本身分配许多线程。这个问题还与正在加载的机器和大量内存使用有关(我们有一台机器,内存为128Gb,进程大小可能为10-100G)

我一直在阅读O'Reilly pthreads一书,书中解释了pthread_atfork(),并建议在启动时使用从主进程派生的“代理父进程”,从主进程派生子进程。它还建议使用预先创建的线程池。这两个似乎都是好主意,所以我至少要实现其中一个。

我刚刚遇到了同样的问题,最后发现fork()复制了所有线程。现在想象一下,当所有线程都运行双实例时,您的程序在fork()之后会做什么

以下规则来自:

1-你不想那样做

2-如果需要fork(),则: 只要有可能,把你所有的 在开始任何线程之前,先执行childs。


编辑:尝试过,fork()不会复制线程。

该链接似乎描述了没有fork的exec的问题,这可能不是同一回事。fork和exec之间没有太多代码;fork/exec实际上是在一个Tcl解释器中完成的(使用Tcl的“exec…&”),小测试用例可能很难实现,因为我无法在庞大的应用程序中可靠地重现它。如果没有您的代码,可能会有一些代码注入信息分叉。请准备一个最小的示例。>小测试用例可能很难,因为我无法用大型应用程序可靠地重现它。--pjc50:这就是我们调试代码的方式。我们不猜。我们跟踪错误。如果你有两种情况——一种是大的产生错误,另一种是小的不产生错误,那么你就接近找到它了。只需删除大块代码并检查错误是否仍然存在。看看这里,做你的家庭作业,让我们知道问题出在哪里。在创建(2)和(4)之后,你的主线程(1)在做什么?它是永远等待(2)还是直到某种情况出现?(1)去等待键盘输入(使用非常类似于readline的东西),它形成命令,通过锁定队列移交给(4)。这不是真的。fork不会复制所有线程,它只复制调用线程,如下所述: