等待(状态),WEXITSTATUS(状态)总是返回0 [英] wait(status), WEXITSTATUS(status) always returns 0

查看:65
本文介绍了等待(状态),WEXITSTATUS(状态)总是返回0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用 fork() exec() wait() 的 c 程序.第一个进程有这个代码:

I'm working on a c program that uses fork() exec() wait(). The first process has this code:

int main(int argc, const char * argv[]) {
// insert code here...

int pid = fork();

if(pid == 0){
    //we are the child process.
    execlp("/Users/matthewdunn/Library/Developer/Xcode/DerivedData/PA2-hekivoaqvsegnggdvcfguasystig/Build/Products/Debug/Checker", "Checker", "1", "5", (char*) NULL);
}else{
    //we are the parent process.
    printf("Coordinator: forked process with ID ");
    printf("%d\n", pid);

    printf("Coordinator: waiting for process [");
    printf("%d", pid);
    printf("]\n");

    int status;
    waitpid(pid, &status, 0);
    int returned = WEXITSTATUS(status);

    printf("Coordinator: child process ");
    printf("%d", pid);
    printf(" returned ");
    printf("%d", returned);
    printf(".\n");
}



  return 0;
}

第二个进程有代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void printProcessInfo(){
    printf("Checker process [");
    printf("%d", getpid());
    printf("]:  ");
}

int main(int argc, const char * argv[]) {
    // insert code here...

    printProcessInfo();
    printf("Starting.\n");

    int arg1;
    int arg2;

    arg1 = atoi(argv[1]);
    arg2 = atoi(argv[2]);

    if((arg2 % arg1) > 0){
        printProcessInfo();
        printf("%d", arg2);
        printf(" *IS NOT* divisible by ");
        printf("%d\n", arg1);

        printProcessInfo();
        printf("Returning 0.\n");
        return 0;
    }
    else{
        printProcessInfo();
        printf("%d", arg2);
        printf(" *IS* divisible by ");
        printf("%d\n", arg1);

        printProcessInfo();
        printf("Returning 1.\n");
        return 1;
    }

}

由于我无法弄清楚的原因,父函数总是读取 0 的返回值,即使我得到了下降的输出:

For a reason that I cannot figure out, the parent function always reads a return value of 0, even though I get the falling output:

Coordinator: forked process with ID 2865 
Coordinator: waiting for process [2865] 
Checker process [2865]:  Starting. 
Checker process [2865]:  5 *IS* divisible by 1 
Checker process [2865]:  Returning 1.
Coordinator: child process 2865 returned 0. 
Program ended with exit code: 0

第二个进程显然返回 1,但我的状态仍然是 0.我不知道是什么原因造成的.我正在使用 Xcode 编写此代码.WEXITSTATUS(status) 总是返回 0 有什么原因吗?

The second process is clearly returning 1, yet I'm still getting a 0 for the status. I have no idea what could be causing this. I'm writing this code using Xcode. Is there a reason why WEXITSTATUS(status) always returns 0?

推荐答案

这里:

int* status;
waitpid(pid, status, 0);

您的指针 status 从未设置为实际指向任何内容.您需要一个实际的 int 来存储值:

your pointer status is never set to actually point to anything. You need an actual int to store the value:

int status;
waitpid(pid, &status, 0);

如果您对退出状态特别感兴趣,您还应该检查以确保它确实正常退出.可以说,就像所有系统调用一样,在尝试对该值执行任何操作之前,您应该检查 waitpid() 的返回是否有错误.

If you're specifically interested in the exit status, you should also be checking to make sure it actually exited normally. Suffice to say, like all system calls, you should be checking the return from waitpid() for errors before attempting to do anything with that value.

总和:

