zentara has asked for the wisdom of the Perl Monks concerning the following question:
This works fine and dosn't block because STDERR is sent to STDOUT. However the original poster had to ask for them to be separated, and it turned out to be trickier than I thought. So I'm posting the code I came up with below, and wondering if it's the best way to do it. At first I thought I could just read ERROR like READ and just print out both....but no...the filehandles blocked each other and the script would hang.#!/usr/bin/perl use warnings; use strict; use IPC::Open3; #interface to "bc" calculator #my $pid = open3(\*WRITE, \*READ, \*ERROR,"bc"); my $pid = open3(\*WRITE, \*READ,0,"bc"); #if \*ERROR is false, STDERR is sent to STDOUT while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; #get the answer from bc chomp(my $answer = <READ>); print "$query = $answer\n"; }
Also a few specific questions:
(1.) If I don't put the select(undef,undef,undef,.01) delay in, the script gives it's output on the next entry. Try it and see what I mean, the output is delayed by 1 cycle. The delay fixes it.
(2.) I did the sysread with a size of 4096. How can I just read the size of the filehandle? I tried using "-s ERROR" and "-s READ" instead of 4096, but would get no output.
(3.) Is there a way to do this without IO::Select?
#!/usr/bin/perl use warnings; use strict; use IPC::Open3; use IO::Select; #interface to "bc" calculator my $pid = open3(\*WRITE, \*READ,\*ERROR,"bc"); my $selread = new IO::Select(); my $selerror = new IO::Select(); $selread->add(\*READ); $selerror->add(\*ERROR); my($error,$answer)=('',''); while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; #timing delay needed tp let bc output select(undef,undef,undef,.01); #see which filehandles have output for debugging # if($selread->can_read(0)){print "ready->read\n"} # if($selerror->can_read(0)){print "ready->error\n"} #get any error from bc sysread(ERROR,$error,4096) if $selerror->can_read(0); if($error){print "ERROR-> $error\n"} #get the answer from bc sysread(READ,$answer,4096) if $selread->can_read(0); if($answer){print "$query = $answer\n"} ($error,$answer)=('',''); }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: IPC::Open3 and blocking filehandles
by sgifford (Prior) on Oct 17, 2003 at 20:34 UTC | |
by zentara (Cardinal) on Oct 18, 2003 at 00:12 UTC | |
by sgifford (Prior) on Oct 18, 2003 at 02:55 UTC | |
by zentara (Cardinal) on Oct 19, 2003 at 13:37 UTC | |
by sgifford (Prior) on Oct 20, 2003 at 05:31 UTC | |
|
Re: IPC::Open3 and blocking filehandles
by pg (Canon) on Oct 17, 2003 at 19:54 UTC |