Closed Bug 15261 Opened 25 years ago Closed 25 years ago

[DOGFOOD]CRASH when creating new profile

Categories

(Core Graveyard :: Profile: BackEnd, defect, P3)

x86
All

Tracking

(Not tracked)

VERIFIED FIXED

People

(Reporter: sspitzer, Assigned: vidur)

References

Details

(Whiteboard: [PDT+])

run -installer
hit new to create a new profile
create profile, and hit finish

crash.

here's a patch to fix the problem:
Index: jsstr.c
===================================================================
RCS file: /cvsroot/mozilla/js/src/jsstr.c,v

retrieving revision 3.12
diff -p -r3.12 jsstr.c
*** jsstr.c     1999/09/28 23:10:55     3.12
--- jsstr.c     1999/09/30 18:00:03
*************** js_GetStringBytes(JSString *str)
*** 2379,2384 ****
--- 2379,2386 ----
      JSHashNumber hash;
      JSHashEntry *he, **hep;

+     if (!str) return NULL;
+
      JS_ACQUIRE_LOCK(deflated_string_cache_lock);

      cache = GetDeflatedStringCache();


here's the stack:

#0  0x400c9896 in js_GetStringBytes (str=0x0) at jsstr.c:2394
#1  0x4007ac12 in js_ReportUncaughtException (cx=0x8381b38) at jsexn.c:655
#2  0x40057daa in JS_CallFunction (cx=0x8381b38, obj=0x841b160, fun=0x8537250,
argc=1, argv=0xbfffeba4, rval=0xbfffea8c) at jsapi.c:2652
#3  0x403df04a in nsJSContext::CallFunction (this=0x8381618, aObj=0x841b160,
aFunction=0x8537250, argc=1, argv=0xbfffeba4, aBoolResult=0xbfffeaf4) at
nsJSEnvironment.cpp:228
#4  0x40417585 in nsJSEventListener::HandleEvent (this=0x8537488,
aEvent=0x8579e08) at nsJSEventListener.cpp:103
#5  0x40c33840 in nsEventListenerManager::HandleEvent (this=0x8537088,
aPresContext=@0x821e9b8, aEvent=0xbfffee98, aDOMEvent=0xbfffee40, aFlags=7,
aEventStatus=@0xbffff1a8) at nsEventListenerManager.cpp:646
#6  0x408a50cd in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/components/librdf.so
#7  0x40c378c2 in nsEventStateManager::CheckForAndDispatchClick (this=0x8535d10,
aPresContext=@0x821e9b8, aEvent=0xbffff288, aStatus=@0xbffff1a8) at
nsEventStateManager.cpp:947
#8  0x40c36535 in nsEventStateManager::PostHandleEvent (this=0x8535d10,
aPresContext=@0x821e9b8, aEvent=0xbffff288, aTargetFrame=0x851b828,
aStatus=@0xbffff1a8, aView=0x8291548) at nsEventStateManager.cpp:418
#9  0x40c7d18d in PresShell::HandleEvent (this=0x82b09e0, aView=0x8291548,
aEvent=0xbffff288, aEventStatus=@0xbffff1a8) at nsPresShell.cpp:2091
#10 0x41019499 in nsView::HandleEvent (this=0x8291548, event=0xbffff288,
aEventFlags=28, aStatus=@0xbffff1a8, aHandled=@0xbffff14c) at nsView.cpp:827
#11 0x41023b23 in nsViewManager::DispatchEvent (this=0x84f4a30,
aEvent=0xbffff288, aStatus=@0xbffff1a8) at nsViewManager.cpp:1662
#12 0x410175f4 in HandleEvent (aEvent=0xbffff288) at nsView.cpp:62
#13 0x40529a20 in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#14 0x405297bc in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#15 0x40529ae0 in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#16 0x4052ab7d in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#17 0x4052b746 in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#18 0x406b879d in ?? () from /usr/lib/libgtk-1.2.so.0
#19 0x40680037 in ?? () from /usr/lib/libgtk-1.2.so.0
#20 0x4067f52f in ?? () from /usr/lib/libgtk-1.2.so.0
#21 0x4067d800 in ?? () from /usr/lib/libgtk-1.2.so.0
#22 0x406b05b8 in ?? () from /usr/lib/libgtk-1.2.so.0
#23 0x406551a2 in ?? () from /usr/lib/libgtk-1.2.so.0
#24 0x406544da in ?? () from /usr/lib/libgtk-1.2.so.0
#25 0x406f7ab2 in ?? () from /usr/lib/libgdk-1.2.so.0
#26 0x407212c6 in ?? () from /usr/lib/libglib-1.2.so.0
#27 0x40721801 in ?? () from /usr/lib/libglib-1.2.so.0
#28 0x40721979 in ?? () from /usr/lib/libglib-1.2.so.0
#29 0x40653f3a in ?? () from /usr/lib/libgtk-1.2.so.0
#30 0x405144c9 in ?? () from
/builds/seth/seamonkey/mozilla/dist/bin/libwidget_gtk.so
#31 0x4038dee1 in nsAppShellService::Run (this=0x809edf0) at
nsAppShellService.cpp:461
#32 0x409f77a6 in nsProfile::LoadDefaultProfileDir (this=0x811f698,
profileURLStr=@0xbffff8a4) at nsProfile.cpp:245
#33 0x409f73d7 in nsProfile::StartupWithArgs (this=0x811f698,
cmdLineArgs=0x8071678) at nsProfile.cpp:159
#34 0x804b22b in main1 (argc=2, argv=0xbffffa54) at nsAppRunner.cpp:548
#35 0x804b759 in main (argc=2, argv=0xbffffa54) at nsAppRunner.cpp:702
#36 0x4028bcb3 in ?? () from /lib/libc.so.6
Seth, shouldn't js_GetStringBytes assert str instead?  NULL might be a
reasonable value to return in a non-debug build, but I'm guessing that calling
js_GetStringBytes with a NULL argument is an indicator of some other problem
that we'd rather catch earlier rather than handle in this out of band way.

