Non-blocking pipe using popen?

后端 未结 3 1624
清歌不尽
清歌不尽 2020-12-04 20:16

I\'d like to open a pipe using popen() and have non-blocking \'read\' access to it.

How can I achieve this?

(The examples I found were all blocking/synchrono

相关标签:
3条回答
  • 2020-12-04 20:40

    popen() internally calls pipe(), fork(), dup2() (to point the child process's fds 0/1/2 to the pipes) and execve(). Have you considered using these instead? In that case, you can set the pipe you read to non-blocking using fcntl().

    update: Here's an example, just for illustrative purposes:

    int read_pipe_for_command(const char **argv)
    {
       int p[2];
    
       /* Create the pipe. */
       if (pipe(p))
       {
          return -1;
       }
    
       /* Set non-blocking on the readable end. */
       if (fcntl(p[0], F_SETFL, O_NONBLOCK))
       {
          close(p[0]);
          close(p[1]);
          return -1;
       }
    
       /* Create child process. */
       switch (fork())
       {
          case -1:
              close(p[0]);
              close(p[1]);
              return -1;
          case 0:
              /* We're the child process, close read end of pipe */
              close(p[0]);
              /* Make stdout into writable end */
              dup2(p[1], 1);
              /* Run program */
              execvp(*argv, argv);
              /* If we got this far there was an error... */
              perror(*argv);
              exit(-1);
          default:
              /* We're the parent process, close write end of pipe */
              close(p[1]);
              return p[0];
       }
    }
    
    0 讨论(0)
  • 2020-12-04 20:57

    Never tried it but I don't see why you couldn't grab the file descriptors with fileno(), use fcntl() to set to non-blocking, and use read()/write(). Worth a try.

    0 讨论(0)
  • 2020-12-04 20:59

    Setup like this:

    FILE *f = popen("./output", "r");
    int d = fileno(f);
    fcntl(d, F_SETFL, O_NONBLOCK);
    

    Now you can read:

    ssize_t r = read(d, buf, count);
    if (r == -1 && errno == EAGAIN)
        no data yet
    else if (r > 0)
        received data
    else
        pipe closed
    

    When you're done, cleanup:

    pclose(f);
    
    0 讨论(0)
提交回复
热议问题