Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Re: Re: Perl::TK - fileevent and script execution theory

by crabbdean (Pilgrim)
on Mar 13, 2004 at 19:11 UTC ( #336401=note: print w/replies, xml ) Need Help??

in reply to Re: Perl::TK - fileevent and script execution theory
in thread Perl::TK - fileevent and script execution theory

Okay, after doing some researching, reading and testing this is where I'm at with this ...

Firstly, thanks zentara for the article, that was helpful. I also read through a tonne of other articles and code, even read through the Tk::ExecuteCommand module source code which was fantastic. Its all helped ratify my understanding and clarify certain aspects. The TK::ExecuteCommand module manages to achieve what I'm hoping to. So let me summise the problem and progress made so far....

The first of your two examples above uses a call to startpiper(). I found his wasn't necessary and didn't make a difference, not sure if that was strategically intentional or just something written in by yourself. Surprisingly in my testing before writing this thread I'd written two very similar examples as the ones you did. Seems we went down similar paths. But your code helped clarify a few things also. So thanks mate.

To help exaggerate the issue I face and show the type of problem I'm describing you'll see in the code below I've change the "ls -la" to "ls -laR c:". This attempts a much bigger call, freezing up the gui while it processes. Okay, so lets get into the juice of this theory and see if we can nut it out...

The "fileevent" call binds itself to the "fill_text_widget" subroutine when the "CHILD" filehandle becomes "readable". Because this is a piped stream if you do a blocking (<>) call on it you'll freeze the gui. It requires reading the stream in bite size pieces and updating the text widget bit by bit. My code below demonstrates this based on code from the "TK::ExecuteCommand" and one I found in another manual. Interestingly, MOST INTERESTINGLY, my gui still freezes .... but something quite strange happens!! If I grab the window bar across the top of the window and move the window you can see it rapidly processing and appending the directory listing to the text box. Also I included a "bell" into the subroutine, and you can hear it looping through, and with the bell it doesn't freeze - at each bell the screen updates. WHY???!!!! Is the gui having troubles keeping up with the refresh? This is what I'm not sure of.

So, any help is appreciated on this bit.

The Funkster of Mirth
Programming these days takes more than a lone avenger with a compiler. - sam
RFC1149: A Standard for the Transmission of IP Datagrams on Avian Carriers
#!/usr/bin/perl use warnings; use strict; use Tk; open(CHILD, "ls -laR h: |") or die "Can't open: $!"; my $mw = new MainWindow; my $t = $mw->Scrolled("Text",-width => 80, -height => 25, -wrap => 'no +ne'); $t->pack(-expand => 1); CHILD->autoflush(1); $mw->fileevent('CHILD', 'readable', [\&fill_text_widget, $mw]); $mw->after(500); MainLoop; sub fill_text_widget { my ($widget) = @_; if (eof(CHILD)) { $widget->fileevent('CHILD', "readable", undef); # cancel bindi +ng return ; } if (sysread ('CHILD', $_, 4096)) { $t->insert('end', $_); # Append the data read $t->yview('end'); $mw->bell; } else { # sysread returned undef. Problem with file $t->insert('end', "ERROR !!!"); $widget->fileevent('CHILD', "readable", undef); # cancel bindi +ng } }

Replies are listed 'Best First'.
•Re: Re: Re: Perl::TK - fileevent and script execution theory
by merlyn (Sage) on Mar 14, 2004 at 04:23 UTC
    I bet the continuously available fileevents are taking higher priority than the idleevents which is where the actual repaint is done. As Tk::Widget says:
    $widget->idletasks One of two methods which are used to bring the application +``up to date'' by entering the event loop repeated until all pendin +g events (including idle callbacks) have been processed. If the idletasks method is specified, then no new events or + errors are processed; only idle callbacks are invoked. This causes + opera- tions that are normally deferred, such as display updates a +nd win- dow layout calculations, to be performed immediately. The idletasks command is useful in scripts where changes ha +ve been made to the application's state and you want those changes +to appear on the display immediately, rather than waiting for +the script to complete. Most display updates are performed as i +dle callbacks, so idletasks will cause them to run. However, th +ere are some kinds of updates that only happen in response to event +s, such as those triggered by window size changes; these updates wi +ll not occur in idletasks.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Thanks Merlyn, that is exactly the answer I was looking for in theory (but I'm yet to test it). But it seems right. This is what I thought was happening but I wasn't sure how to resolve it. I have to race out the door now and will test this tomorrow, or later tonight. Two preliminary question that I'm sure I'll answer later anyway in testing:

      1. Do you write this into your Mainloop or into the end of the subroutine.
      2. Which widget is it assigned to? MainWindow or the text box?

      No biggy if you don't answer. It will only take me a few mins to work it out, but I have to race now. I'll post an update, conclusion and discussional results with my findings at the end of all this.

      The Funkster of Mirth
      Programming these days takes more than a lone avenger with a compiler. - sam
      RFC1149: A Standard for the Transmission of IP Datagrams on Avian Carriers
Re: Re: Re: Perl::TK - fileevent and script execution theory
by zentara (Archbishop) on Mar 14, 2004 at 14:57 UTC
    I'm experiencing your same problem with trying to figure out how fileevent works. I chose to use top for my experimenting. It's really tricky. I can get the output just fine with IPC3::Open, but fileevent won't read it. After googling on the topic, I see that fileevent hanging is a common problem, and it seems to boil down to how the "child" buffers it's output. And if you are'nt watching for it, Tk will hang until the child finishes outputting, which can be never for some utilities.

    I seem to have no problem with fileevent, if the child is a perl script and I set $|=1. But when calling external c apps, it's hit or miss, depending on the app. Sometimes app will not write output unless it has a tty to write to, and you need to use IO::Pty to fake a tty. Sometimes you have to do something to force it to give output. So it seems that there is no "easy rule" to follow which gives consistent results...each app you run as a child needs special consideration.

    Now I did find 1 example googling, which seems to be a "universal method" for getting fileevent to work, and it involves bypassing the pipe buffering problem by calling everything as a bash script, and reading bash's output. So maybe a "rule of thumb" is "start your child as a bash instance". Maybe "bash -c $cmd" would do it. Here it is:

    #!/usr/bin/perl -w use strict 'vars'; #by John Drukman $|=1; use Tk; use IPC::Open3; local *IN; local *OUT; local *ERR; my $pid=open3(\*IN,\*OUT,\*ERR,'/bin/sh'); my $inwin=new MainWindow; my $entry=$inwin->Entry(-width => 80)->pack; $inwin->Button(-text => 'Send', -command => \&send_to_shell)->pack; my $outwin=new MainWindow; my $textwin=$outwin->Text(-width => 80, -height => 24, -state => 'disabled')->pack; $outwin->fileevent(OUT,'readable',\&get_from); MainLoop; sub send_to_shell { my $cmd=$entry->get() . "\n"; write_textwin("> $cmd"); print IN $cmd; } sub get_from { my $buf=''; sysread OUT,$buf,4096; write_textwin($buf); } sub write_textwin { my $str=shift; $textwin->configure(-state=>'normal'); $textwin->insert('end',$str); $textwin->see('end'); $textwin->configure(-state=>'disabled'); } __END__

    I'm not really a human, but I play one on earth. flash japh

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://336401]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (10)
As of 2018-06-22 08:35 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (122 votes). Check out past polls.