crabbdean has asked for the wisdom of the Perl Monks concerning the following question:
Where I get stuck theory-wise is that what I'm executing would be a large directory read which in itself makes more subroutine calls while the filehandle is open. The callback is supposed to read and output what is read from the file handle. I'm just a little unclear how I'd write this into my MainLoop. The output is going to be put to a text widget or a log file.$this -> fileevent(FILEHANDLE, "readable", \&callback);
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Perl::TK - fileevent and script execution theory
by zentara (Cardinal) on Mar 12, 2004 at 17:17 UTC | |
While playing around, I've noticed some peculiarities with Tk::fileevent. If it's something with alot of output, you may need to throttle it a little bit. For instance, this first example will not produce output, but the second will. I need to study more on this. I believe it boils down to the filehandle needs to "be readable", it won't buffer for you. The following will run And the piper script
I'm not really a human, but I play one on earth. flash japh | [reply] [d/l] [select] |
by crabbdean (Pilgrim) on Mar 13, 2004 at 19:11 UTC | |
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. Dean 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
| [reply] [d/l] |
by merlyn (Sage) on Mar 14, 2004 at 04:23 UTC | |
-- Randal L. Schwartz, Perl hacker
| [reply] [d/l] |
by crabbdean (Pilgrim) on Mar 14, 2004 at 04:40 UTC | |
by zentara (Cardinal) on Mar 14, 2004 at 14:57 UTC | |
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:
I'm not really a human, but I play one on earth. flash japh | [reply] [d/l] |
|
Re: Perl::TK - fileevent and script execution theory
by crabbdean (Pilgrim) on Mar 14, 2004 at 12:19 UTC | |
Outputting to a text widget is all fine and dandy if what you are reading and outputting is small, because the population of the data to gui is relatively fast. But try executing a script or outputting a large amount of data like a listing of your entire hard drive and your gui freezes until it finishes the read. For all intensive purpose your gui looks like its crapped itself, while its off busily working in the background. The event driven nature of TK means it will process this event before continuing and updating the display or the next event. The TK::fileevent module is designed to execute a callback when a FileHandle becomes either writable or readable. Great sounds good!! Although, my problem came in the implementation of this, which you can read about in this node. Finally here is the solution below. The "$widget->idletasks" method helps with the updating of the display when the widget changes or in this case is populated with more data, which fixes the apparant freezing problem. Calling "idletasks" for the MainWindow or the text widget within the callback both worked although on the Text Widget would require less redraw and is most likely faster, hence the solution below. I found trying to call "idletasks" within the MainLoop didn't work. Below is the final solution. Hope that helps. Dean 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
| [reply] [d/l] |
by crabbdean (Pilgrim) on Mar 25, 2004 at 00:27 UTC | |
Update: It would seem more correct to put the whole bottom "sysread" if statement as and "else" to the "eof". See below.
Dean 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 | [reply] [d/l] [select] |