Is there a way to check if pclose () will succeed?

In my C ++ application, I see pclose () hangs because the pipe process hangs and never exits. Is there anyway I can do something like select () to check if pclose () returns because the child process has terminated? I would rather not use fork () instead of popen () if possible. If fork () is the only solution, are there examples of using fork () to replace the popen () / pclose () script?

+3


source to share


1 answer


Probably the easiest way, especially if you only have one child process, is to catch SIGCHLD

and set the flag that the process terminated and pclose()

can be called.

Here's a simple example:

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;
}

      



pc.c

:

#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;
}

      

which outputs:

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$ 

      

+1


source







All Articles