C waitpid-wifexite返回0,但子项正常退出
我一直在编写一个生成子进程的程序,并调用C waitpid-wifexite返回0,但子项正常退出,c,fork,waitpid,execv,C,Fork,Waitpid,Execv,我一直在编写一个生成子进程的程序,并调用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 proce
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]
程序运行正常,除了触发的警告,这让我觉得这里发生了什么,我错过了
编辑:
正如下面的注释中所建议的,我检查了子项是否通过segfault终止,实际上,WIFSIGNALED(status)
返回1,WTERMSIG(status)
返回11,即SIGSEGV
然而,我不明白的是,为什么通过execv的调用会以segfault失败,而通过gdb或shell的调用会成功
EDIT2:
我的应用程序的行为在很大程度上取决于子进程的行为,特别是在子进程在声明为\uuuu attribute\uuuu((析构函数))
的函数中写入的文件上。waitpid
调用返回后,此文件存在并正确生成,这意味着segfault发生在另一个析构函数中的某个地方,或我无法控制的某个地方。在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退出,信号11为SIGSEGV
(同样,不是Posix,而是常规)
您的程序正在将无效参数传递给execv
(它是围绕execve
或其他特定于内核的调用的C库包装器),或者当您execv
它和从shell或gdb运行它时,它的运行方式不同
如果您所在的系统支持strace
,请运行(父级)在strace-f
下编程,查看execv
是否引起信号。Status 11表示孩子接收到信号11,SIGSEGV
。如果你在平台上(如Linux),非信号出口是传递给\u exit
或exit
或main
返回的低8位值的256倍具有战略的,使用它(使用-f
标志)查看子进程是由于对execv
的错误调用,还是在成功执行后获得信号。@robmayoff你说得对!我不知道status变量的下位字节包含派生进程的退出状态以及信号id。感谢你指出这一点!“但我不明白的是,为什么通过execv的呼叫会因segfault而失败"“args.binary_调用”
看起来怎么样?它从哪里来,您创建它?@Dabo是的,args.binary_调用是一个以NULL结尾的字符指针数组,这些字符指针是子应用程序及其参数的名称。我已经验证了数组是否正确。@robmayoff由于您的评论,我找到了segfault的原因。”-问题是我的应用程序改变了子进程的环境,我在独立测试中没有复制该环境,这就是为什么SEGFULT隐藏在exec环境之外。我想为此向您表示感谢,因为您将我发送到了正确的方向。因此,如果您想将您的评论作为答案,我很乐意接受:)