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.

Reply via email to