消失的孩子过程

时间:2014-10-06 02:11:30

标签: c++ exec fork pipe dup2

我有这个方法:

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc) {
    std::cout << "Building Pipe...\ncmd1: " << cmd1 << "\n cmd2: " << cmd2 << "\n";
    int *pipefd = new int[2];
    if (pipe(pipefd) < 0) {
        std::cerr << "There was an error setting up the pipe.\n";
        return -1;
    }
    pid_t cpid1 = fork();
    std::cout << "First process forked, cpid: " << cpid1 << " - Process " << getpid() << "\n";
    switch (cpid1) {
        case -1:
            std::cerr << "There was an error forking the process.\n";
            return -1;
            break;
        case 0: // this is the part that isn't executing
            std::cout << "Dup2 return: " << dup2(pipefd[1], 1) << "\n";
            std::cout << "Process " << getpid() << " duped and about to exec.\n";
            execvp(cmd1.c_str(), argv1);
            std::cout << "Process " << getpid() << " about to exit.\n";
            _exit(0);
            break;
        default:
            pid_t cpid2 = fork();
            switch (cpid2) {
                case -1:
                    std::cerr << "There was an error forking the process.\n";
                    return -1;
                    break;
                case 0:
                    dup2(pipefd[0], 0);
                    std::cout << "Process " << getpid() << " duped and about to exec.\n";
                    execvp(cmd2.c_str(), argv2);
                    _exit(0);
                    break;
                default:
                    if (conc) {

                    } else {
                        int status1, status2;
                        std::cout << "Process " << getpid() << " about to wait.\n";
                        waitpid(cpid1, &status1, 0);
                        waitpid(cpid2, &status2, 0);
                    }
                    break;
            }
        }
    delete[] pipefd;
    return 0;
}

我已经添加了打印语句,仅用于调试。但是,当此方法运行时,这就是打印的内容。

Building Pipe...
cmd1: cat
cmd2: wc
First process forked, cpid: 1454 - Process 1453
First process forked, cpid: 0 - Process 1454
Process 1453 about to wait.
Process 1455 duped and about to exec.

进程1454,即分叉的第一个进程,在创建消息后立即打印该消息。但是,它从不打印来自switch语句的任何消息,并且从不执​​行指定的程序(在本例中为cat)。这个过程并不像僵尸那样流连,它只会消失。结果,第二个子进程挂起,实际上从未做过任何事情。

(另外,只是添加,我知道我还没有添加所有适当的错误处理功能,但功能还没有完成)。

2 个答案:

答案 0 :(得分:2)

您没有看到switch语句中的消息,因为它们已写入管道。尝试将std::cout替换为std::cerr

答案 1 :(得分:1)

管道在检测到EOF时结束,为此你必须在重复它后关闭不需要的描述符(在子项和父项中):

close(pipefd[0]);
close(pipefd[1]);

此外,请始终检查execvp的返回值,您可能在argv中出错:

if (execvp(cmd1.c_str(), argv1) == -1) {
    // check errno here
}

此外,请务必以 nullptr 作为最后一个元素结束argv, argv [0] 必须是命令本身。原型:

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc)

...让我觉得你没有提供第一个元素( argv [0] = cmd1 )。如果你在 argv 中拥有它,你就不需要为函数build_pipe_and_call提供额外的值( cmdX )。

请注意,如果execvp运行良好,您将永远无法访问程序中的后续代码,因此您无法按照预期看到某些消息:

execvp(cmd1.c_str(), argv1);
std::cout << "Process " << getpid() << " about to exit.\n"; // if execvp didn't fail, it's never reached

一旦你复制了它,也要小心使用 std :: cout ,如@larpico answered