bi-directional IPC / pipes / when to close??

Ask a Question related to UNIX Programming, Design and Development.

  1. #1

    Default bi-directional IPC / pipes / when to close??

    Hi,

    I'm writing a C program that needs to bi-directionally communicate
    with with a forked/execvp'd process. Here is a sample program that
    illustrates my problem. I fork 'tr' and send it a string, but it only
    works if I close the pipe after the write, before the read. Any
    ideas? I can't keep closing the pipe b/c I need to
    read/write/read/write... etc.

    I'm using redhad linux 7.2 and gcc 3.1

    Thanks!!
    itd

    #include <iostream>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <signal.h>
    #include <unistd.h>
    #include <fcntl.h>

    using namespace std;

    #define R_END 0
    #define W_END 1

    int
    main(int argc, char *argv[])
    {
    fflush(stdout);
    setbuf(stdout, (char*)NULL);
    fflush(stderr);
    setbuf(stderr, (char*)NULL);

    int pid;

    int pipe_a[2];
    int pipe_b[2];

    if (pipe(pipe_a) < 0)
    return 1;
    if (pipe(pipe_b) < 0)
    return 1;

    cout << "Pipes created, forking...\n";

    pid = fork();
    if (pid == 0)
    {
    dup2(pipe_b[R_END], STDIN_FILENO);
    dup2(pipe_a[W_END], STDOUT_FILENO);
    dup2(pipe_a[W_END], STDERR_FILENO);

    close(pipe_a[0]);
    close(pipe_b[0]);
    close(pipe_a[1]);
    close(pipe_b[1]);

    char *args[] = {"tr", "A-Z", "a-z", 0};

    execvp(args[0], args);
    perror("child/fork()");

    _exit(0);
    }
    else if (pid < 0)
    {
    cout << "Failed\n";
    return 1;
    }


    // Parent reads from R_END of pipe_a
    // Parent writes to W_END of pipe_b

    // Child reads from R_END of pipe_b
    // Child writes to W_END of pipe_a

    cout << "Child process (" << pid << ")\n";

    int read, write;

    read = pipe_a[R_END];
    write = pipe_b[W_END];

    close(pipe_a[W_END]);
    close(pipe_b[R_END]);

    char *string = "UPPERCASE LINE\n";

    cout << "Writing: " << string;

    FILE *fw;
    fw = fdopen(write, "w"); // w or w+ or a?
    if (!fw)
    {
    perror("fdopen(w)");
    return 1;
    }
    fprintf(fw, "%s", string);

    // --------------------------------------
    // --------------------------------------
    // Doesn't work unless I comment this... why?
    // fclose(fw);
    // --------------------------------------
    // --------------------------------------

    cout << "Reading child ...\n";

    FILE *fr;
    char buffer[1024];
    fr = fdopen(read, "r");
    if (!fr)
    {
    perror("fdopen(r)");
    return 1;
    }

    while (fgets(buffer, 1000, fr))
    {
    printf("%s", buffer);
    }

    fclose(fr);

    cout << "Closing down child, waiting\n";
    kill(pid, 9);

    int return_status;
    wait(&return_status);

    return 0;
    }
    ixtahdoom Guest

  2. Similar Questions and Discussions

    1. Bidirectional pipes
      Hi all, I wonder how can I open pipe to STDIN and STDOUT of a process ? Tnx. Mehmet
    2. Bi-Directional Encryption for classic ASP
      Does anyone know if such thing exists? I am trying to find a component for classic ASP. Thanks, CK
    3. get rid of whitespace around pipes??
      On Dec 17, LoneWolf said: Then split on /\s*\|\s*/. That regex reads "zero or more whitespace, a |, then zero or more whitespace". @fields...
    4. [PHP] How to achieve bi-directional communication between twoservers?
      Daevid Vincent wrote: You can open a link to a "service" that is running on the client, or call some page on the client with another GET...
    5. Interactive directional sound
      Does anyone know if this could be done using a QTVR clip (sound only) with SoundSaVR? Has anyone used SoundSaVR ( http://www.smgvr.com )? "Dan"...
  3. #2

    Default Re: bi-directional IPC / pipes / when to close??

    On 19 Jul 2003 14:41:28 -0700, ixtahdoom <ixtahdoom@yahoo.com> wrote:
    > Hi,
    >
    > I'm writing a C program that needs to bi-directionally communicate
    > with with a forked/execvp'd process. Here is a sample program that
    > illustrates my problem. I fork 'tr' and send it a string, but it only
    > works if I close the pipe after the write, before the read. Any
    > ideas? I can't keep closing the pipe b/c I need to
    > read/write/read/write... etc.
    >
    [snip]

    There's not a lot you can do when you're trying to interact with a command
    over which you have no control, which is the case here. The command is
    buffering its input, and that's causing it to be noninteractive. Closing
    the pipe causes it to effectively get an EOF, but, as you say, that's
    impractical if you want to keep it alive for long time.

    One very complicated solution is to make the standard input of the command
    that wants to buffer a terminal device instead of a pipe. For this you have
    to use pseudo-terminals (ptys). Very complicated and non-portable to set
    up. However, they will usually solve the problem, but even that is not
    guaranteed, depending on how the command is programmed. It still might
    buffer until it gets an EOF.

    --Marc
    Marc Rochkind Guest

  4. #3

    Default Re: bi-directional IPC / pipes / when to close??

    That makes sense. I thought it was related to all this
    blocking/non-blocking stuff that I've read about, and can't seem to
    get my head around yet. Fortunately the target program I need to
    invoke as a child is a Perl script with $|=1, so I guess I can scoot
    by in this case with lots of comments in the C. I wrote a version of
    'tr' in perl that had unbuffered input and it worked fine. Thanks.


    Marc Rochkind <rochkind@basepath.com> wrote in message news:<oprsk23tiyojfyi9@den.news.speakeasy.net>...
    > On 19 Jul 2003 14:41:28 -0700, ixtahdoom <ixtahdoom@yahoo.com> wrote:
    >
    > > Hi,
    > >
    > > I'm writing a C program that needs to bi-directionally communicate
    > > with with a forked/execvp'd process. Here is a sample program that
    > > illustrates my problem. I fork 'tr' and send it a string, but it only
    > > works if I close the pipe after the write, before the read. Any
    > > ideas? I can't keep closing the pipe b/c I need to
    > > read/write/read/write... etc.
    > >
    >
    > [snip]
    >
    > There's not a lot you can do when you're trying to interact with a command
    > over which you have no control, which is the case here. The command is
    > buffering its input, and that's causing it to be noninteractive. Closing
    > the pipe causes it to effectively get an EOF, but, as you say, that's
    > impractical if you want to keep it alive for long time.
    >
    > One very complicated solution is to make the standard input of the command
    > that wants to buffer a terminal device instead of a pipe. For this you have
    > to use pseudo-terminals (ptys). Very complicated and non-portable to set
    > up. However, they will usually solve the problem, but even that is not
    > guaranteed, depending on how the command is programmed. It still might
    > buffer until it gets an EOF.
    >
    > --Marc
    ixtahdoom Guest

  5. #4

    Default Re: bi-directional IPC / pipes / when to close??

    * [email]ixtahdoom@yahoo.com[/email] (ixtahdoom)
    | fw = fdopen(write, "w"); // w or w+ or a?
    | if (!fw)
    | {
    | perror("fdopen(w)");
    | return 1;
    | }
    | fprintf(fw, "%s", string);
    |
    | // --------------------------------------
    | // --------------------------------------
    | // Doesn't work unless I comment this... why?
    | // fclose(fw);

    Try fflush(fw) here to handle stdio buffering at your side of the pipe.
    (BTW, why do you use stdio here at all if you don't want buffering?)

    But, as Marc Rochkind pointed out, there might be buffering involved
    in the other program, too, so this may or may not work.

    R'
    Ralf Fassel Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139