http://qs321.pair.com?node_id=498719

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

I'm trying to use fork in the middle of a Perl tk application on Win32 (Activestate v5.8.7). What I'd like to do is shell out to an external application without making the TK engine freeze while its waiting on the system'd process to finish. The obvious solution to this is to use fork, but when I try it:
my $pid = fork; if (!defined($pid)) { # display an error window return; } elsif () { # ... # generate temp.tcl exec("wish temp.tcl"); } else { return; }
I get a crazy panic: restartop error. Nothing beyond that. perldiag2 claims its something about the interpreter is trying to goto somewhere it can't, but that doesn't help me. Taking out the fork-code causes my application to work fine (beyond the freezing while its waiting for the subprocess to finish). Does anyone have any ideas?

Replies are listed 'Best First'.
Re: panic: restartop error using Perl Tk + fork() on Win32.
by BrowserUk (Patriarch) on Oct 10, 2005 at 07:23 UTC

    As metioned above, fork is emulated under Win32(using threads). So both branches of the fork are threads within the same process. When you then exec your command, the entire process is replaced by the exec'd command, which isn't very useful.

    To avoid that problem, skip fork completely (just forking and doing nothing is enough to crash Tk;), and use system 1, 'wish temp.tcl'; to run the command asynchronously.

    That works, but doesn't give you the opportunity to retrieve the return code from the command if that is important to you. If you need that, you can use threads::async, to run system synchronously in a thread, but asynchronously from the Tk thread.

    The following snippet will run the command from the edit field via system in a thread, retrieve the return code and post it to the tk screen. The progress bar is there to show that the tk interface doesn't stall. Indeed, you can click 'Doit' several times and multiple copies of the command will run concurrently:

    #! perl -slw use strict; use threads qw[ async ]; use Tk; use Tk::ProgressBar; use Tk::ROText; my $cmd = 'perl -le" print for 1 .. 10; sleep 10; exit 123"'; my $mw = MainWindow->new; my $pb = $mw->ProgressBar()->pack(); my $txt = $mw->ROText( -width => 3, -height => 1, )->pack( -side => 'left' ); my $edit = $mw->Entry( -width => 80, -textvariable => \$cmd )->pack( -side => 'left' ); my $btn = $mw->Button( -text => 'Doit', -command => sub{ async{ system $cmd; $txt->Contents( $? >> 8 ); }; } )->pack( -side => 'left' ); my $progress = 0; my $repeat = $mw->repeat( 100 => sub{ $progress = 0 if ++$progress == 100; $pb->value( $progress ); } ); MainLoop;

    When you terminate the tk window, you will see the following errors displayed:

    Use of uninitialized value in hash element at c:/Perl/site/lib/Tk/Trac +e.pm line 181. Attempt to free non-existent shared string 'Modified' during global de +struction.

    The first I have no idea about but is probably related to the second.

    The second is a consequence of using tk and threads together, but it only occurs when the app is terminating anyway and does not appear from my scant tests to indicate anything that would prevent the app from running correctly and completing successfully.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Thanks a million! I didn't know the system(1,...) trick, and I was shocked that it worked, but it did, so thanks!
Re: panic: restartop error using Perl Tk + fork() on Win32.
by neosamuri (Friar) on Oct 10, 2005 at 06:25 UTC
    You might want to look into Win32::Process . According to perlfork.pod one problem that windows has is that it does not have a fork system call, thus has to emulate the fork. The document then goes on to discuss the limitations of the emulation.

    Hopefully these links will be of some help.