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

I have an application which is command line based and I decided to give it a face-lift by doing a GUI with Perl/Tk (on the Windows platform).

There is a button called 'GO' and its callback (&go_command) calls a sub that creates a new thread. As many nodes suggest, this won't work since Perl/Tk is not thread safe but I did conduct an experiment anyway to see for myself.

sub go_command { . . . my $thr = threads->create(\&sub1); if ($thr->is_joinable()) { $thr->join(); } } sub sub1 { print("In the thread\n"); }

When the thread is created and no join() or detach() is used against it, the application does not crash

However on the opposite case, the app crashes with "Free to wrong pool ....Perl/site/lib/Tk/Widget.pm line 98 during global destruction."

When a Perl/Tk app is exiting normally (e.g. by use of $mainwindow->destroy()) the following process is initiated:
All the widgets go through the following subroutine of Widget.pm:

sub DESTROY { my $w = shift; $w->destroy if ($w->IsWidget); }

which subsequently calls :

sub _Destroyed { my $w = shift; my $a = delete $w->{'_Destroy_'}; if (ref($a)) { while (@$a) { my $ent = pop(@$a); if (ref $ent) {....}

The main window is the only widget that goes through it last and the only widget that goes beyond the if (ref($a)) point .

It seems that when join or detach try to do their clean up, as perlthrtut says :

"join() also performs any OS cleanup necessary for the thread. That cleanup might be important, especially for long-running programs that spawn lots of threads",

they do something that triggers the destruction of the window as well.

Specifically when join() is called the sub DESTROY is called and it tries to go through the normal exiting process for every widget as described above.

However when it reaches point 'if (ref($a))' for the first widget to kill (in this case the button) it crashes with the "Free to wrong pool" message.

Now why would that be? I hypothesized that when the OS cleans up for the newly created thread it cleans up for the main thread as well.

Further investigation makes me think that Perl/Tk is hit by the same issue as Storable 2.09 as documented threads.t and make Storable thread-safe in that Perl Tk uses the same context for different threads and when the OS tries to clean up the memory pool of the newly created thread it cleans up the memory pool of the primary thread as well :

From threads.t about Storable:

as of 2.09 on win32 Storable w/threads dies with "free to wrong pool" since it uses the same context for different threads. since win32 perl implementation allocates a different memory pool for each thread using the a memory pool from one thread to allocate memory for another thread makes win32 perl very unhappy

Do you think that my assumption that both Tk and Storable 2.09 suffer because of the same issue, is correct? and what term would more accurately describe the situation?

1.Perl Tk is not thread safe? (I'm not calling any Tk components from multiple threads)

2.Perl Tk is not thread-friendly? (maybe better since I am calling a thread from within a Tk component?)

3.Or Perl Tk is not re-entrant?

Replies are listed 'Best First'.
Re: Perl Tk and threads
by zentara (Cardinal) on Dec 20, 2009 at 14:14 UTC
    Now why would that be?

    google for "perl threads copy on create"

    ...for Tk all 3 are correct....Tk goes out of it's way to bite you on the a*s when used with threads..... the real problem is that your experiments may work occaisionally, but then not when a different widget set involved, or different system speed or load..... etc etc etc... so you think you are figuring out a pattern.....then it turns out different on some other machine

    ... in Tk with threads, you need to keep all Tk code in the main thread of the parent process where the Tk mainloop runs....and you need to create the threads before any Tk code statements are made

    ...if you want to do what you are attempting..... create threads in gui button callbacks, or in some manner after the gui code has started.... use Gtk2....it is more advanced than Tk... see Gtk2 ....needs thread testing on a multi-threaded computer for how to do it, with the GLib::IdleAdd method, and the attempt at builtin object thread safety of Gtk2

    .... i don't know about Storable's thread safety problems, but you can probably get around the problem the same way as Tk.... create your thread first thing in the code, and confine the storable code to a single thread

    ....another trick to try, is to create your object in the parent thread, and try to pass it as a reference into the thread creation command

    $thread = threads->new(\&work , $object_ref);
    .... sometimes that works, sometimes not

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
Re: Perl Tk and threads
by llancet (Friar) on Dec 21, 2009 at 06:01 UTC
    Just surrender! According to my experience, the only way to use Tk and thread together is to build threads before any Tk widgets are initialized.
    If you need to use GUI and threads together, you may look at Gtk2, Gnome::Canvas......