我一直在编写一个生成子进程的程序,并调用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
的{{1}}州的联合页面:
WIFEXITED
我的意思是它应该返回一个整数!= 0成功,这在我的程序执行中没有发生,因为我观察WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or
_exit(2), or by returning from main().
但是,从命令行执行相同的程序会导致WIFEXITED(status) == 0
,并从gdb开始导致:
$? == 0
程序运行正常,除了触发警告,这让我觉得其他事情正在发生,我不知道。
修改
如下面评论中所述,我检查了孩子是否通过段错误终止,确实[Inferior 1 (process 31934) exited normally]
返回1,而WIFSIGNALED(status)
返回11,即WTERMSIG(status)
。
我不明白的是,为什么通过execv进行的调用会因为段错误而失败,而通过gdb或shell进行同一调用会成功?
EDIT2:
我的应用程序的行为在很大程度上取决于子进程的行为,尤其是子进程在声明为SIGSEGV
的函数中写入的文件。在__attribute__ ((destructor))
调用返回后,此文件存在且生成正确,这意味着段错误发生在另一个析构函数中的某个位置,或者在我无法控制的位置。
答案 0 :(得分:7)
在Unix和Linux系统上,从wait
或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
(这是execve
的C库包装器或其他一些特定于内核的调用),或者execv
时子进程运行方式不同它以及从shell或gdb运行时。
如果您使用的是支持strace
的系统,请在strace -f
下运行您的(父)计划,以查看execv
是否正在发出信号。