質問

I'm trying to get the exit code of a subprocess. On Linux and FreeBSD I can go like so:

[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)

However, on OpenBSD, I get complaints from the compiler...

[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)

I don't really care how it's done, I just need the exit code.

This leads me to believe that I would also have this problem on Mac: http://web.archiveorange.com/archive/v/8XiUWJBLMIKYSCRJnZK5#F4GgyRGRAgSCEG1

Is there a more portable way to use the WEXITSTATUS macro? Or is there a more portable alternative?

役に立ちましたか?

解決

OpenBSD's implementation of WEXITSTATUS uses the address-of operator (unary &) on its argument, effectively requiring that its argument have storage. You are calling it with the return value of a function, which doesn't have storage, so the compiler complains.

It is unclear whether OpenBSD's WEXITSTATUS is POSIX-compliant, but the problem can be easily worked around by assigning the return value of pclose() to a variable:

    int status = pclose(proc);
    printf("Exit code: %d\n", WEXITSTATUS(status));

他のヒント

As a detail that could go unnoticed for some people arriving here, BSD object code needs the library:

#include <sys/wait.h>

I was too compiling to Linux and BSD, and WEXITSTATUS worked OK without the need for that library (I don't know why) when compiling to Linux (using gcc), but failed when compiling to BSD (using clang).

If your application died or was otherwise killed, the return status is bogus. You need to check the status to see if the exit value is even valid. See the man page for waitpid.

if(WIFEXITED(status))
{
     use WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
     use WTERMSIG(status);
} else {
     oh oh
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top