(Also, a Brendan-nit as this is Brendan code; consistent formatting puts the
if-body on a new line.)
JS_GetStringBytes should perhaps assert, but the patch is bogus.  You'd just
have to check the return value of JS_GetStringBytes instead of whatever is
giving you that NULL pointer.  If a JSAPI function is returning a NULL |JSString
*|, it's probably telling you that something went wrong.
So hang on a sec: what is js_ReportUncaughtException doing calling it with a
NULL pointer?  bad code! bad!
accepting.  marking all milestone 11.
what's wrong with bulletproofing js_GetStringBytes() to not crash if called with
null.

Something bad is probably happening, and after checking in the bulletproofing,
I can re-assign this bug to a JS person for inspection.

crashing is never a good thing.
a different patch, but the same idea:
prevent js_GetStringBytes() from crashing, if it was passed a null.

Index: jsstr.c
===================================================================
RCS file: /cvsroot/mozilla/js/src/jsstr.c,v
retrieving revision 3.12
diff -r3.12 jsstr.c
2381a2382
>
2394,2401c2395,2396
<           bytes = js_DeflateString(NULL, str->chars, str->length);
<           if (bytes) {
<               if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
<                   deflated_string_cache_bytes += str->length;
<               } else {
<                   free(bytes);
<                   bytes = NULL;
<               }
---
>           if (!str) {
>               bytes = NULL;
2402a2398,2408
>             else {
>                   bytes = js_DeflateString(NULL, str->chars, str->length);
>                   if (bytes) {
>                       if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
>                           deflated_string_cache_bytes += str->length;
>                       } else {
>                           free(bytes);
>                           bytes = NULL;
>                       }
>                   }
>          }

can I get one you js guys to review this, and then take over the bug and see why
js_GetStringBytes() was getting called with null?
Assignee: sspitzer → mccabe
Status: ASSIGNED → NEW
Sorry, my code (it was once) does not null-check at every damn layer, just in
case someone screwed up a layer above, when all layers are within the JS engine.
That way lies performance death by a thousand cuts, and code bloat, and mental
slackness (no offense to sspitzer, who is new on scene).

