NativeEventThread's run() method's infinite loop was implemented. The
loop looks like this:
while (null != this.browserControlCanvas) {
synchronized (this.browserControlCanvas.getTreeLock()) {
nativeProcessEvents(nativeWebShell);
if (null != listenersToAdd && !listenersToAdd.isEmpty()) {
tempEnum = listenersToAdd.elements();
while (tempEnum.hasMoreElements()) {
nativeAddListener(nativeWebShell,
(WebclientEventListener)
tempEnum.nextElement());
}
listenersToAdd.clear();
}
}
}
The problem I was observing was that
nativeProcessEvents(nativeWebShell) would crash due to the fact that
the nativeWebShell, which is actually an WebShellInitContext instance,
had been de-allocated. This de-allocation happens as a result of the
WindowControlImpl.delete() method, which looks like this:
public void delete()
{
Assert.assert(null != eventThread, "eventThread shouldn't be null at delete time");
eventThread.delete();
eventThread = null;
nativeDestroyInitContext(nativeWebShell);
nativeWebShell = -1;
}
nativeDestroyInitContext de-allocates the WebShellInitContextInstance.
You can see that the first thing done is to delete the eventThread().
NativeEventThread.delete() looks like this:
public void delete()
{
// setting this to null causes the run thread to exit
synchronized(this.browserControlCanvas.getTreeLock()) {
browserControlCanvas = null;
}
...
}
If you compare NativeEventThread.delete() with the infinite loop in
NativeEventThread.run(), you'll see that the fact that they both
synchronize on the same object doesn't protect us from the following
case:
NativeEventThread: The infinite loop checks to see if the
browserControlCanvas is null, then does synchronize on
browserControlCanvas.getTreeLock(), then calls processNativeEvents().
meanwhile
WindowControlImpl thread: delete() calls NativeEventThread.delete(),
which does synchronize on browserControlCanvas.getTreeLock().
During NativeEventThread.delete(), synchronized section,
browserControlCanvas is set to null.
NativeEventThread: because the check for null browserControlCanvas
occurrs outside of the synchronized block, it's not recheked, and
thus, the event loop continues to process when it shouldn't.
The fix is to change the event loop to look like this:
while (true) {
synchronized (this.browserControlCanvas.getTreeLock()) {
// this has to be inside the synchronized block!
if (null == this.browserControlCanvas) {
return;
}
nativeProcessEvents(nativeWebShell);
if (null != listenersToAdd && !listenersToAdd.isEmpty()) {
tempEnum = listenersToAdd.elements();
while (tempEnum.hasMoreElements()) {
nativeAddListener(nativeWebShell,
(WebclientEventListener)
tempEnum.nextElement());
}
listenersToAdd.clear();
}
}
}
git-svn-id: svn://10.0.0.236/trunk@64998 18797224-902f-48f8-a5cc-f745e15eee43
Here lies the code that comprises the java enhancers to mozilla. Authors: see the README files for each individual subdirectory Requirements: * JDK1.1.7 or greater (may work with lower versions, haven't checked). * M8 or post M8 mozilla tree * Perl 5 perl.exe must be in your path How To Build: * make it so the directory in which this file resides is a child of your top level mozilla directory * Copy the files .\config\buildpkg.bat and .\config\outofdate.pl to mozilla\config. These file were modified after M8 and the modifications are required to build java. * make sure the environment var JDKHOME is set to your jdk installation directory, ie SET JDKHOME=C:\jdk1.1.8 * type "nmake /f makefile.win all" and hope for the best * this should compile the clasess into %MOZ_SRC%\dist\classes Problems: * clobber_all doesn't remove the .class files from dist\classes. You have to do this manually. * post to netscape.public.mozilla.java newsgroup General notes: * Please update the ChangeLog (changelo) files in the subdirectories when you make changes.