我使用以下代码来使用父/子运行一些命令:
int nStatus = 0;
int nRet = 0;
pid_t pid = -1;
char *envp[] =
{
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp",
0
};
if(pnChildExitStatus == NULL || pcBuf == NULL)
{
nRet = -EINVAL;
goto returnHandler;
}
*pnChildExitStatus = 0;
pid = fork();
switch(pid)
{
case -1:
nRet = -errno; //can't fork
break;
case 0: //child
nRet = execl("/bin/sh","sh","-c", pcBuf, envp,NULL);
if (-1 == nRet) {
nRet = -errno;
goto returnHandler;
}
break;
default: //parent
/*After this call 'nStatus' is an encoded exit value. WIF macros will extract how it exited*/
if( waitpid(pid, &nStatus, 0) < 0 )
{
nRet = -errno;
*pnChildExitStatus = errno;
}
if(WIFEXITED(nStatus))
{
nRet = EXIT_SUCCESS;
*pnChildExitStatus = WEXITSTATUS(nStatus);
}
goto returnHandler;
break;
}
returnHandler:
return nRet;
}
我的问题如下:
在某些情况下,Parent收到WEXITSTATUS(nStatus)!= 0,虽然我的子进程总是返回0(我用调试打印验证了它)。
有人可以就这怎么可能提供任何想法?
提前谢谢大家。
答案 0 :(得分:3)
您对waitpid()
的使用存在缺陷。
如果waitpid()
被中断,它将返回-1,
但nStatus
中的值可能未定义,
因此if (WIFEXITED(nStatus))
可能仍然是真实的
WEXITSTATUS(nStatus)
可以是任何东西。
什么可以中断系统调用,(如waitpid)? 一个信号,如SIGCHLD,为一个退出的孩子。
正常模式类似于:
while ((wpid = waitpid(pid, &nStatus, 0)) != pid) {
if (wpid == -1) { /* see below */
if (errno == EINTR) continue;
/* else handle the other error (pretty unlikely) */
/* probably by returning something */
}
}
if (wpid == -1) { /* error */ } /* if you choose to `break' from the loop on error */
else { /* process exited */ } /* you need to check the situation here */
if (wpid == -1)
在这里有点多余,因为此循环中唯一的值wpid
可能是-1
,但此模式的其他变体不会约束wpid
这么紧,所以它是针对改变的防御性编程。
与if (errno == EINTR)
类似,因为大多数(全部?)errno
中只有3 waitpid
是:EINTR,ECHILD(没有孩子)和EFAULT(你得到了第二个arg)错误)。但是,再次,防御性编程。