2012-06-03 35 views
2

我有一个C++ pthread线程使用Popen调用shell脚本。pthread_join失败会导致子进程成为僵尸吗?

在一种情况下观察到的情况是捕获到pthread_join失败(即pthread_join!= 0)并且子进程保持为僵尸(按ps输出)。

这也会导致主程序挂起。

现在,我不知道为什么pthread_join会失败,因为它在其他情况下从未做过。

但我想知道是否收集Popen产生的子进程的等待状态是thread_join的一部分。如果是这样至少我可以肯定的是,连接失败的根本原因僵尸和程序挂起..

在此先感谢..

+0

是的,我有这个想法。还没有尝试,因为pthread_join被封​​装为一个公共库。我已经放弃了下一次测试.. – Vivek

回答

1

调用popen后,需要有对pclose相应通话,否则由popen调用产生的子进程将保持僵尸状态。可能发生的情况是该线程遇到未处理的异常,导致pclose不被调用,导致僵尸和pthread_join的“失败”结果。

一个解决方案是确保您的代码正确处理所有可能的异常。

另一种解决方案是实现类似popen()的东西,但不需要pclose()收获僵尸。这可以通过使用双叉来完成。您致电fork(),然后再打电话给exec()。父进程允许中间子进程退出并通过wait4()获得。孙子过程现在可以不离开僵尸而离开,因为它将被init过程收割。要创建孙子和父母之间的沟通渠道,请使用pipe()作为popen(),如果您需要双向沟通,请使用socketpair()。在孙子过程中使用dup2(),以便在致电exec()之前允许您选择stdin,stdoutstderr通过管道或插座重定向。

+0

这似乎是有道理的。因为只有在底层套接字引发异常时才会发生此连接失败。但try-catch捕获加入失败..我会检查它是否是pclose情况并更新条件。 – Vivek

+0

我有一个疑问。如果我的主进程有一个SIGCHLD的信号处理程序并实现等待,那么即使连接失败僵尸也不会移除吗? – Vivek

+0

我接受你的答案,因为这帮助我解决了这个问题。前一个线程在加入后处理异常时留在列表中,当当前线程结束时,该列表再次遍历以便加入。再次加入会导致失败,因此此线程永远不会加入,从而导致僵尸进程和进程挂起。谢谢:) – Vivek