waitpid - WIFEXITED返回0虽然孩子正常退出

And*_*tin 3 c fork execv waitpid

我一直在编写一个生成子进程的程序,并调用waitpid等待子进程的终止.代码如下:

  // fork & exec the child
  pid_t pid = fork();
  if (pid == -1)
    // here is error handling code that is **not** triggered

  if (!pid)
    {
      // binary_invocation is an array of the child process program and its arguments
      execv(args.binary_invocation[0], (char * const*)args.binary_invocation);
      // here is some error handling code that is **not** triggered
    }
  else
    {
      int status = 0;
      pid_t res = waitpid(pid, &status, 0);

      // here I see pid_t being a positive integer > 0
      // and status being 11, which means WIFEXITED(status) is 0.
      // this triggers a warning in my programs output.
    }
Run Code Online (Sandbox Code Playgroud)

waitpid各州的联合办公室WIFEXITED:

WIFEXITED(status)
    returns  true  if  the child terminated normally, that is, by calling exit(3) or
    _exit(2), or by returning from main().
Run Code Online (Sandbox Code Playgroud)

我的意思是它应该返回一个整数!= 0成功,这在我的程序执行中没有发生,因为我观察 WIFEXITED(status) == 0

但是,从命令行执行相同的程序会导致$? == 0,并从gdb开始导致:

[Inferior 1 (process 31934) exited normally]
Run Code Online (Sandbox Code Playgroud)

程序运行正常,除了触发警告,这让我觉得其他事情正在发生,我不知道.

编辑:
正如下面评论中所建议的,我检查了孩子是否通过segfault终止,实际上,WIFSIGNALED(status)返回1,并WTERMSIG(status)返回11,即SIGSEGV.

我不明白的是,为什么通过execv调用会因为段错误而失败,而通过gdb进行相同的调用,或者shell会成功?

EDIT2:
我的应用程序的行为在很大程度上取决于子进程的行为,特别是在子进程在声明的函数中写入的文件上__attribute__ ((destructor)).在之后waitpid调用返回,该文件存在,并正确生成,这意味着该段错误的地方出现在另一个析构函数,或介于我的控制之外.

rob*_*off 8

在Unix和Linux系统,状态从返回waitwaitpid(或任何其他的wait变种)具有这样的结构:

bits   meaning

0-6    signal number that caused child to exit,
       or 0177 if child stopped / continued
       or zero if child exited without a signal

 7     1 if core dumped, else 0

8-15   low 8 bits of value passed to _exit/exit or returned by main,
       or signal that caused child to stop/continue
Run Code Online (Sandbox Code Playgroud)

(注意,Posix不定义位,只定义宏,但这些是至少Linux,Mac OS X/iOS和Solaris使用的位定义.另请注意,waitpid如果将WUNTRACED标志传递给标志,则仅返回停止事件.如果您传递WCONTINUED旗帜,则继续事件.)

因此状态为11意味着孩子由于信号11而退出,这也是SIGSEGV(同样不是Posix而是常规).

您的程序正在传递无效参数execv(这是一个C库包装execve或其他一些特定于内核的调用),或者execv当您从shell或gdb运行它时,子程序运行方式不同.

如果您使用的是支持的系统strace,请运行您的(父)程序strace -f以查看是否execv导致信号.