int status;
if ( waitpid(pid, &status, 0) != -1 ) {
    if ( WIFEXITED(status) ) {
        int returned = WEXITSTATUS(status);
        printf("Exited normally with status %d\n", returned);
    }
    else if ( WIFSIGNALED(status) ) {
        int signum = WTERMSIG(status);
        printf("Exited due to receiving signal %d\n", signum);
    }
    else if ( WIFSTOPPED(status) ) {
        int signum = WSTOPSIG(status);
        printf("Stopped due to receiving signal %d\n", signum);
    }
    else {
        printf("Something strange just happened.\n");
    }
}
else {
    perror("waitpid() failed");
    exit(EXIT_FAILURE);
}

这是一个工作示例:

parent.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
    int pid = fork();

    if ( pid == -1 ) {
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }
    else if ( pid == 0 ) {
        execlp("./child", "child", "1", "5", (char *)NULL);
        perror("execlp() failed");
        exit(EXIT_FAILURE);
    } else {
        printf("Coordinator: forked and waiting for process %d\n", pid);

        int status;
        if ( waitpid(pid, &status, 0) != -1 ) {
            if ( WIFEXITED(status) ) {
                int returned = WEXITSTATUS(status);
                printf("Exited normally with status %d\n", returned);
            }
            else if ( WIFSIGNALED(status) ) {
                int signum = WTERMSIG(status);
                printf("Exited due to receiving signal %d\n", signum);
            }
            else if ( WIFSTOPPED(status) ) {
                int signum = WSTOPSIG(status);
                printf("Stopped due to receiving signal %d\n", signum);
            }
            else {
                printf("Something strange just happened.\n");
            }
        }
        else {
            perror("waitpid() failed");
            exit(EXIT_FAILURE);
        }
    }

    return 0;
}

child.c:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void printProcessInfo()
{
    printf("Checker process [%d]: ", getpid());
}

int main(int argc, char * argv[])
{
    printProcessInfo();
    printf("Starting.\n");

    int arg1, arg2;

    arg1 = atoi(argv[1]);
    arg2 = atoi(argv[2]);

    if ( (arg1 != 0) && (arg2 % arg1) > 0 ){
        printProcessInfo();
        printf("%d *IS NOT* divisible by %d\n", arg2, arg1);
        printProcessInfo();
        printf("Returning 0.\n");
        return 0;
    }
    else {
        printProcessInfo();
        printf("%d *IS* divisible by %d\n", arg2, arg1);
        printProcessInfo();
        printf("Returning 1.\n");
        return 1;
    }

    return 0;
}

带输出:

paul@horus:~/src/sandbox/ft$ ./parent
Coordinator: forked and waiting for process 40330
Checker process [40330]: Starting.
Checker process [40330]: 5 *IS* divisible by 1
Checker process [40330]: Returning 1.
Exited normally with status 1
paul@horus:~/src/sandbox/ft$ 

如果您在 Xcode 中构建它,发生的情况是您的 waitpid() 调用被信号中断(很可能是 SIGCHLD).在这种情况下,您只需要重新启动它,如下所示:

If you're building this in Xcode, what's happening is your waitpid() call is getting interrupted by a signal (most probably SIGCHLD). In this case, you just need to restart it, like so:

int status;
while ( waitpid(pid, &status, 0) == -1 ) {
    if (errno == EINTR) {
        printf("Parent interrrupted - restarting...\n");                   
        continue;
    }
    else {
        perror("waitpid() failed");
        exit(EXIT_FAILURE);
    }
}

if ( WIFEXITED(status) ) {
    int returned = WEXITSTATUS(status);
    printf("Exited normally with status %d\n", returned);
}
else if ( WIFSIGNALED(status) ) {
    int signum = WTERMSIG(status);
    printf("Exited due to receiving signal %d\n", signum);
}
else if ( WIFSTOPPED(status) ) {
    int signum = WSTOPSIG(status);
    printf("Stopped due to receiving signal %d\n", signum);
}
else {
    printf("Something strange just happened.\n");
}

这篇关于等待(状态),WEXITSTATUS(状态)总是返回0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