All js_* routines are internal to the engine.  JS_* routines may well null-check
as they are relatively infrequent API calls -- but high-frequency ones may not,
again to hoist the stupidity tax out to callers.

In this case, the bug is in js_ReportUncaughtException, and belongs to mccabe.
Why didn't he take it?  Here it comes!

/be
Severity: normal → major
fair enough.  you JS guys run a tight ship.

The bug still exists (at least on Linux).  To reproduce, do this:

$ mv ~/.mozilla ~/.mozilla-old
$ ./mozilla-apprunner.sh

hit the new button to bring up the create profile wizard
hit next, then hit finished

crash.
Assignee: mccabe → rogerl
Roger Lawrence is doing exception goo currently.  Roger, to you...

As far as not crashing on NULL...  Silently accepting NULL and returning is a
dual behavior, and a mistake.  Functions are best designed to do *one* thing.
Yes, maybe we shouldn't crash in this situation in a shipping product, but this
situation should be loudly flagged to developers.  Crashing is one way to raise
this flag.
rogerl, if you need help getting set up to reproduce this, give me a call at
x4129.  you can come over to my cube and we can debug it.
Status: NEW → ASSIGNED
The problem is that damn null string - it "shouldn't" happen since it's origin
is a 'toString' call on an exception object.

sspitzer - thanks for the offer, if i can't reproduce it I'll stop by.
*** Bug 15197 has been marked as a duplicate of this bug. ***
*** Bug 15075 has been marked as a duplicate of this bug. ***
An exception object is being created to reflect a JS error that has occurred but
the context that has been passed in is missing the exception prototype objects -
so the 'toString' method is not found and a null string created and ...

I don't understand why the context is missing the exception prototypes, they're
created as part of InitStandardClasses along with all the other native stuff and
yet are not available when the error occurs. The contxet being passed in looks
fine in all other regards. Is there any chance that a 'non-standard' context is
being used?
Status: ASSIGNED → RESOLVED
Closed: 25 years ago
Resolution: --- → FIXED
fixed.  vidur's patch has been checked in with rogerl's blessing.
Status: RESOLVED → VERIFIED
builds for 19991007 Win and Linux
no more crashing!
Status: VERIFIED → REOPENED
I want to re-open this since I think another bug is being hidden by the patch.
What's happenning is that the global object in the context being used to execute
the 'onclick' script has already been blown away by clearScope called from :

