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 | |
|
Re: Perl Tk and threads
by llancet (Friar) on Dec 21, 2009 at 06:01 UTC |