我有一个程序:

  • 有一个主线程 (1),它启动一个服务器线程 (2) 和另一个线程 (4)。
  • 服务器线程 (2) 执行accept(),然后创建一个新线程 (3) 来处理连接。

在某个时刻,线程 (4) 执行 fork/exec 来运行另一个程序,该程序应连接到线程 (2) 正在侦听的套接字。有时会失败或花费不合理的长时间,并且诊断起来非常困难。如果我跟踪系统,看起来 fork/exec 已经工作,接受已经发生,新线程 (4) 已经创建..但该线程中没有任何反应(使用 strace -ff,相关 pid 的文件为空)。

有任何想法吗?

有帮助吗?

解决方案

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

http://kerneltrap.org/mailarchive/linux-kernel/2008/8/15/2950234/thread

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

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

其他提示

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

将代码减少到仍然具有行为的最小可能大小并将其发布在此处。要么您找到答案,要么我们能够找到答案。

顺便提一句 - http://lists.samba.org/archive/linux/2002-February/002171.html 似乎 exec 的 pthread 行为没有明确定义,可能取决于您的操作系统。

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

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

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

以下规则来自 “关于 fork() 和 Pthreads 的迷你指南”:

1-你不想那样做。

2-如果您需要 fork() 那么:只要可能,请在启动任何线程之前叉()所有孩子。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top