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

Here is my question Oh Monks! I'm trying to launch a tk dialog box to tell the user to wait until what i'm processing is done. To do this i'm forking the main program. The child process creates a main window that shows a please wait message. Once the parent process finishes what it does it tries to kill the child. What happens then is that although the program does not exit, i get this error message:

XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0" after 570 requests (559 known processed) with 0 events remaining.

and also it won't fire another tk main window. In the code below the call to resultsTk is ignored.

Here is my code:

my $pid = fork(); if(!defined($pid)){ print "Couldn't fork , continue"; } elsif($pid == 0){ &waitTk(); } else{ print $pid."\n"; my $min=$max; my $count=0; my $bpSum=0; foreach my $accID (keys %accDict){ #here do things sleep(20); } kill(1,$pid); waitpid($pid,0); #don't know if it's needed.Here just in case print "it got killed"; print $min."\n"; print $max."\n"; &resultsTk($min,$max); } sub resultsTk{ my ($rMin,$rMax) = @_; my $main = MainWindow->new(); $main->withdraw; my $dialog = $main->DialogBox(-buttons=>["Ok"]); $dialog->add("Label",-text=>"Min: $rMin, Max: $rMax")->pack(); my $button=$dialog->Show(); if($button eq "Ok"){ exit(0); } } sub waitTk{ local $SIG{HUP} =sub{exit(0);}; my $main = MainWindow->new(); $main->withdraw; my $dialog = $main->DialogBox(); $dialog->add("Label",-text=>"Please wait, calculating.")->pack(); my $button=$dialog->Show(); } Result: _TK_EXIT_(0) it got killed379 5168 XIO: fatal IO error 11 (Resource temporarily unavailable) on X server + ":0.0" after 570 requests (559 known processed) with 0 events remaining +.

Replies are listed 'Best First'.
Re: killing a child process which contains a Tk Main window
by zentara (Cardinal) on Dec 06, 2009 at 11:36 UTC
    I'm trying to launch a tk dialog box to tell the user to wait until what i'm processing is done. To do this i'm forking the main program.

    ... that is about as wrong a thing you can do with a gui toolkit..... you cannot go outside of the main process with any Tk widget...... you need to rethink your design...... unless all your Tk is contained in the forked code

    ...the problem is that Tk and almost gui's are event loop systems...... you cannot track a loop from one process to another, unless you use InterProcess Communication.....read perldoc perlipc

    .... write down what exactly you need done.....there are ways of doing what you want, but you are doing it backasswards

    ...then maybe someone will show you an example for Tk ipc on windows....like Tk GUI and Listen?

    ... in general: see tk-ps ..... you let Tk exist in the master loop, and spawn your process off thru an IPC.... you let the spawned program terminate and return to the Tk program, which holds your popup notification

    on windows you probably want something like IPC::Run or another windows friendly ipc module

    PS .. a few hours later..... there is another tip i will give you..... only create 1 mainwindow in any one program..... and use toplevels for everything else..... here is an idea for you

    #!/usr/bin/perl -w use strict; use warnings; use Tk; my $mw = MainWindow->new(); $mw->withdraw(); my $ftp_warn = $mw->messageBox( -title => 'Silly message', -message => "We are displaying a silly message, do you wish to conti +nue?", -type => 'YesNo', -icon => 'question', ); if ( $ftp_warn eq 'No' ) { exit; }else { my $msg2 = $mw->messageBox( -title => 'Really?', -message => "We displayed silly message and you wish to continue?" +, -type => 'OK', -icon => 'question', ); while (1){ print "hit control-c to exit\n"; sleep 1; } }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
Re: killing a child process which contains a Tk Main window
by Marshall (Canon) on Dec 06, 2009 at 10:03 UTC
    I don't know the answer to this question. I do know that this fork() stuff in Windows doesn't work like in *NIX. The PID's under Windows are negative meaning that this is a thread emulation, not a really new PID. There is some code below.

    When I write a Tk GUI with a long lived number cruncher app, I put up a Window with status and an "abort" button. This works because this is a single process and I call the thing managing the GUI progress bar often enough that the user won't notice any difference in performance if the user clicks on "stop". If you experiment with such an approach, you will find that updating the display is *very* expensive. On a 0-100% progress bar, you will find that you only want to update the display 100 times or maybe even only 50 times (once per 2%) (do a calculation and don't update the display more often than that). Looking about every 25 ms is way fast enough.

    The way that you have described your app, it is started via a command line, not from the user "clicking a button" to start the "number cruncher". The Tk GUI creates lots of objects and then MainLoop() is called and the user then clicks on some button(s).

    I think an equivalent question is: how to do I start a Tk GUI app and have my program punch one of the "go" buttons instead of the user having to do that?

    #!/usr/bin/perl -w use strict; #this code is for WinXP, not Unix $| =1; #buffering is off! print "my Parent ID at start is: $$\n"; my $pid = fork(); if (!defined($pid)) { die "Couldn't fork"; } if ($pid == 0) #I am a child ## { print "My child PID =$$\n"; my $c =0; while ($c<10) { print $c++; sleep(1); } print "\n"; } else # I am parent ## { print "Parent PID = $$\n"; } print "end of PID = $$ process ID\n"; __END__ PRINTS: my Parent ID at start is: 3640 Parent PID = 3640 end of PID = 3640 process ID My child PID =-1628 0123456789 (one digit per second) end of PID = -1628 process ID
Re: killing a child process which contains a Tk Main window
by zentara (Cardinal) on Dec 07, 2009 at 12:28 UTC
    ..... it sometimes takes me a few days to finish an answer :-) .... but see linux memory leak monitor ... where i fork a Tk window off..... to monitor a process's memory usage..... you can easily use the idea to run your task..... follow the recipe closely though..... you cannot access Tk widgets or methods across process boundaries.....you can have 2 separate Tk instances (event loops) running under the same parent process....but they act as entirely separate programs..... i use the MeM.pm on any perl script.... but it must be run under an X server of course

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku