Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nsIBadCertListener and JVM death

4 views
Skip to first unread message

Greg Bowyer

unread,
Jun 12, 2007, 1:38:27 PM6/12/07
to
Hi all, as part of a project (which I am sure I have mentioned before in
here), I control the browser in an effort to provide a site-confidence /
Gomez a' like tool (these are tools that test websites).

A bug that came to my attention today is that when the thing hits a
broken secure certificate, it presents the (not present) end user with a
confirmation dialog asking them what to do.

I believe that JavaXPCom is not liking new threads that are created
inside XPCom / in the C side.

Since the thing is headless, I need to automatically handle this myself,
the code that I have implemented for this is nsIBadCertListener which I
then register with the componentRegistrar like so

-------------------------------------------------------------------------
// Register the certListener so that we can handle bad site certs
GenericXulRunnerFactory certHandlerFactory =
new GenericXulRunnerFactory(InvalidCertificateHandler.class);

compRegistrar.registerFactory(
nsIBadCertListener.NS_IBADCERTLISTENER_IID,
MozillaCOMConstants.COM_NAME_BAD_CERT_LISTENER,
MozillaCOMConstants.COM_BAD_CERT_LISTENER, certHandlerFactory
);
-------------------------------------------------------------------------

However when this code runs I get the lovely world of VM death, and
hence a h_pid_err_xxx.log.
Running this on my 1.9 build (which has debug info on) I get the
following information from XPCom / XULRunner which leads me to believe
that this is a fault in JavaXPCom's handling of threads. I assume that
whatever invokes the security prompt (Necko / libnspr prehaps ?!?!?) is
spawning a thread for it, which appears to confuse things.

Output includes .....
-------------------------------------------------------------------------
998 [main] DEBUG com.opodo.siterunner.xulrunner.XulRunnerTestCase -
Running XulRunnerTestCommand[command=open,value=,
target=https://webmail.freeshell.org,isBreakPoint=false,
metrics=com.opodo.siterunner.metrics.Metrics@c980c9]

WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file
/home/greg/projects/xulrunner/mozilla/toolkit/components/places/src/nsNavHistory.cpp,
line 400
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file
/home/greg/projects/xulrunner/mozilla/toolkit/components/places/src/nsNavHistory.cpp,
line 273
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file
/home/greg/projects/xulrunner/mozilla/toolkit/components/places/src/nsNavHistory.cpp,
line 400
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file
/home/greg/projects/xulrunner/mozilla/toolkit/components/places/src/nsNavHistory.cpp,
line 273
###!!! ASSERTION: reflow state computed incorrect width:
'reflowState.ComputedWidth() == size.width -
reflowState.mComputedBorderPadding.LeftRight()', file
/home/greg/projects/xulrunner/mozilla/layout/base/nsPresShell.cpp, line 6143
###!!! ASSERTION: reflow roots must not have visible overflow:
'desiredSize.mOverflowArea == nsRect(nsPoint(0, 0),
nsSize(desiredSize.width, desiredSize.height))', file
/home/greg/projects/xulrunner/mozilla/layout/base/nsPresShell.cpp, line 6159
1008 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener -
[JavaScript Error: "[Exception... "Component returned failure code:
0x80004005 (NS_ERROR_FAILURE) [nsIDocShellHistory.useGlobalHistory]"
nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame ::
chrome://global/content/bindings/browser.xml :: :: line 578" data:
no]" {file: "chrome://global/content/bindings/browser.xml" line: 582}]
1009 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener - My
component: Initial setup started
1010 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener -
[JavaScript Error: "Initial setup started" {file:
"chrome://siterunner/content/lib/utils.js" line: 17}]
1010 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener - My
component: Setup finished - ready to rock !!!
1010 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener -
[JavaScript Error: "Setup finished - ready to rock !!!" {file:
"chrome://siterunner/content/lib/utils.js" line: 17}]
1010 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener - Here
with a test case
1010 [main] INFO com.opodo.siterunner.xulrunner.ConsoleListener -
[xpconnect wrapped srITestCase @ 0x8895a70 (native @ 0x8896828)]
###!!! ASSERTION: nsSecureBrowserUIImpl not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file
/home/greg/projects/xulrunner/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp,
line 165
###!!! ASSERTION: nsSecureBrowserUIImpl not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file
/home/greg/projects/xulrunner/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp,
line 165
###!!! ASSERTION: nsSecureBrowserUIImpl not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file
/home/greg/projects/xulrunner/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp,
line 165
###!!! ASSERTION: nsSecureBrowserUIImpl not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file
/home/greg/projects/xulrunner/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp,
line 165
###!!! ASSERTION: nsJavaXPTCStub not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file
/home/greg/projects/xulrunner/mozilla/extensions/java/xpcom/src/nsJavaXPTCStub.cpp,
line 99
###!!! ASSERTION: Current thread not attached to given JVM instance: 'rc
== JNI_OK && env != nsnull', file
/home/greg/projects/xulrunner/mozilla/extensions/java/xpcom/src/nsJavaXPCOMBindingUtils.cpp,
line 975
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# SIGSEGV (0xb) at pc=0xa87ed21f, pid=6586, tid=2780609424
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_11-b03 mixed mode)
# Problematic frame:
# C [libxul.so+0xfae21f]
#
# An error report file with more information is saved as hs_err_pid6586.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
eService :: line 1004" data: no]
************************************************************
Couldn't convert chrome URL: chrome://branding/locale/brand.properties
++WEBSHELL 0x8600e00 == 1
++DOMWINDOW == 1
++DOMWINDOW == 2
Couldn't convert chrome URL: chrome://siterunner/locale/core.dtd
++WEBSHELL 0x87560a0 == 2
++DOMWINDOW == 3
Note: styleverifytree is disabled
Note: frameverifytree is disabled
++DOMWINDOW == 4
Note: verifyreflow is disabled

Process finished with exit code 134
-------------------------------------------------------------------------------------

The VM death report contains the following
-------------------------------------------------------------------------------------
Stack: [0xa5780000,0xa5f81000), sp=0xa5f7fbc0, free space=8190k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code,
C=native code)
C [libxul.so+0x54a1ea]
_ZN7JNIEnv_16CallObjectMethodEP8_jobjectP10_jmethodIDz+0xc
C [libxul.so+0x54e4aa]
C [libxul.so+0x4fb3fd]
C [libxul.so+0x4dcbe3]
C [libxul.so+0x4dd625]
C [libxul.so+0x4a031f] _Z14CallGetServicePKcRK4nsIDPPv+0x33
C [libxul.so+0x4a0652]
_ZNK33nsGetServiceByContractIDWithErrorclERK4nsIDPPv+0x22
C [libxul.so+0x4a0220]
_ZN13nsCOMPtr_base36assign_from_gs_contractid_with_errorERK33nsGetServiceByContractIDWithErrorRK4nsID+0x22
C [libpipnss.so+0x1904b]
C [libpipnss.so+0x1d8fb]
C [libpipnss.so+0x1eca4]
C [libssl3.so+0xe1f3]
C [libssl3.so+0xee3b]
C [libssl3.so+0xf246]
C [libssl3.so+0xf5ad]
C [libssl3.so+0x10269]
C [libssl3.so+0x11aa9]
C [libssl3.so+0x15d10]
C [libssl3.so+0x172ae]
C [libssl3.so+0x1740d]
C [libssl3.so+0x1b5a9]
C [libpipnss.so+0xf7bf]
C [libpipnss.so+0xe542]
C [libnspr4.so+0x23f7d]
-------------------------------------------------------------------------------------


This is happening for me with both xulrunner 1.9a (homebrew) and
xulrunner 1.8.1.3 (although without logging / debugging I am a little
more on the dark as for 1.8.1.3)

So ..
1) Is this an issue or bug with JavaXPCom itself ?
2) Am I being incredibly stupid, do I need to be doing anything like
wrapping up the created nsIBadCertListener implementation in a proxy,
and if so how do I go about doing this
3) Is there an alternative to this approach, I would like to keep the
thing rendering to its own managed window (rather than implement all the
glue for my own nsIWindowCreator etc, partly because I want to avoid any
code that has the potential to change the layout / behavior of pages,
but mostly because I am lazy)

Many thanks
Greg Bowyer

Michal Ceresna

unread,
Jun 12, 2007, 5:18:34 PM6/12/07
to dev-te...@lists.mozilla.org
On Tuesday 12 June 2007, Greg Bowyer wrote:
Hello,

> A bug that came to my attention today is that when the thing hits a
> broken secure certificate, it presents the (not present) end user with a
> confirmation dialog asking them what to do.

> Since the thing is headless, I need to automatically handle this myself,
> the code that I have implemented for this is nsIBadCertListener which I
> then register with the componentRegistrar like so

Isn't it possible to implement that using nsIPromptService?
This is what we do to solve the same problem as you have.

> However when this code runs I get the lovely world of VM death, and
> hence a h_pid_err_xxx.log.
> Running this on my 1.9 build (which has debug info on) I get the
> following information from XPCom / XULRunner which leads me to believe
> that this is a fault in JavaXPCom's handling of threads. I assume that
> whatever invokes the security prompt (Necko / libnspr prehaps ?!?!?) is
> spawning a thread for it, which appears to confuse things.

Most of the code in Mozilla is not thread-safe.

I mean, not multi-threaded in the sense as you know from java.
Mozilla mostly uses the concept of event queues to break
execution into smaller blocks.
E.g. all page rendering code, gui, mouse and key handling,
JS execution run on the same (GUI) thread.

Therefore, there are several mechanisms in mozilla code
that check that xpcom components are accessed in
a tread-safe way.

> ###!!! ASSERTION: nsJavaXPTCStub not thread-safe:
> '_mOwningThread.GetThread() == PR_GetCurrentThread()', file

For example, this check is implemented in AddRef and tests that
the method (current code) is executing on the same thread
that created instance of the xpcom component.
So, my estimate is that you have created an instance of XPCOM
object on a java thread A and then you try to access it on thread B.

> ###!!! ASSERTION: Current thread not attached to given JVM instance: 'rc
> == JNI_OK && env != nsnull', file
> /home/greg/projects/xulrunner/mozilla/extensions/java/xpcom/src/nsJavaXPCOM
>BindingUtils.cpp, line 975

This error occurs when a native thread tries to do a callback to java,
but because it is not attached to the jvm, it can not obtain
the jvm pointer.
This simplest solution without changes in javaxpcom is
1) implement your code in a way, that the callback occurs on GUI thread
2) reimplement this particular part of code as a native xpcom/c++ component

best regards,
Michal

Greg Bowyer

unread,
Jun 12, 2007, 6:48:58 PM6/12/07
to
Michal Ceresna wrote:
> On Tuesday 12 June 2007, Greg Bowyer wrote:
> Hello,
>
>> A bug that came to my attention today is that when the thing hits a
>> broken secure certificate, it presents the (not present) end user with a
>> confirmation dialog asking them what to do.
>> Since the thing is headless, I need to automatically handle this myself,
>> the code that I have implemented for this is nsIBadCertListener which I
>> then register with the componentRegistrar like so
> Isn't it possible to implement that using nsIPromptService?
> This is what we do to solve the same problem as you have.
Already implemented nsIPromptService, it doesn't allow to override this
behavior (unfortunately). :(

>> However when this code runs I get the lovely world of VM death, and
>> hence a h_pid_err_xxx.log.
>> Running this on my 1.9 build (which has debug info on) I get the
>> following information from XPCom / XULRunner which leads me to believe
>> that this is a fault in JavaXPCom's handling of threads. I assume that
>> whatever invokes the security prompt (Necko / libnspr prehaps ?!?!?) is
>> spawning a thread for it, which appears to confuse things.
>
> Most of the code in Mozilla is not thread-safe.
>
> I mean, not multi-threaded in the sense as you know from java.
> Mozilla mostly uses the concept of event queues to break
> execution into smaller blocks.
> E.g. all page rendering code, gui, mouse and key handling,
> JS execution run on the same (GUI) thread.
>
> Therefore, there are several mechanisms in mozilla code
> that check that xpcom components are accessed in
> a tread-safe way.

I was under this impression, that it was a event queue / pump system, to
be honest I seriously dislike threading in general and the entire design
of that is done so far puts the control in the hands of xpcom /
xulrunner (once the thread on which I create the mozilla embedding
blocks) I don't access anything from another thread.

>> ###!!! ASSERTION: nsJavaXPTCStub not thread-safe:
>> '_mOwningThread.GetThread() == PR_GetCurrentThread()', file
> For example, this check is implemented in AddRef and tests that
> the method (current code) is executing on the same thread
> that created instance of the xpcom component.

This is whats slightly got me, my chain of events is like so:
1) Java starts up, does the setup work for embedding
2) XPCom and moz embedding fires up, java blocks its thread as xpcom
runs the event loop
3) XPCom does some initial setup (on the xulrunner side)
4) All accesses are now done from XPCom to java, e.g. xpcom calls java
5) The work finishes, XPCom terminates itself, java does some minor
cleanup and the process ends

So during the setup I register creation factories for several things
including the nsIBadCertListener (but also an implementation of
nsIPromptService, which works correctly)

So once XPCom needs an instance of these components, surly that same
thread (inside xulrunner) obtains the factory from the component
registrar, creates the instance and then uses it.

So any thread change is happening inside xpcom / xulrunner and is out of
my control.

> So, my estimate is that you have created an instance of XPCOM
> object on a java thread A and then you try to access it on thread B.

Yup I thought the same, :(

>> ###!!! ASSERTION: Current thread not attached to given JVM instance: 'rc
>> == JNI_OK && env != nsnull', file
>> /home/greg/projects/xulrunner/mozilla/extensions/java/xpcom/src/nsJavaXPCOM
>> BindingUtils.cpp, line 975
> This error occurs when a native thread tries to do a callback to java,
> but because it is not attached to the jvm, it can not obtain
> the jvm pointer.
> This simplest solution without changes in javaxpcom is
> 1) implement your code in a way, that the callback occurs on GUI thread
> 2) reimplement this particular part of code as a native xpcom/c++ component

1) I think my code is already organised in a way which is most friendly
to XPCom, especially since the creation and useage of the
nsIBadCertListener should be being performed by it, rather than by myself.
However since I have avoided the dreaded threading question, by putting
the control into the hands of the C side, are there any pointers as to
slightly better organization.

2) Humm I was kind of afraid of this as an approach, I already have a
small amount of native code involved and would rather not have any more,
if this still turns out to be a requirement I would go with it, but it
raises the question of how to register the C++ implementation, since the
embedding setup is in the hands of java (novice question I know but one
I cant find any answers to)

I might take a snoop into the JavaXPCom code that is called inside
xulrunner / xpcom to see if I can work out whats wrong.

> best regards,
> Michal

Cheers
Greg

Greg Bowyer

unread,
Jun 12, 2007, 8:28:10 PM6/12/07
to
Greg Bowyer wrote:
The plot thickens ......

(This is long and slightly meandering)
Using a Javascript implementation of the same service I get the same
behavior as per bug 361149
(I am using the implementation as per this bug)
https://bugzilla.mozilla.org/show_bug.cgi?id=361148

On the first call life is good, and the implementation does as its told,
on the second call (with stale compreg.dat xpti.dat files) I get the
following in my logs.

------------------------------------------------------------------------------
###!!! ASSERTION: nsSecureBrowserUIImpl not thread-safe:

'_mOwningThread.GetThread() == PR_GetCurrentThread()', file

/home/greg/projects/xulrunner/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp,
line 165
Assertion failure: cx->thread->id == js_CurrentThreadId(), at
/home/greg/projects/xulrunner/mozilla/js/src/jsapi.c:829
----------------------------------------------------------------------------------

Again its looking to be the same sort of issue, with objects being
abused across threads,

More light on the "threading hates nsBadCertListener impls" comes from
this archaic bug
https://bugzilla.mozilla.org/show_bug.cgi?id=304286#c18
https://bugzilla.mozilla.org/show_bug.cgi?id=304286#c20
Also
https://bugzilla.mozilla.org/show_bug.cgi?id=243591

What I think is happening is that Necko or PSM is hitting the invalid
cert, and the calling out to get the implementation of
nsBadCertListener, it gets this expecting it to be native, or thread
safe, so the moment it's not it all falls apart (with in my case SegV)

Picking apart the xpi for the extension mentioned in....
https://bugzilla.mozilla.org/show_bug.cgi?id=361148

... I see that they fixed the issue by implementing the feature in C++
This leaves me going back to solution 2 again (although thankfully RMD
appear to be open-sourced, so I might be able to leverage this)

Any further ideas on this.

Many thanks
Greg Bowyer

Greg Bowyer

unread,
Jun 13, 2007, 10:20:24 AM6/13/07
to
Hi all, I have built a C++ native component for doing a task of handling
invalid certificates, anyone got any hints on how I register this with
XPCOM, I am assuming something to do with
nsIComponentRegistrar.registerFactoryLocation, but I can't figure it out.
0 new messages