我正在尝试获取子进程的退出代码。在Linux和FreeBSD上我可以这样:
[0] [ishpeck@kiyoshi /tmp]$ uname
FreeBSD
[0] [ishpeck@kiyoshi /tmp]$ cat tinker.c
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
FILE *proc = popen("ls", "r");
printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
return 0;
}
[0] [ishpeck@kiyoshi /tmp]$ gcc tinker.c -o tinker
[0] [ishpeck@kiyoshi /tmp]$ ./tinker
Exit code: 0
[0] [ishpeck@kiyoshi /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h
#define WEXITSTATUS(x) (_W_INT(x) >> 8)
但是,在OpenBSD上,我收到了编译器的抱怨......
[0] [ishpeck@ishberk-00 /tmp]$ uname
OpenBSD
[0] [ishpeck@ishberk-00 /tmp]$ cat tinker.c
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
FILE *proc = popen("ls", "r");
printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
return 0;
}
[0] [ishpeck@ishberk-00 /tmp]$ gcc tinker.c -o tinker
tinker.c: In function 'main':
tinker.c:7: error: lvalue required as unary '&' operand
[1] [ishpeck@ishberk-00 /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h
#define WEXITSTATUS(x) (int)(((unsigned)_W_INT(x) >> 8) & 0xff)
我真的不在意它是怎么做的,我只需要退出代码。
这让我相信我在Mac上也会遇到这个问题: http://web.archiveorange.com/archive/v/8XiUWJBLMIKYSCRJnZK5#F4GgyRGRAgSCEG1
是否有更便携的方式来使用WEXITSTATUS宏?还是有更便携的替代方案?
答案 0 :(得分:9)
OpenBSD的WEXITSTATUS
实现在其参数上使用了address-of运算符(一元&
),实际上要求其参数具有存储空间。您正在使用函数的返回值调用它,该函数没有存储空间,因此编译器会抱怨。
目前还不清楚OpenBSD的WEXITSTATUS
是否符合POSIX标准,但通过将pclose()
的返回值赋给变量可以轻松解决问题:
int status = pclose(proc);
printf("Exit code: %d\n", WEXITSTATUS(status));
答案 1 :(得分:0)
如果您的申请死亡或以其他方式被杀,则返回状态为虚假。您需要检查状态以查看退出值是否有效。请参阅waitpid的手册页。
if(WIFEXITED(status))
{
use WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
use WTERMSIG(status);
} else {
oh oh
}
答案 2 :(得分:0)
作为一些到达这里的人可能不会注意到的细节, BSD对象代码需要该库:
#include <sys/wait.h>
我过于编译为 Linux 和 BSD ,WEXITSTATUS
可以在编译时不需要该库(我不知道为什么)的情况下正常运行到 Linux (使用gcc
),但是编译到 BSD (使用clang
)时失败。