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.