problem writing to stdin of child process

Discussion in 'Perl Misc' started by john, Mar 14, 2005.

  1. john

    john Guest

    Hello everyone,

    I have a program which forks multiple children and needs to have
    bidirectional communication with each child. Each child needs to use
    STDIN and STDOUT to talk back to the parent.

    The problem is that I'm having trouble connecting the pipe to STDIN of
    the child. I've tried various approaches. A simple testcase is below.
    In this case, the child seems to read the number (I think) of the pipe
    file descriptor rather than the string I send down the pipe.

    perl -v shows...
    This is perl, v5.8.2 built for aix-thread-multi

    Can anyone tell me where I'm going wrong ?
    Thanks in advance.



    #!/usr/bin/perl
    use strict;
    use warnings;

    use IO::Handle;
    use IO::pipe;

    my $cr = IO::Handle->new(); # child reader
    my $pw = IO::Handle->new(); # child writer

    new IO::pipe($cr, $pw) or die 'pr/cw pipe';

    my $pid = fork();
    if ($pid > 0) {

    # Parent

    print {$pw} "hello!\n"; # sending to the child
    close($pw);

    } else {
    # Child

    # Connect stdin to pipe

    close($pw);
    my $fd = fileno($cr);
    open(my $stdin, "<", \$fd) or die "STDIN open: $!";
    *STDIN = $stdin;

    my $line = <STDIN>; # hopefully reading from the parent
    chomp $line;
    print "child received: ($line)\n";
    close($cr);
    exit(0);
    }

    wait;
     
    john, Mar 14, 2005
    #1
    1. Advertising

  2. john

    Big and Blue Guest

    john wrote:

    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    > use IO::Handle;
    > use IO::pipe;
    >
    > my $cr = IO::Handle->new(); # child reader
    > my $pw = IO::Handle->new(); # child writer
    >
    > new IO::pipe($cr, $pw) or die 'pr/cw pipe';


    Have you read the IO::pipe documentation?
    (e.g. http://search.cpan.org/~nwclark/perl-5.8.6/ext/IO/lib/IO/Pipe.pm)

    It starts with (almost) exactly what you want under the SYNOPSIS. (It
    has the child writing to the parent - just swap the if/else codew blocks).

    No need to mention IO::Handle (IO::pipe gets them for you).


    > my $fd = fileno($cr);
    > open(my $stdin, "<", \$fd) or die "STDIN open: $!";
    > *STDIN = $stdin;
    >
    > my $line = <STDIN>; # hopefully reading from the parent


    Not sure why you would want to do this anyway. You shouldn't be
    reading from STDIN - you want to read from the read-side of the pipe opened
    in the parent. Don't assume that just because your want to read from it
    you have to make it STDIN. STDIN is "STanDard INput" - reading from a pipe
    isn't "standard" in this sense.



    --
    Just because I've written it doesn't mean that
    either you or I have to believe it.
     
    Big and Blue, Mar 15, 2005
    #2
    1. Advertising

  3. john

    john Guest

    Big and Blue <> wrote in message news:<>...
    > john wrote:
    >
    > > #!/usr/bin/perl
    > > use strict;
    > > use warnings;
    > >
    > > use IO::Handle;
    > > use IO::pipe;
    > >
    > > my $cr = IO::Handle->new(); # child reader
    > > my $pw = IO::Handle->new(); # child writer
    > >
    > > new IO::pipe($cr, $pw) or die 'pr/cw pipe';

    >
    > Have you read the IO::pipe documentation?
    > (e.g. http://search.cpan.org/~nwclark/perl-5.8.6/ext/IO/lib/IO/Pipe.pm)
    >
    > It starts with (almost) exactly what you want under the SYNOPSIS. (It
    > has the child writing to the parent - just swap the if/else codew blocks).


    I've seen this on my travels, but for some reason it didn't sink in
    that this was what I needed. Terms such as "re-blessed" confuse me and
    I've been sticking to stuff that I *thought* I understood. Anyway
    you're right. This is exactly what I need and it'll make my code a lot
    neater. I was going to post the modified and working testcase, however
    it's so close to the example in the IO:pipe doc that there doesn't
    seem much point.

    >
    > No need to mention IO::Handle (IO::pipe gets them for you).


    I'm using autoflush in my larger program, but you're right; it's not
    needed in this testcase.

    >
    >
    > > my $fd = fileno($cr);
    > > open(my $stdin, "<", \$fd) or die "STDIN open: $!";
    > > *STDIN = $stdin;
    > >
    > > my $line = <STDIN>; # hopefully reading from the parent

    >
    > Not sure why you would want to do this anyway. You shouldn't be
    > reading from STDIN - you want to read from the read-side of the pipe opened
    > in the parent. Don't assume that just because your want to read from it
    > you have to make it STDIN. STDIN is "STanDard INput" - reading from a pipe
    > isn't "standard" in this sense.


    The children will each exec an external command which will read from
    stdin, and the parent has to manage sending data to each.

    Thanks for your help "Big and Blue".
     
    john, Mar 15, 2005
    #3
  4. john

    Anno Siegel Guest

    john <> wrote in comp.lang.perl.misc:
    > Hello everyone,
    >
    > I have a program which forks multiple children and needs to have
    > bidirectional communication with each child. Each child needs to use
    > STDIN and STDOUT to talk back to the parent.


    Have you considered IPC::Open2?

    Anno
     
    Anno Siegel, Mar 15, 2005
    #4
  5. john

    john Guest

    (john) wrote in message news:<>...
    > Big and Blue <> wrote in message news:<>...
    > > john wrote:
    > >
    > > > #!/usr/bin/perl
    > > > use strict;
    > > > use warnings;
    > > >
    > > > use IO::Handle;
    > > > use IO::pipe;
    > > >
    > > > my $cr = IO::Handle->new(); # child reader
    > > > my $pw = IO::Handle->new(); # child writer
    > > >
    > > > new IO::pipe($cr, $pw) or die 'pr/cw pipe';

    > >
    > > Have you read the IO::pipe documentation?
    > > (e.g. http://search.cpan.org/~nwclark/perl-5.8.6/ext/IO/lib/IO/Pipe.pm)
    > >
    > > It starts with (almost) exactly what you want under the SYNOPSIS. (It
    > > has the child writing to the parent - just swap the if/else codew blocks).

    >
    > I've seen this on my travels, but for some reason it didn't sink in
    > that this was what I needed. Terms such as "re-blessed" confuse me and
    > I've been sticking to stuff that I *thought* I understood. Anyway
    > you're right. This is exactly what I need and it'll make my code a lot
    > neater. I was going to post the modified and working testcase, however
    > it's so close to the example in the IO:pipe doc that there doesn't
    > seem much point.
    >
    > >
    > > No need to mention IO::Handle (IO::pipe gets them for you).

    >
    > I'm using autoflush in my larger program, but you're right; it's not
    > needed in this testcase.
    >
    > >
    > >
    > > > my $fd = fileno($cr);
    > > > open(my $stdin, "<", \$fd) or die "STDIN open: $!";
    > > > *STDIN = $stdin;
    > > >
    > > > my $line = <STDIN>; # hopefully reading from the parent

    > >
    > > Not sure why you would want to do this anyway. You shouldn't be
    > > reading from STDIN - you want to read from the read-side of the pipe opened
    > > in the parent. Don't assume that just because your want to read from it
    > > you have to make it STDIN. STDIN is "STanDard INput" - reading from a pipe
    > > isn't "standard" in this sense.

    >
    > The children will each exec an external command which will read from
    > stdin, and the parent has to manage sending data to each.
    >
    > Thanks for your help "Big and Blue".



    Sorry, I spoke too soon. I'm still left with my original problem of
    how to attach the pipe to STDIN of the child. The various approaches
    I've tried either raise an invalid argument error or the child appears
    to read the number of the file descriptor rather than the data.
     
    john, Mar 15, 2005
    #5
  6. john

    john Guest

    -berlin.de (Anno Siegel) wrote in message news:<d16ekt$5mo$-Berlin.DE>...
    > john <> wrote in comp.lang.perl.misc:
    > > Hello everyone,
    > >
    > > I have a program which forks multiple children and needs to have
    > > bidirectional communication with each child. Each child needs to use
    > > STDIN and STDOUT to talk back to the parent.

    >
    > Have you considered IPC::Open2?
    >
    > Anno


    This is close to what I want because it connects the reader and writer
    filehandles to STDIN and STDOUT of the child, however I wanted to
    control the exec of the child myself, so that I could have a test
    harness within the same program file which simulates the child
    behaviour.

    I still don't understand why what I'm trying to do doesn't work but if
    no-one has any better ideas I'll try with IPC::Open2 (or maybe Open3
    if I need STDERR) as suggested.

    Thanks for tip.
     
    john, Mar 15, 2005
    #6
  7. john

    Big and Blue Guest

    john wrote:
    >
    > Sorry, I spoke too soon. I'm still left with my original problem of
    > how to attach the pipe to STDIN of the child. The various approaches
    > I've tried either raise an invalid argument error or the child appears
    > to read the number of the file descriptor rather than the data.


    Hav a look at the documentation for open. It gives (or gave...) an
    example of saving STDOUT and STDERR, opening somethign else on them and
    then restoring the original.

    Rearrange as appropriate for STDIN.



    --
    Just because I've written it doesn't mean that
    either you or I have to believe it.
     
    Big and Blue, Mar 15, 2005
    #7
  8. john

    john Guest

    Big and Blue <> wrote in message news:<>...
    > john wrote:
    > >
    > > Sorry, I spoke too soon. I'm still left with my original problem of
    > > how to attach the pipe to STDIN of the child. The various approaches
    > > I've tried either raise an invalid argument error or the child appears
    > > to read the number of the file descriptor rather than the data.

    >
    > Hav a look at the documentation for open. It gives (or gave...) an
    > example of saving STDOUT and STDERR, opening somethign else on them and
    > then restoring the original.
    >
    > Rearrange as appropriate for STDIN.


    Once again, I may be speaking too soon...
    It's not obvious from the perdoc, but the following seems to work with
    the IO::pipe version of the testcase...

    my $fd = fileno($pipe);
    open(STDIN, "<&$fd") or die "STDIN open: $!";

    I'll plug this back into my original program and see if it keeps
    working :)
    Thanks for your help.

    Here's the modified code...

    #!/usr/bin/perl
    use strict;
    use warnings;

    use IO::pipe;

    my $pipe = new IO::pipe or die 'pipe';

    my $pid = fork();
    if ($pid > 0) {

    # Parent
    $pipe->writer();

    print $pipe "hello!\n"; # to the child
    close($pipe);

    } else {
    # Child

    # Connect stdin to pipe

    $pipe->reader();

    my $fd = fileno($pipe);
    open(STDIN, "<&$fd") or die "STDIN open: $!";

    my $line = <STDIN>; # from the pipe ?
    chomp $line;
    print "child received: ($line)\n";
    close($pipe);
    exit(0);
    }

    wait;
     
    john, Mar 16, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    2
    Views:
    907
    Raymond DeCampo
    Aug 30, 2005
  2. Mike Finister
    Replies:
    1
    Views:
    745
  3. Mike Finister
    Replies:
    3
    Views:
    472
    Shug Boabie
    Jul 24, 2004
  4. Ben
    Replies:
    2
    Views:
    1,381
    jacob navia
    Aug 29, 2009
  5. Z W
    Replies:
    0
    Views:
    188
Loading...

Share This Page