Closed
Bug 340022
Opened 19 years ago
Closed 19 years ago
Virtual machine deadlock can happen on finalization of Java XPCOM proxies
Categories
(Core Graveyard :: Java to XPCOM Bridge, defect)
Tracking
(Not tracked)
RESOLVED
FIXED
People
(Reporter: ttudor, Assigned: jhpedemonte)
Details
(Keywords: fixed1.8.1)
Attachments
(1 file)
|
880 bytes,
patch
|
jhpedemonte
:
review+
jhpedemonte
:
approval-branch-1.8.1+
|
Details | Diff | Splinter Review |
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Build Identifier:
CONTEXT :
The java garbage collector can be (and in many actual implementations is) multi-threaded. A multi-threaded gc often uses a special, finalizer thread for object finalization.
Suppose we have java app with 2 threads: the main one - MainThread - and the finalizer one - FinalizeThread.
MainThread is the UI thread for both the app and the embedded mozilla and works around an event loop. Our app also contains (at least) one displayed mozilla window. An event happens in the mozilla window (like a mouse click). It is read in the event loop and dipatched to mozilla.
The general pattern of event processing in mozilla (see PL_ProcessPendingEvents()) is :
a. Enter monitor of the thread
b. Process events
c. Exit monitor of the thread
Step b. (that actually happens in http://lxr.mozilla.org/mozilla1.8.0/source/xpcom/threads/plevent.c#1327) can translate to a call to java code (e.g. a click in the mozilla window can generate a SWT.Activate event that will be dispatched to various registered event listeners). Let's suppose that this java code calls (through jni) an xpcom method.
While MainThread is processing step b, FinalizerThread starts running and finalizing a proxy (is in finalizeProxy() in nsJavaWrapper.cpp)
BUG :
1. FinalizerThread acquires the global gJavaXPCOMLock (http://lxr.mozilla.org/mozilla1.8.0/source/extensions/java/xpcom/nsJavaWrapper.cpp#1731).
2. FinalizerThread deletes the corresponding JavaXPCOMInstance (http://lxr.mozilla.org/mozilla1.8.0/source/extensions/java/xpcom/nsJavaWrapper.cpp#1754).
The destructor of JavaXPCOMInstance gets invoked (http://lxr.mozilla.org/mozilla1.8.0/source/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp#688).
As we are not on the main thread the NS_ProxyRelease() calls in the above mentioned destructor will need to acquire the xpcom monitor of the MainThread. MainThread currently own its monitor so FinalizerThread BLOCKS waiting for MainThread
3. MainThread proceeds with the xpcom call. As it uses or returns a xpcom object (this is one last supposition) it will call the NativeToJavaProxy::Find() method. This method starts by trying to acquire the global gJavaXPCOMLock which is held by FinalizeThread. So MainThread BLOCKS waiting for FinalizeThread.
4. DEADLOCK.
This seems a highly hypothetical scenario but it actually happens. With the hack described in bug 339947 it is pretty frequent.
Reproducible: Sometimes
Proposed solution :
This is a simple one. In the finalizeProxy() method (nsJavaWrapper.cpp) we should explicitly release the gJavaXPCOMLock autolock (through lock.unlock()) before deleting the JavaXPCOMInstance :
if (gJavaXPCOMLock) {
nsAutoLock lock(gJavaXPCOMLock);
...
if (gJavaXPCOMInitialized) {
// Get native XPCOM instance
nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
if (NS_SUCCEEDED(rv)) {
JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
...
// !!!! UNLOCK BEFORE DELETING
lock.unlock();
// !!!! THIS IS ALL
delete inst;
}
| Reporter | ||
Comment 1•19 years ago
|
||
Patch for the above mentioned solution.
| Assignee | ||
Updated•19 years ago
|
Attachment #224175 -
Flags: review+
Attachment #224175 -
Flags: approval-branch-1.8.1+
| Assignee | ||
Comment 2•19 years ago
|
||
Checked in to trunk and 1.8 branch. ->FIXED
Updated•11 years ago
|
Product: Core → Core Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•