-
Bug
-
Resolution: Fixed
-
P1
-
1.1.2
-
1.1.5
-
generic
-
generic
-
Verified
Dispose was called on a MenuItem at the same time that the MenuItem was
handling a WM_DRAWITEM message causing a trap when the class AwtMenu is freed.
Synchronization needs to be added to ensure that this cannot occur.
ingrid.yao@Eng 1997-08-14
More info provided by Oracle:
=================================
The trap occurs when dispose is called on a MenuItem at the same
time that the menu is being drawn.
The Window thread receives a WM_DRAWITEM message and starts drawing
the menu by calling the DrawItem methods in awt_Menu.cpp,
awt_MenuItem.cpp and awt_MenuBar.cpp.
At the same time a MenuItem is removed from the menu by another thread,
causing the peer code to delete the c++ object. If the memory
gets reallocated (and hence cleared), while the window thread is
accessing the deleted class, the window thread traps, trying to use 0
as a pointer.
I haven't had any luck reproducing this in a testcase, because with
a small applet the freed c++ object doesn't get reallocated immediately
and so the fact that the Window Thread is pointing to freed memory
doesn't cause a problem.
You could try to reproduce it by having multiple threads adding and
removing MenuItems, while you open and close the menu, causing the
menu to be painted repeatedly. Perhaps you could reduce the heap
size to simulate a larger applet.
Frame.setMenu() causes some similar problems because references to
the deleted c++ object are kept in a couple of places.
The fix I suggested was basically the same fix that has been put into
the Component dispose code, which is to wait until the windows thread
has finished processing messages before deleting the c++ object.
This solution is less than ideal, because a message may arrive
after the wait and before the delete. I figured that if this fix was
regarded, by Javasoft, as good enough for Components it would be
regarded as good enough for MenuItems:)
A better fix for both Component disposal and MenuItem disposal, would be:
- In _dispose, post a message WM_AWT_DESTROY to the Window Thread and
mark the c++ object as invalid.
- In response to WM_AWT_DESTROY, call DestroyWindow on the c++ object's window
- In WM_DESTROY processing, delete the c++ object; this is guaranteed to be the
last message dispatched to a window.
- check if the c++ object is marked as invalid before referencing it.
The c++ object has to be marked in some way because it contains a reference
to the Java object, which is invisible to the garbage collector. After
the _dispose call there are no other references to the Java object, so it
could be freed.
handling a WM_DRAWITEM message causing a trap when the class AwtMenu is freed.
Synchronization needs to be added to ensure that this cannot occur.
ingrid.yao@Eng 1997-08-14
More info provided by Oracle:
=================================
The trap occurs when dispose is called on a MenuItem at the same
time that the menu is being drawn.
The Window thread receives a WM_DRAWITEM message and starts drawing
the menu by calling the DrawItem methods in awt_Menu.cpp,
awt_MenuItem.cpp and awt_MenuBar.cpp.
At the same time a MenuItem is removed from the menu by another thread,
causing the peer code to delete the c++ object. If the memory
gets reallocated (and hence cleared), while the window thread is
accessing the deleted class, the window thread traps, trying to use 0
as a pointer.
I haven't had any luck reproducing this in a testcase, because with
a small applet the freed c++ object doesn't get reallocated immediately
and so the fact that the Window Thread is pointing to freed memory
doesn't cause a problem.
You could try to reproduce it by having multiple threads adding and
removing MenuItems, while you open and close the menu, causing the
menu to be painted repeatedly. Perhaps you could reduce the heap
size to simulate a larger applet.
Frame.setMenu() causes some similar problems because references to
the deleted c++ object are kept in a couple of places.
The fix I suggested was basically the same fix that has been put into
the Component dispose code, which is to wait until the windows thread
has finished processing messages before deleting the c++ object.
This solution is less than ideal, because a message may arrive
after the wait and before the delete. I figured that if this fix was
regarded, by Javasoft, as good enough for Components it would be
regarded as good enough for MenuItems:)
A better fix for both Component disposal and MenuItem disposal, would be:
- In _dispose, post a message WM_AWT_DESTROY to the Window Thread and
mark the c++ object as invalid.
- In response to WM_AWT_DESTROY, call DestroyWindow on the c++ object's window
- In WM_DESTROY processing, delete the c++ object; this is guaranteed to be the
last message dispatched to a window.
- check if the c++ object is marked as invalid before referencing it.
The c++ object has to be marked in some way because it contains a reference
to the Java object, which is invisible to the garbage collector. After
the _dispose call there are no other references to the Java object, so it
could be freed.