puravida has asked for the wisdom of the Perl Monks concerning the following question:

Please look at the code below:

#!/usr/bin/env perl -w use strict; use IO::Pty; my $master = new IO::Pty; my $slave = $master->slave(); my $pid = fork(); die "Couldn't fork: $!" unless defined $pid; if ($pid) { $master->close_slave(); while ( !$master->eof ) { my $line = $master->getline; chomp $line; print "TIME: " . localtime() . " OUTPUT: " . $line . "\n"; if ( $line == 3 ) { $master->print("2\n"); $master->print("4\n"); $master->print("6\n"); } } wait(); } else { $master->close(); $master->make_slave_controlling_terminal(); $slave->print("1\n"); $slave->print("3\n"); $slave->print("5\n"); }

and the result is:

$ perl  realtime5d.pl
TIME: Thu Jul  3 21:05:10 2014 OUTPUT: 1
TIME: Thu Jul  3 21:05:10 2014 OUTPUT: 3
TIME: Thu Jul  3 21:05:10 2014 OUTPUT: 2
TIME: Thu Jul  3 21:05:10 2014 OUTPUT: 4
TIME: Thu Jul  3 21:05:10 2014 OUTPUT: 6

Question 1: I expect 1, 3, 2, 4, 6, 5, why 5 written to $slave is lost? If you look at the picture from here: http://en.wikipedia.org/wiki/Pseudo_terminal, the traffic is bidirectional from master <=> slave, no?

Question 2: How do I turn off the echo? i.e. I do not want to read what I wrote myself, 2, 4, 6 in this case.

Question 3: Above 5 line output was from Perl 5.16 on Mac OS X 10.9.3. I did not think it is OS dependent for this simple script, but when I run with Perl 5.8 on Linux kernel 2.6, I got the following:

$ perl realtime5d.pl 
TIME: Fri Jul  4 10:08:50 2014 OUTPUT: 1
TIME: Fri Jul  4 10:08:50 2014 OUTPUT: 3

It looks that the echo is turned off, but once I write to the master, the is no more reading from slave. Why?

Question 4: The other very similar script http://www.perlmonks.org/?node_id=1092227 produces the same behavior on Perl 5.16 on Mac OS X 10.9.3 and on Perl 5.8 on Linux kernel 2.6, what is the real difference that these two scripts that causes the different behavior?

Thanks.

Replies are listed 'Best First'.
Re: [IO::Pty] How to read from and write to slave?
by choroba (Cardinal) on Jul 04, 2014 at 06:40 UTC
    I don't know much about pseudo terminals. Just for curiosity, I tried your code on a Linux machine. I had to modify == to eq to prevent lots of warnings. I also get a different output if I change chomp to s/\s+$// (there was "\r" present). To reduce the output, I also print only if length $line. 2, 4, and 6 never get to the output, but sometimes, I get something like:
    TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 3 TIME: Fri Jul 4 08:38:34 2014 OUTPUT: 1

    Something weird's going on.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: [IO::Pty] How to read from and write to slave?
by zentara (Cardinal) on Jul 04, 2014 at 11:14 UTC
Re: [IO::Pty] How to read from and write to slave?
by rgiersig (Initiate) on Jul 09, 2014 at 13:16 UTC

    Please note that the slave immediately exits after sending the "5", thus implicitly closing the pty slave. Maybe this is the reason why the "5" is lost. A "sleep(1)" should help here.

    Regarding echoing: setting the slave to raw with "$slave->set_raw()" should turn off echoing. This could also help with the lost "5".

    Hope this helps,

    Roland

    PS: yes, ptys are VERY much black magic... :-)

      Thanks Roland for the hint. I did further test and found that the sleep place at the end of slave process does not matter, it has to be placed precisely before master talks each time in terms of time. It appears as if the master and slave cannot talk at the same time, or some kind of chaos will happen. This is demonstrated with the code below, and commented therein. In this simple example, we know when the master talks and we can place a sleep there. But in real situation, we do not know when the master talks, and how long it will talk, we have to have a general mechanism of control. I thought the control is provided by IO::Pty, or otherwise why we should have a pair of master and slave terminals. If we have to provide the control, then we can just use master or slave, no? Thanks a lot.
      #!/usr/bin/env perl -w use strict; use IO::Pty; my $master = new IO::Pty; my $slave = $master->slave(); my $pid = fork(); die "Couldn't fork: $!" unless defined $pid; if ($pid) { $master->close_slave(); while ( !$master->eof ) { my $line = $master->getline; chomp $line; print "TIME: " . localtime() . " OUTPUT: " . $line . "\n"; if ( $line == 3 or $line == 7 ) { my $j = $line++; $master->print("$j\n"); } } wait(); } else { $master->close(); $master->make_slave_controlling_terminal(); $slave->set_raw(); $slave->print("1\n"); $slave->print("3\n"); sleep 1; $slave->print("5\n"); $slave->print("7\n"); sleep 2; $slave->print("9\n"); $slave->print("11\n"); # sleep 3; } __END__ (1) with $master->print(), and without sleeps: $master->print("$j\n"); # sleep 1; # sleep 2; # sleep 3; We have the output: TIME: Wed Jul 9 11:27:53 2014 OUTPUT: 1 TIME: Wed Jul 9 11:27:53 2014 OUTPUT: 3 (2) Without $master->print(), and without sleeps: # $master->print("$j\n"); # sleep 1; # sleep 2; # sleep 3; We have the output: TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 1 TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 3 TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 5 TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 7 TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 9 TIME: Wed Jul 9 11:31:42 2014 OUTPUT: 11 (3) "sleep 3" at the end makes no difference in terms of output. (4) with $master->print(), and with "sleep 1": $master->print("$j\n"); sleep 1; # sleep 2; # sleep 3; We have the output: TIME: Wed Jul 9 11:41:05 2014 OUTPUT: 1 TIME: Wed Jul 9 11:41:05 2014 OUTPUT: 3 TIME: Wed Jul 9 11:41:06 2014 OUTPUT: 5 TIME: Wed Jul 9 11:41:06 2014 OUTPUT: 7 (5) with $master->print(), and with "sleep 2": $master->print("$j\n"); # sleep 1; sleep 2; # sleep 3; TIME: Wed Jul 9 11:42:52 2014 OUTPUT: 1 TIME: Wed Jul 9 11:42:52 2014 OUTPUT: 3 TIME: Wed Jul 9 11:42:54 2014 OUTPUT: 9 TIME: Wed Jul 9 11:42:54 2014 OUTPUT: 11 (6) with $master->print(), and with both "sleep 1" and "sleep 2": $master->print("$j\n"); sleep 1; sleep 2; # sleep 3; TIME: Wed Jul 9 11:43:31 2014 OUTPUT: 1 TIME: Wed Jul 9 11:43:31 2014 OUTPUT: 3 TIME: Wed Jul 9 11:43:32 2014 OUTPUT: 5 TIME: Wed Jul 9 11:43:32 2014 OUTPUT: 7 TIME: Wed Jul 9 11:43:34 2014 OUTPUT: 9 TIME: Wed Jul 9 11:43:34 2014 OUTPUT: 11 Conclusion: When master talks, the slave has to wait, otherwise what is written to slave is lost.