JS_ClearScope(JSContext * 0x01fe22e0, JSObject * 0x01c75960) line 2034 + 17
bytes
GlobalWindowImpl::SetNewDocument(GlobalWindowImpl * const 0x01fe24a4,
nsIDOMDocument * 0x00000000) line 286 + 32 bytes
DocumentViewerImpl::~DocumentViewerImpl() line 259
DocumentViewerImpl::`scalar deleting destructor'(unsigned int 0x00000001) + 15
bytes
DocumentViewerImpl::Release(DocumentViewerImpl * const 0x0200c1d0) line 217 + 99
bytes
nsWebShell::Destroy(nsWebShell * const 0x01fe1330) line 1161 + 27 bytes
nsWebShellWindow::Close(nsWebShellWindow * const 0x01fe18b0) line 454
GlobalWindowImpl::Close(GlobalWindowImpl * const 0x01fe24a8) line 1260
nsAppShellService::Quit(nsAppShellService * const 0x00d232b0) line 488
XPTC_InvokeByIndex(nsISupports * 0x00d232b0, unsigned int 0x00000005, unsigned
int 0x00000000, nsXPTCVariant * 0x0012d0cc) line 135
nsXPCWrappedNativeClass::CallWrappedMethod(JSContext * 0x01fe22e0,
nsXPCWrappedNative * 0x01eaa930, const XPCNativeMemberDescriptor * 0x01ead1dc,
nsXPCWrappedNativeClass::CallMode CALL_METHOD, unsigned int 0x00000000, long *
0x01cf70e4, long * 0x0012d26c) line 767 + 44 bytes
WrappedNative_CallMethod(JSContext * 0x01fe22e0, JSObject * 0x01d26b48, unsigned
int 0x00000000, long * 0x01cf70e4, long * 0x0012d26c) line 186 + 34 bytes
js_Invoke(JSContext * 0x01fe22e0, unsigned int 0x00000000, unsigned int
0x00000000) line 672 + 26 bytes
js_Interpret(JSContext * 0x01fe22e0, long * 0x0012dae4) line 2248 + 15 bytes
js_Invoke(JSContext * 0x01fe22e0, unsigned int 0x00000000, unsigned int
0x00000000) line 688 + 13 bytes
js_Interpret(JSContext * 0x01fe22e0, long * 0x0012e318) line 2248 + 15 bytes
js_Invoke(JSContext * 0x01fe22e0, unsigned int 0x00000000, unsigned int
0x00000000) line 688 + 13 bytes
js_Interpret(JSContext * 0x01fe22e0, long * 0x0012eb4c) line 2248 + 15 bytes
js_Invoke(JSContext * 0x01fe22e0, unsigned int 0x00000001, unsigned int
0x00000000) line 688 + 13 bytes
js_Interpret(JSContext * 0x01fe22e0, long * 0x0012f380) line 2248 + 15 bytes
js_Invoke(JSContext * 0x01fe22e0, unsigned int 0x00000001, unsigned int
0x00000002) line 688 + 13 bytes
js_InternalCall(JSContext * 0x01fe22e0, JSObject * 0x01c74d98, long 0x01c74da0,
unsigned int 0x00000001, long * 0x0012f500, long * 0x0012f4b8) line 765 + 15
bytes
JS_CallFunction(JSContext * 0x01fe22e0, JSObject * 0x01c74d98, JSFunction *
0x0201f7f0, unsigned int 0x00000001, long * 0x0012f500, long * 0x0012f4b8) line
2650 + 32 bytes
nsJSContext::CallFunction(nsJSContext * const 0x01fe2450, void * 0x01c74d98,
void * 0x0201f7f0, unsigned int 0x00000001, void * 0x0012f500, int * 0x0012f4fc)
line 231 + 39 bytes
nsJSEventListener::HandleEvent(nsIDOMEvent * 0x02108a80) line 103 + 48 bytes
nsEventListenerManager::HandleEvent(nsIPresContext & {...}, nsEvent *
0x0012f7f8, nsIDOMEvent * * 0x0012f7c0, unsigned int 0x00000007, nsEventStatus &
nsEventStatus_eIgnore) line 646 + 21 bytes
RDFElementImpl::HandleDOMEvent(RDFElementImpl * const 0x0201ff90, nsIPresContext
& {...}, nsEvent * 0x0012f7f8, nsIDOMEvent * * 0x0012f7c0, unsigned int
0x00000001, nsEventStatus & nsEventStatus_eIgnore) line 2894
nsEventStateManager::CheckForAndDispatchClick(nsEventStateManager * const
0x02023b20, nsIPresContext & {...}, nsMouseEvent * 0x0012fb6c, nsEventStatus &
nsEventStatus_eIgnore) line 1003 + 42 bytes
nsEventStateManager::PostHandleEvent(nsEventStateManager * const 0x02023b20,
nsIPresContext & {...}, nsGUIEvent * 0x0012fb6c, nsIFrame * 0x02027ec0,
nsEventStatus & nsEventStatus_eIgnore, nsIView * 0x0200ea60) line 474 + 24 bytes
PresShell::HandleEvent(PresShell * const 0x0200e604, nsIView * 0x0200ea60,
nsGUIEvent * 0x0012fb6c, nsEventStatus & nsEventStatus_eIgnore) line 2102 + 43
bytes
nsView::HandleEvent(nsView * const 0x0200ea60, nsGUIEvent * 0x0012fb6c, unsigned
int 0x0000001c, nsEventStatus & nsEventStatus_eIgnore, int & 0x00000000) line
834
nsViewManager::DispatchEvent(nsViewManager * const 0x0200eb40, nsGUIEvent *
0x0012fb6c, nsEventStatus & nsEventStatus_eIgnore) line 1670
HandleEvent(nsGUIEvent * 0x0012fb6c) line 63
nsWindow::DispatchEvent(nsWindow * const 0x0200e924, nsGUIEvent * 0x0012fb6c,
nsEventStatus & nsEventStatus_eIgnore) line 342 + 10 bytes
nsWindow::DispatchWindowEvent(nsGUIEvent * 0x0012fb6c) line 363
nsWindow::DispatchMouseEvent(unsigned int 0x0000012d, nsPoint * 0x00000000) line
3306 + 21 bytes
ChildWindow::DispatchMouseEvent(unsigned int 0x0000012d, nsPoint * 0x00000000)
line 3524
nsWindow::ProcessMessage(unsigned int 0x00000202, unsigned int 0x00000000, long
0x01870078, long * 0x0012fd90) line 2533 + 24 bytes
nsWindow::WindowProc(HWND__ * 0x033f0884, unsigned int 0x00000202, unsigned int
0x00000000, long 0x01870078) line 520 + 27 bytes
USER32! 77e71250()
Resolution: FIXED → ---
Clearing FIXED resolution due to reopen of this bug.
Adding vidur.  It looks like the event handler is quitting the app, which takes
down the JS environment of the running handler.  Maybe there's a way to avoid
clearing the window scope until after the handler finishes?

/be
Well...that was the question that I asked you in 15197, Brendan. Currently,
we're executing window.close() (and, hence, JS_ClearScope) synchronously.
Synchronous execution was probably not the case in 4.x because of the threading
model. It is the case in 4.x, however, that any script after the window.close()
doesn't execute (e.g. window.alert right after the close doesn't seem to
execute). It may be possible, with some work, to defer the actual closing of the
window (and, hence, the call to JS_ClearScope) till after script execution, but
I'm not sure that's correct either.

In the case of 15197, there was a call to setTimeout immediately after the
window.close(). It turns out that the call was inadvertant and really shouldn't
have been there. An exception was thrown since setTimeout no longer existed. The
patch that Roger checked in allowed the exception to be forwarded to the error
reporter successfully. It's unclear to me that this is worse than defering the
window closure and actually executing the setTimeout.
Assignee: rogerl → vidur
Status: REOPENED → NEW
See http://lxr.mozilla.org/mozilla/source/lib/libmocha/lm_win.c#1418 for how
MozillaClassic solved this.  The next statement after window.close does not fail
to run in 4.x, for me:

<script>
foo=1
window.open("javascript:'<body onload=self.close();opener.foo=3><\/body>'")
</script>
<body onload='document.form.fooval.value = foo'>
<form name=form>
<input name=fooval size=4>
<input type=button onclick='document.form.fooval.value = foo'>
</form>
</body>

If you click the button after the opened window has closed itself, you'll see
that foo was set to 3.  If you're using alerts to trace execution, beware 4.x
does not put up an alert for a window being torn down, IIRC.

It seems to me we should fix this in Mozilla 5 using a setTimeout-like technique
to defer the window's destruction till after the handler.  It might be simpler
and safer to just set a flag that you check on end of script evaluation, though
-- what do you say?

/be
Ugh...the determination that the window.close() came from script (and from there
the determination that it's script in the same window) will be a treat. Other
than that, either setting or a timeout like mechanism could work.
Could javascript's window.close() bind to a function that helps resolve those
problems (or augment whatever it currently calls)?  Maybe pass along a window
handle or something?
Blocks: 16654
Summary: CRASH when creating new profile → [dogfood]CRASH when creating new profile
Whiteboard: [PDT+]
Added dogfood and PDT+ annotations.
Blocks: 17432
Status: NEW → RESOLVED
Closed: 25 years ago25 years ago
Resolution: --- → FIXED
Fix checked in on 10/28/1999. If the calling context of a call to window.close()
is the same as the window's script context, the actual closure is defered till
the script completes. This is done by setting a termination function for the
script context.
Summary: [dogfood]CRASH when creating new profile → [DOGFOOD]CRASH when creating new profile
changing caps in summary.
Status: RESOLVED → VERIFIED
build 1999110508
Component: Profile Manager → Profile Manager BackEnd
Moving all Profile Manager bugs to new Profile Manager Backend component.
Profile Manager component to be deleted.
No longer blocks: 17432
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.