Вопрос

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