United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6857855 6.0u14 new plugin executing javascipt can hang IE
JDK-6857855 : 6.0u14 new plugin executing javascipt can hang IE

Details
Type:
Bug
Submit Date:
2009-07-07
Status:
Resolved
Updated Date:
2013-01-08
Project Name:
JDK
Resolved Date:
2009-10-28
Component:
deploy
OS:
windows_xp
Sub-Component:
plugin
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6u14
Fixed Versions:
6u18 (b04)

Related Reports
Backport:
Relates:

Sub Tasks

Description
A javascript invocation is hanging IE6.x.  This used to work in 5.0_x JVMs.

Attached to the bug report is the jstack traces.

Using windbg,
0:000> ~0kb 
ChildEBP RetAddr  Args to Child              
0013500c 7c90df4a 7c809590 00000002 00135038 ntdll!KiFastSystemCallRet
00135010 7c809590 00000002 00135038 00000001 ntdll!ZwWaitForMultipleObjects+0xc
001350ac 7e4195f9 00000002 001350d4 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
00135108 7752ebd6 00000001 00135150 000003e8 user32!RealMsgWaitForMultipleObjectsEx+0x13e
00135130 7752ecfd 00135150 000003e8 00135160 ole32!CCliModalLoop::BlockFn+0x80
00135158 77525fc1 ffffffff 00135250 00135188 ole32!ModalLoop+0x5b
00135168 77601efe 00197a28 00135250 00000000 ole32!SwitchSTA+0x21
00135188 7760108a 00135250 089cc9ac 001352ac ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0xd1
00135268 7752edaa 089cc9ac 0013537c 0013536c ole32!CRpcChannelBuffer::SendReceive2+0xc8
00135284 7752ed53 0013537c 0013536c 089cc9ac ole32!CCliModalLoop::SendReceive+0x1e
001352f0 7752cdb2 089cc9ac 0013537c 0013536c ole32!CAptRpcChnl::SendReceive+0x6f
00135344 77ef4db5 089cc9ac 0013537c 0013536c ole32!CCtxComChnl::SendReceive+0x113
...

0:000> dd (poi (089cc9ac  + 18) +8) 
00197a30  0000009c 00000dd0 17a59799 0b21bbb9

The COM call is blocked by pid 0x9c (156d) and thread id 0xdd0.  The stack trace of 0xdd0 is this thread.
"Thread-3" prio=6 tid=0x05ff8400 nid=0xdd0 runnable [0x0d50b000]
   java.lang.Thread.State: RUNNABLE
        at sun.plugin2.main.server.WindowsHelper.runMessagePump0(Native Method)
        at sun.plugin2.main.server.WindowsHelper.runMessagePump(Unknown Source)
        at sun.plugin2.main.server.IExplorerPlugin.runMessagePump(Unknown Source)
        at sun.plugin2.main.server.IExplorerPlugin.runMessagePump(Unknown Source)
        at sun.plugin2.main.server.IExplorerPlugin.access$400(Unknown Source)
        at sun.plugin2.main.server.IExplorerPlugin$1.waitForSignal(Unknown Source)
        at sun.plugin2.main.server.ResultHandler.waitForResult(Unknown Source)
        at sun.plugin2.main.server.AbstractPlugin.doJavaObjectOp(Unknown Source)
        at sun.plugin2.main.server.IExplorerPlugin.doJavaObjectOp(Unknown Source)
        at sun.plugin2.main.server.AbstractPlugin.javaObjectInvoke(Unknown Source)

                                    

Comments
EVALUATION

A simple test case for this issue can be found in Attachments section.
To reproduce, just open Test1.html with IE (whether from a local disk or
a web server) and press the button two times. The problem happens with
Plugin2 only.

A Java thread dump collected using jstack indicates that the "Applet 2
LiveConnect Worker Thread" in the client VM (java.exe) is stuck at
sun.plugin2.main.client.MessagePassingExecutionContext.getProxyList(),
and the browser VM (iexplore.exe) is inside runMessagePump().

Testing with an instrumented JDK confirmed this. The "Applet 2 LiveConnect
Worker Thread" issues an asynchronous GET_PROXY request to some other
thread. This request goes to a pipe, and the issuing thread waits for
a response, but it never gets any notification. Probably it happens because
the targeted thread is already waiting for some other event, and doesn't
read the message from the pipe. There is also some periodic message exchange
going through the same pipe. It happens every 10 seconds, even after IE hangs.

Thanks to Hao Dong's help, the root cause is found. The problem is that
Plugin2 could not get the correct Applet2Manager for the running applet.
When the applet in the second window tries to get a proxy, Plugin2 gets
a wrong Applet2Manager (it got the manager for the applet in the first window)
and used a wrong ExecutionContext to get the proxy list. The GetProxyMessage
has the AppletID of the first applet. On the browser side, the message is
routed to the main thread of the window where the first applet resides in.
That main thread is blocked doing a JavaScript call and no message pump is
running. Thus the browser deadlocked.

The message should be routed to the main thread of the second window on which
a message pump is running. There is actually a good FIXME in Plugin2Manager.java
about this semantic problem.

  /** Fetches the Plugin2Manager instance associated with the
       current AppContext. <P>

       NOTE: (FIXME) this method may return imprecise answers, in
       particular in the case where the old "class loader caching"
       mechanism is being used and we have multiple applets all
       running in the same AppContext. This definitely isn't the
       execution model we want to support long term going forward; it
       causes all sorts of encapsulation and termination problems. In
       the meantime, callers of this method should implicitly assume
       that it might return a "random" Plugin2Manager if multiple
       applets are running in the same AppContext. If more precise
       answers are required, such as for Java-to-JavaScript calls,
       different mechanisms should be used.
   */
   public static Plugin2Manager getCurrentManager() {

Well, the root is the class loader caching that Plugin2 want to get rid of
very much.

One possible workaround may be to disable classloading sharing in applet's
param <param name="classloader_cache" value="false">. We checked it with
the customer, and unfortunately it doesn't work in their application.
It causes their applet to be blank and hung. Their application relies
on the fact that the applets should be loaded by the same classloader.

Another workaround is to close a pop up applet window and open it again,
but the customer is reluctant to use it.
                                     
2009-09-29
SUGGESTED FIX

Applet's manager is stored in a thread local storage for all threads spawned from
the applet's lifecycle thread (e.g. threads created from init(), start(), stop(),
etc.) and the liveconnect worker thread for that applet.
Plugin2Manager.getCurrentManager() called on those threads should get
the correct Plugin2Manager.

The only problem left is the awt event queue because this thread is shared among
all applets in the AppContext. If EventQueue.invoke*() or SwingUtilities.invoke*()
are used, Plugin2Manager.getCurrentManager() won't get precise answer running
on the event queue thread.
                                     
2009-10-22



Hardware and Software, Engineered to Work Together