From: Robert M. <rm...@po...> - 2007-02-09 21:52:45
|
Robert May wrote: > I can see the problem clearly. It's because you're > destroying a window while in the middle of processing an event sent to > it, and the code isn't expecting that, and so ends up trying to access > some of the window's properties after they have been freed. I've got a > solution to most of it, but there are a couple of areas where I'm not > sure how to resolve it ... some more thought required, but I'll try to > get a fix into the next release. > > For the record, here's the shortest example I can come up with that > exhibits the problem: > > #!perl -w > use strict; > use warnings; > > use Win32::GUI(); > > my $mw; > > $mw = Win32::GUI::Window->new( > -onKeyDown => sub { undef $mw; return -1; }, > ); > > $mw->Show(); > Win32::GUI::Dialog(); > __END__ Hackers, Would you expect the above sample to exit cleanly? The problem is that if we destroy a window during a callback, perlud gets freed before the callback returns; the code then has a non-NULL perlud pointer, that points into freed memory. The fact that this only exhibits a crash on Win98 is, I think, just luck. I've now got checks in place in all the places that I can see that we attempt to access perlud after a callback, and the crash appears to be fixed, but I'm left with one issue: return -1 results in us trying to exit the Dialog() loop using PostMessage(hwnd, WM_EXITLOOP, (WPARAM) -1, 0); but hwnd has already been destroyed, so the message never gets delivered. In the above example pressing a key causes the window to disappear, but leaves Dialog() spinning, and the script never finishes. I can change the PostMessage(..) to PostThreadMessage(GetCurrentThreadId(), WM_EXITLOOOP, (WPARAM) -1, 0); and all tests pass, and I haven't (yet) found a problem with it, but it feels like quite a fundamental change to me. Can anyone see a problem with it, or propose a better solution? Or should I not worry? Regards, Rob. |