Waitpid等待失效的子进程

3

如果出现崩溃,我们使用以下函数将堆栈转储以获取有关崩溃的更多信息:

static void dumpStack()
    {
        char buf[64];

        pid_t pid = getpid();

        sprintf( buf, "%d", pid );

        pid_t fork_result = vfork();

        int status;

        if( fork_result == 0 )

            execlp( "pstack", "pstack", buf, NULL );

        else if( fork_result > 0 )

            waitpid( fork_result, &status, 0 );

        else

            std::cerr << "vfork failed with err=%s" << strerror( errno ) << std::endl;
    }

在上面的代码中,父进程一直停留在waitPid状态。我检查了子进程的状态,它变成了僵尸进程。
Deepak@linuxPC:~$ ps aux | grep  21054

    700048982 21054 0.0  0.0      0     0 pts/0    Z+   03:01   0:00 [pstack] <defunct>

而且子进程打印的堆栈信息也不完整,它只会打印一行信息然后退出。

#0  0x00007f61cb48d26e in waitpid () from /lib64/libpthread.so.0

不确定为什么父进程无法收割该进程。

请帮忙确认是否有遗漏。


你的意思是在父进程崩溃的情况下吗?这个函数会如何被调用? - user7860670
2
请提供一个完整的 [mcve],可以直接复制和编译以演示问题,而不仅仅是单个孤立的函数。 - Shawn
1
你是从信号处理程序中调用这个函数吗?请注意,vfork此处没有被列为信号安全,execlp也不是。你可能可以使用Linux特定的backtrace函数,但它也没有被列为信号安全(但已经在其他地方的信号示例中使用,比如这个)。 - Some programmer dude
避免使用vfork,在我看来永远不要使用它。 - Soner from The Ottoman Empire
1个回答

0

首先,您最好使用backtrace()函数,参见当我的程序崩溃时如何自动生成堆栈跟踪

至于您的代码,如果您在64位Linux上(很可能),pstack将无法工作。对我来说,它会导致段错误。此外,我同意有关vfork()和execlp()的评论。另外,您可能需要以root身份执行您的程序。下面的代码适用于我(打印父进程的堆栈,但不确定这是否非常有用):

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <iostream>
#include <system_error>

using std::cout;

static void dumpStack() {
  char buf[64];
  pid_t result;
  pid_t pid = getpid();
  sprintf(buf, "/proc/%d/stack", pid );
  //cout << buf << '\n';                                                                                                         
  pid_t fork_result = vfork();
  int status;
  if( fork_result == 0 ) {
    //execlp( "pstack", "pstack", buf, NULL );                                                                                   
    cout << "Child before execlp\n";
    execlp("cat", "cat", buf, NULL);
    cout << "Child after execlp\n";  // Will not print, of course
  } else if( fork_result > 0 ) {
    result = waitpid( fork_result, &status, 0 );
    if (result < 0) {
      throw std::system_error(errno, std::generic_category());
    }
  } else {
    std::cerr << "vfork failed with err=%s" << strerror( errno ) << std::endl;
  }
  cout << std::endl;
}

int main() {
  dumpStack();

  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接