有没有办法测试pclose()是否会成功? 在我的C++应用程序中,我看到一个挂起的(pHeLeT)(),因为管道的进程挂起并且从不退出。我是否可以执行类似select()的操作来测试pclose()是否会因为子进程已完成而返回?如果可能的话,我宁愿不做fork()而不是popen()。如果fork()是唯一的解决方案,那么有没有使用fork()替换popen()/pclose()场景的例子?

有没有办法测试pclose()是否会成功? 在我的C++应用程序中,我看到一个挂起的(pHeLeT)(),因为管道的进程挂起并且从不退出。我是否可以执行类似select()的操作来测试pclose()是否会因为子进程已完成而返回?如果可能的话,我宁愿不做fork()而不是popen()。如果fork()是唯一的解决方案,那么有没有使用fork()替换popen()/pclose()场景的例子?,c++,fork,wait,pclose,C++,Fork,Wait,Pclose,可能最简单的方法,特别是如果您只有一个子进程,就是捕获SIGCHLD并设置一个标志,表明进程已终止,并且可以调用pclose() 下面是一个简单的例子: sillyprog.c: #include <stdio.h> #include <unistd.h> int main(void) { printf("This is some data from the child.\n"); fflush(stdout); sleep(5); re

可能最简单的方法,特别是如果您只有一个子进程,就是捕获
SIGCHLD
并设置一个标志,表明进程已终止,并且可以调用
pclose()

下面是一个简单的例子:

sillyprog.c

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    printf("This is some data from the child.\n");
    fflush(stdout);
    sleep(5);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

volatile sig_atomic_t child_done = 0;

void handler(int signum)
{
    if ( signum == SIGCHLD ) {
        child_done = 1;
    }
}

int main(void)
{
    /*  Set signal handler  */

    struct sigaction sa;
    sa.sa_handler = handler;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    if ( sigaction(SIGCHLD, &sa, NULL) == -1 ) {
        perror("couldn't set signal handler");
        return EXIT_FAILURE;
    }

    /*  Open pipe  */

    FILE * fp = popen("./sillyprog", "r");
    if ( !fp ) {
        fprintf(stderr, "Couldn't open pipe\n");
        return EXIT_FAILURE;
    }

    /*  Get a line from pipe  */

    char buffer[100];
    if ( !fgets(buffer, 100, fp) ) {
        fprintf(stderr, "Error calling fgets()\n");
        return EXIT_FAILURE;
    }

    const size_t len = strlen(buffer);
    if ( len && buffer[len - 1] == '\n' ) {
        buffer[len - 1] = 0;
    }
    printf("Got '%s' from pipe.\n", buffer);

    /*  Wait for child to finish  */

    while ( !child_done ) {
        printf("Child not ready, waiting...\n");
        sleep(1);
    }

    /*  Close pipe  */

    if ( pclose(fp) == -1 ) {
        fprintf(stderr, "Error calling pclose()\n");
        return EXIT_FAILURE;
    }
    else {
        printf("pclose() successfully called.\n");
    }

    return 0;
}
哪些产出:

paul@horus:~/src/sandbox$ ./pc
Got 'This is some data from the child.' from pipe.
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
pclose() successfully called.
paul@horus:~/src/sandbox$ 

您可能需要做一些更低级的工作,并设置自己的管道文件描述符。然后,您可以对这些子管道进行轮询,查看它们是否已关闭,然后终止子进程。如果您有多个子管道,如何确定是哪个子管道导致了SIGPIPE?@WilliamKF:
SIGCHLD
,使用此方法,您无法确定。您可以做的是每次递增
child\u done
,而不是将其设置为1,然后等待它等于管道总数,然后对其中任何管道调用
pclose()
。如果您在问题中更详细地说明您实际想要实现的目标,这会有所帮助,例如,如果您确定某个特定的子项正在挂起,并且调用
pclose()
将无限期挂起,您想对此做些什么?在可能挂起的进程上不调用
popen()
,可能是总体上最好的解决方案。