4

我一直在编写一个生成子进程的程序,并调用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.
    }

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().

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

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

[Inferior 1 (process 31934) exited normally]

该程序运行正常,除了触发的警告,这让我觉得这里发生了其他事情,我错过了。

编辑:
正如评论中建议的那样,我检查了孩子是否通过段错误终止,并且确实WIFSIGNALED(status)返回 1,并WTERMSIG(status)返回 11,即SIGSEGV.

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

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

4

1 回答 1

11

在 Unix 和 Linux 系统上,从waitor waitpid(或任何其他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

(请注意,Posix 没有定义位,只是宏,但这些是至少 Linux、Mac OS X/iOS 和 Solaris 使用的位定义。另请注意,waitpid如果您将WUNTRACED标志和如果您将WCONTINUED标志传递给它,则继续事件。)

因此,状态 11 意味着孩子因信号 11 而退出,这是SIGSEGV(同样,不是 Posix,而是传统上)。

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

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

于 2014-04-24T14:47:55.800 回答