Bug 13563 - REGRESSION: Crash loading message in Yahoo! Mail
Summary: REGRESSION: Crash loading message in Yahoo! Mail
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 523.x (Safari 3)
Hardware: Mac OS X 10.4
: P1 Normal
Assignee: Nobody
URL:
Keywords: InRadar, NeedsReduction, Regression
Depends on:
Blocks:
 
Reported: 2007-05-01 11:34 PDT by David Kilzer (:ddkilzer)
Modified: 2007-05-23 19:10 PDT (History)
3 users (show)

See Also:


Attachments
Test page (webarchive) (555.63 KB, application/x-webarchive)
2007-05-01 14:27 PDT, David Kilzer (:ddkilzer)
no flags Details
Test case (web page, complete from Firefox) (176.27 KB, application/zip)
2007-05-01 14:29 PDT, David Kilzer (:ddkilzer)
no flags Details
Debug patch (5.96 KB, patch)
2007-05-17 00:17 PDT, David Kilzer (:ddkilzer)
no flags Details | Formatted Diff | Diff
Reduction (will crash when you click Test) (1.01 KB, text/html)
2007-05-20 02:07 PDT, mitz
no flags Details
Keep updating the style selector once you calculated it (8.43 KB, patch)
2007-05-20 15:58 PDT, mitz
hyatt: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description David Kilzer (:ddkilzer) 2007-05-01 11:34:30 PDT
* SUMMARY

Crash loading a mail message in Yahoo! Mail.

* CONSOLE OUTPUT

Segmentation fault

* STACK TRACE

Exception:  EXC_BAD_ACCESS (0x0001)
Codes:      KERN_INVALID_ADDRESS (0x0001) at 0x4082600c

Thread 0 Crashed:
0   com.apple.WebCore        	0x0158fbfc WTF::RefPtr<WebCore::StringImpl>::get() const + 20 (RefPtr.h:45)
1   com.apple.WebCore        	0x0158fc34 WebCore::String::impl() const + 36 (PlatformString.h:151)
2   com.apple.WebCore        	0x01594ba0 WebCore::AtomicString::impl() const + 36 (AtomicString.h:50)
3   com.apple.WebCore        	0x01594c2c WebCore::operator==(WebCore::AtomicString const&, WebCore::AtomicString const&) + 48 (AtomicString.h:103)
4   com.apple.WebCore        	0x0114fab0 WebCore::CSSStyleSelector::matchRulesForList(WebCore::CSSRuleDataList*, int&, int&) + 188 (cssstyleselector.cpp:432)
5   com.apple.WebCore        	0x0114fd28 WebCore::CSSStyleSelector::matchRules(WebCore::CSSRuleSet*, int&, int&) + 176 (cssstyleselector.cpp:396)
6   com.apple.WebCore        	0x0115efe0 WebCore::CSSStyleSelector::styleForElement(WebCore::Element*, WebCore::RenderStyle*, bool, bool) + 1212 (cssstyleselector.cpp:867)
7   com.apple.WebCore        	0x012b893c WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 484 (Element.cpp:675)
8   com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
9   com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
10  com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
11  com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
12  com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
13  com.apple.WebCore        	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
14  com.apple.WebCore        	0x0110048c WebCore::Document::recalcStyle(WebCore::Node::StyleChange) + 1284 (Document.cpp:1024)
15  com.apple.WebCore        	0x010f67f4 WebCore::Document::updateRendering() + 84 (Document.cpp:1049)
16  com.apple.WebCore        	0x012eadbc KJS::ScheduledAction::execute(KJS::Window*) + 1168 (kjs_window.cpp:1940)
17  com.apple.WebCore        	0x012edec4 KJS::Window::timerFired(KJS::DOMWindowTimer*) + 504 (kjs_window.cpp:2054)
18  com.apple.WebCore        	0x012edf60 KJS::DOMWindowTimer::fired() + 72 (kjs_window.cpp:2640)
19  com.apple.WebCore        	0x0126a88c WebCore::TimerBase::fireTimers(double, WTF::Vector<WebCore::TimerBase*, (unsigned long)0> const&) + 240 (Timer.cpp:322)
20  com.apple.WebCore        	0x0126a958 WebCore::TimerBase::sharedTimerFired() + 132 (Timer.cpp:355)
21  com.apple.WebCore        	0x01269d48 WebCore::timerFired(__CFRunLoopTimer*, void*) + 60 (SharedTimerMac.cpp:47)
22  com.apple.CoreFoundation 	0x907f2578 __CFRunLoopDoTimer + 184
23  com.apple.CoreFoundation 	0x907deef8 __CFRunLoopRun + 1680
24  com.apple.CoreFoundation 	0x907de4ac CFRunLoopRunSpecific + 268
25  com.apple.HIToolbox      	0x93298b20 RunCurrentEventLoopInMode + 264
26  com.apple.HIToolbox      	0x932981b4 ReceiveNextEventCommon + 380
27  com.apple.HIToolbox      	0x93298020 BlockUntilNextEventMatchingListInMode + 96
28  com.apple.AppKit         	0x9379eae4 _DPSNextEvent + 384
29  com.apple.AppKit         	0x9379e7a8 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 116
30  com.apple.Safari         	0x00006740 0x1000 + 22336
31  com.apple.AppKit         	0x9379acec -[NSApplication run] + 472
32  com.apple.AppKit         	0x9388b87c NSApplicationMain + 452
33  com.apple.Safari         	0x0005c77c 0x1000 + 374652
34  com.apple.Safari         	0x0005c624 0x1000 + 374308
Comment 1 David Kilzer (:ddkilzer) 2007-05-01 14:27:06 PDT
Reproduced with a local debug build of WebKit r21200 with Safari 2.0.4 (419.3) on Mac OS X 10.4.9 (8P135).

Note that this doesn't reproduce every time...I've had to reload a few times before the bug has occurred.  (And of course I can't reproduce it at all now.)

Comment 2 David Kilzer (:ddkilzer) 2007-05-01 14:27:56 PDT
Created attachment 14301 [details]
Test page (webarchive)

Please, no smart-aleck comments about the contents of the message. :)
Comment 3 David Kilzer (:ddkilzer) 2007-05-01 14:29:05 PDT
Created attachment 14302 [details]
Test case (web page, complete from Firefox)

Note that I have NOT been able to reproduce the bug loading this page or the webarchive.
Comment 4 David Kilzer (:ddkilzer) 2007-05-01 14:45:57 PDT
Slightly different stack trace:

Exception:  EXC_BAD_ACCESS (0x0001)
Codes:      KERN_PROTECTION_FAILURE (0x0002) at 0x00000070

Thread 0 Crashed:
0   com.apple.WebCore              	0x0114fb54 WebCore::CSSStyleSelector::matchRulesForList(WebCore::CSSRuleDataList*, int&, int&) + 352 (cssstyleselector.cpp:435)
1   com.apple.WebCore              	0x0114fd28 WebCore::CSSStyleSelector::matchRules(WebCore::CSSRuleSet*, int&, int&) + 176 (cssstyleselector.cpp:396)
2   com.apple.WebCore              	0x0115efe0 WebCore::CSSStyleSelector::styleForElement(WebCore::Element*, WebCore::RenderStyle*, bool, bool) + 1212 (cssstyleselector.cpp:867)
3   com.apple.WebCore              	0x012b893c WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 484 (Element.cpp:675)
4   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
5   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
6   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
7   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
8   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
9   com.apple.WebCore              	0x012b8c80 WebCore::Element::recalcStyle(WebCore::Node::StyleChange) + 1320 (Element.cpp:713)
10  com.apple.WebCore              	0x0110048c WebCore::Document::recalcStyle(WebCore::Node::StyleChange) + 1284 (Document.cpp:1024)
11  com.apple.WebCore              	0x010f67f4 WebCore::Document::updateRendering() + 84 (Document.cpp:1049)
12  com.apple.WebCore              	0x012eadbc KJS::ScheduledAction::execute(KJS::Window*) + 1168 (kjs_window.cpp:1940)
13  com.apple.WebCore              	0x012edec4 KJS::Window::timerFired(KJS::DOMWindowTimer*) + 504 (kjs_window.cpp:2054)
14  com.apple.WebCore              	0x012edf60 KJS::DOMWindowTimer::fired() + 72 (kjs_window.cpp:2640)
15  com.apple.WebCore              	0x0126a88c WebCore::TimerBase::fireTimers(double, WTF::Vector<WebCore::TimerBase*, (unsigned long)0> const&) + 240 (Timer.cpp:322)
16  com.apple.WebCore              	0x0126a958 WebCore::TimerBase::sharedTimerFired() + 132 (Timer.cpp:355)
17  com.apple.WebCore              	0x01269d48 WebCore::timerFired(__CFRunLoopTimer*, void*) + 60 (SharedTimerMac.cpp:47)
18  com.apple.CoreFoundation       	0x907f2578 __CFRunLoopDoTimer + 184
19  com.apple.CoreFoundation       	0x907deef8 __CFRunLoopRun + 1680
20  com.apple.CoreFoundation       	0x907de4ac CFRunLoopRunSpecific + 268
21  com.apple.HIToolbox            	0x93298b20 RunCurrentEventLoopInMode + 264
22  com.apple.HIToolbox            	0x932981b4 ReceiveNextEventCommon + 380
23  com.apple.HIToolbox            	0x93298020 BlockUntilNextEventMatchingListInMode + 96
24  com.apple.AppKit               	0x9379eae4 _DPSNextEvent + 384
25  com.apple.AppKit               	0x9379e7a8 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 116
26  com.apple.Safari               	0x00006740 0x1000 + 22336
27  com.apple.AppKit               	0x9379acec -[NSApplication run] + 472
28  com.apple.AppKit               	0x9388b87c NSApplicationMain + 452
29  com.apple.Safari               	0x0005c77c 0x1000 + 374652
30  com.apple.Safari               	0x0005c624 0x1000 + 374308

Comment 5 David Kilzer (:ddkilzer) 2007-05-01 14:48:41 PDT
NOTE: The content may have to be served from a web server (to get the timing right) to reproduce.

Also, I noticed clearing the browser cache (Cmd-Opt-E) helps to reproduce the issue.

I still have not been able to reproduce using either the Firefox web-page-complete copy or the webarchvie.

Comment 6 David Kilzer (:ddkilzer) 2007-05-01 19:42:12 PDT
What appears to be happening is that the loop iterating over CSSRuleData objects in CSSStyleSelector::matchRulesForList() is getting a rule that has been deleted (or is in the process of being deleted) while it's being accessed in that loop.
Comment 7 Alexey Proskuryakov 2007-05-02 01:16:35 PDT
Opening the archive just redirects to Yahoo login page in my case.
Comment 8 David Kilzer (:ddkilzer) 2007-05-03 09:45:16 PDT
Using this interesting hack:

 StringImpl::~StringImpl()
 {
+fprintf(stderr, ">>> StringImpl::~StringImpl() %p '%s'\n", this, ascii().data());
     if (m_inTable)
         AtomicString::remove(this);
     deleteUCharVector(m_data);
 }

I discovered that this interesting bit of JavaScript from function rmvScroll(msg) in the body of the main page was being run during page layout:

if ( newWidth > 0 || newHeight > 0 ) {
    var ssxyzzy = document.getElementById( "ssxyzzy" );
    var cssAttribs = ['#message {'];
    if ( newWidth > 0 ) cssAttribs.push( 'width:' + newWidth + 'px;' );
    if ( newHeight > 0 ) cssAttribs.push( ' height:' + newHeight + 'px;' );
    cssAttribs.push( '}' );
    try {
        ssxyzzy.sheet.deleteRule( 0 );  // DURING LAYOUT!
        ssxyzzy.sheet.insertRule( cssAttribs.join(""), 0 );
    } catch( e ){}
}

It would appear that the CSS rules are being deleted by JavaScript during layout!  It's not good to be deleting rules from stylesheets when you're running CSSStyleSelector::matchRulesForList() in cssstyleselector.cpp.

Haven't had time to figure out how to create a reproducible test case (or a fix), but the problem is quite obvious now.
Comment 9 mitz 2007-05-03 14:49:29 PDT
Executing arbitrary JS under layout is bad for you. It's probably event dispatch that should go through FrameView::scheduleEvent. A call stack from when it happens would help.
Comment 10 David Kilzer (:ddkilzer) 2007-05-03 15:09:15 PDT
(In reply to comment #8)
> Haven't had time to figure out how to create a reproducible test case (or a
> fix), but the problem is quite obvious now.

Actually, it's not.  I'll should really stop using my "Jump to Conclusions" mat.  Will try to create a reproducible test case.

Comment 11 Eric Seidel (no email) 2007-05-03 19:49:23 PDT
The webarchive didn't work (tried to load up Yahoo), and the static page didn't crash for me.
Comment 12 Darin Adler 2007-05-04 22:19:41 PDT
<rdar://problem/5183694>
Comment 13 mitz 2007-05-15 16:22:45 PDT
(In reply to comment #6)
> What appears to be happening is that the loop iterating over CSSRuleData
> objects in CSSStyleSelector::matchRulesForList() is getting a rule that has
> been deleted (or is in the process of being deleted) while it's being accessed
> in that loop.

If the bug is still reproducible, could you do the following? Set a breakpoint at ~CSSRuleData() and have it print |this| and a backtrace each time it's hit. When you crash as a result of dereferencing a deleted CSSRuleData, get the invalid pointer and find the backtrace from when it was deleted. Not sure it would help much, but IMO it's worth trying.
Comment 14 David Kilzer (:ddkilzer) 2007-05-15 22:55:35 PDT
(In reply to comment #13)
> If the bug is still reproducible, could you do the following? Set a breakpoint
> at ~CSSRuleData() and have it print |this| and a backtrace each time it's hit.
> When you crash as a result of dereferencing a deleted CSSRuleData, get the
> invalid pointer and find the backtrace from when it was deleted. Not sure it
> would help much, but IMO it's worth trying.

Oh yes, it's still reproducible.  If you want me to forward a message to your own Yahoo! Mail account, let me know.

I understand the technique you're using to find who deleted the CSSRuleData, but I'm going to have to do learn more about gdb before I can do that.

Comment 15 David Kilzer (:ddkilzer) 2007-05-15 23:37:58 PDT
(In reply to comment #14)
> I understand the technique you're using to find who deleted the CSSRuleData,
> but I'm going to have to do learn more about gdb before I can do that.

Okay, figured this out.  Now I have to wait for the page to load and the spew to stop!
Comment 16 David Kilzer (:ddkilzer) 2007-05-16 14:36:55 PDT
(In reply to comment #13)
> If the bug is still reproducible, could you do the following? Set a breakpoint
> at ~CSSRuleData() and have it print |this| and a backtrace each time it's hit.
> When you crash as a result of dereferencing a deleted CSSRuleData, get the
> invalid pointer and find the backtrace from when it was deleted. Not sure it
> would help much, but IMO it's worth trying.

I don't believe it's the CSSRuleData or CSSStyleRule that's being deleted.  Still researching.
Comment 17 David Kilzer (:ddkilzer) 2007-05-16 18:01:23 PDT
(In reply to comment #16)
> I don't believe it's the CSSRuleData or CSSStyleRule that's being deleted. 

This is very much timing-related, so slowing down the browser with gdb backtraces or big fprintf() statements makes it harder to reproduce.  :(

Comment 18 David Kilzer (:ddkilzer) 2007-05-16 22:13:49 PDT
Taking a slightly different approach, let's look at where a method named "deleteRule()" is implemented:

void CSSMediaRule::deleteRule(unsigned index, ExceptionCode& ec)
void CSSRuleList::deleteRule(unsigned index)
void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec)

If we look at CSSMediaRule::deleteRule(), we see it calls CSSRuleList::deleteRule().  However, CSSStyleSheet::deleteRule() seems to be an island unto itself.

I'm not sure how these are all supposed to be connected, but I think this is the source of this issue.

Still investigating (until someone else confirms this).

Comment 19 David Kilzer (:ddkilzer) 2007-05-16 23:31:12 PDT
Okay, I've been doing too much guessing.

By adding specific debugging output, I can confirm that:

- the rmvScroll(msg) JavaScript function on the page fires
- which calls ssxyzzy.sheet.deleteRule(0)
- which deletes a CSSStyleRule object
- which deletes a CSSSelector
- which then causes deleted pointers to be accessed through CSSStyleSelector::matchRulesForList()
- which causes a crash.

The timing of when ssxyzzy.sheet.deleteRule(0) is critical.  Most times when the page loads, it happens to "early".  It's only when the rmvScroll(msg) JavaScript function fires many times that the crash is likely to occur.

Still investigating.
Comment 20 David Kilzer (:ddkilzer) 2007-05-17 00:17:37 PDT
Created attachment 14588 [details]
Debug patch

This is the patch I used to determine what's happening when this bug is triggered.

Basically, the bug occurs when:

1. The rmvScroll(msg) JavaScript method fires.

2. Before rmvScroll(msg) calls deleteRule(), its code triggers a partial relayout.  If I had to guess, it would be one of these two lines:

    msg.style.overflow = "visible";
    msg.style.visibility = "visible";

3. The deleteRule() and InsertRule() methods are called, replacing the rules.

4. The relayout continues after the stylesheet change, except that some data structures still have references to deleted objects causing the crash.

The backtrace when deleteRule() is called from rmvScroll(msg) when the bug happens (and when it doesn't) looks like this:

Breakpoint 1, WebCore::CSSSelector::~CSSSelector () at CSSSelector.h:65
65      fprintf(stderr, "Deleting CSSSelector(%s) = %p\n", selectorText().ascii().data(), this);
#0  WebCore::CSSSelector::~CSSSelector () at CSSSelector.h:65
#1  0x01671f10 in WebCore::CSSSelector::~CSSSelector (this=0x170313d0) at CSSSelector.h:69
#2  0x0134b7b8 in WebCore::CSSStyleRule::~CSSStyleRule () at /Volumes/Data/WebKit/WebCore/css/CSSStyleRule.cpp:47
#3  0x015a4acc in WebCore::Shared<WebCore::StyleBase>::deref (this=0x17031434) at Shared.h:52
#4  0x0167205c in WTF::RefPtr<WebCore::StyleBase>::~RefPtr () at RefPtr.h:41
#5  0x01672090 in WTF::RefPtr<WebCore::StyleBase>::~RefPtr (this=0x1733b120) at RefPtr.h:41
#6  0x017412e4 in WTF::Vector<WTF::RefPtr<WebCore::StyleBase>, 0ul>::remove (this=0x173260d4, position=0) at Vector.h:702
#7  0x01354ce0 in WebCore::StyleList::remove (this=0x173260c0, position=0) at /Volumes/Data/WebKit/WebCore/css/StyleList.cpp:51
#8  0x013472d8 in WebCore::CSSStyleSheet::deleteRule (this=0x173260c0, index=0, ec=@0xbfffd870) at /Volumes/Data/WebKit/WebCore/css/CSSStyleSheet.cpp:118
#9  0x012c8f50 in KJS::DOMCSSStyleSheetPrototypeFunction::callAsFunction (this=0x17231480, exec=0xbfffde2c, thisObj=0x17231440, args=@0xbfffd958) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_css.cpp:635
#10 0x0059b4f8 in KJS::JSObject::call (this=0x17231480, exec=0xbfffde2c, thisObj=0x17231440, args=@0xbfffd958) at object.cpp:98
#11 0x005c083c in KJS::FunctionCallDotNode::evaluate (this=0x1702baa0, exec=0xbfffde2c) at nodes.cpp:790
#12 0x005bceb8 in KJS::ExprStatementNode::execute (this=0x1702bac0, exec=0xbfffde2c) at nodes.cpp:1723
#13 0x005b96a8 in KJS::SourceElementsNode::execute (this=0x1702bae0, exec=0xbfffde2c) at nodes.cpp:2522
#14 0x005894d4 in KJS::BlockNode::execute (this=0x177f3a90, exec=0xbfffde2c) at nodes.cpp:1699
#15 0x00597ec0 in KJS::TryNode::execute (this=0x177f3ad0, exec=0xbfffde2c) at nodes.cpp:2344
#16 0x005b97fc in KJS::SourceElementsNode::execute (this=0x175b3dc0, exec=0xbfffde2c) at nodes.cpp:2528
#17 0x005894d4 in KJS::BlockNode::execute (this=0x177f3b10, exec=0xbfffde2c) at nodes.cpp:1699
#18 0x005bcd40 in KJS::IfNode::execute (this=0x177f3b30, exec=0xbfffde2c) at nodes.cpp:1742
#19 0x005b97fc in KJS::SourceElementsNode::execute (this=0x177b6f60, exec=0xbfffde2c) at nodes.cpp:2528
#20 0x005894d4 in KJS::BlockNode::execute (this=0x177f3b70, exec=0xbfffde2c) at nodes.cpp:1699
#21 0x00589624 in KJS::DeclaredFunctionImp::execute (this=0x16fffbe0, exec=0xbfffde2c) at function.cpp:317
#22 0x00598ac8 in KJS::FunctionImp::callAsFunction (this=0x16fffbe0, exec=0xbfffe18c, thisObj=0x16f5fdc0, args=@0xbfffdf70) at function.cpp:104
#23 0x0059b4f8 in KJS::JSObject::call (this=0x16fffbe0, exec=0xbfffe18c, thisObj=0x16f5fdc0, args=@0xbfffdf70) at object.cpp:98
#24 0x005c1088 in KJS::FunctionCallResolveNode::evaluate (this=0x17596d60, exec=0xbfffe18c) at nodes.cpp:694
#25 0x005bceb8 in KJS::ExprStatementNode::execute (this=0x177b6ff0, exec=0xbfffe18c) at nodes.cpp:1723
#26 0x005b96a8 in KJS::SourceElementsNode::execute (this=0x177b7010, exec=0xbfffe18c) at nodes.cpp:2522
#27 0x005894d4 in KJS::BlockNode::execute (this=0x177b7030, exec=0xbfffe18c) at nodes.cpp:1699
#28 0x00589624 in KJS::DeclaredFunctionImp::execute (this=0x16ffd2c0, exec=0xbfffe18c) at function.cpp:317
#29 0x00598ac8 in KJS::FunctionImp::callAsFunction (this=0x16ffd2c0, exec=0x1752feec, thisObj=0x16f5fdc0, args=@0x17021f24) at function.cpp:104
#30 0x0059b4f8 in KJS::JSObject::call (this=0x16ffd2c0, exec=0x1752feec, thisObj=0x16f5fdc0, args=@0x17021f24) at object.cpp:98
#31 0x012ec3cc in KJS::ScheduledAction::execute (this=0x17021f20, window=0x16f5fdc0) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:1918
#32 0x012ef734 in KJS::Window::timerFired (this=0x16f5fdc0, timer=0x16e79e30) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2054
#33 0x012ef7d0 in KJS::DOMWindowTimer::fired (this=0x16e79e30) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2641
#34 0x0126b6dc in WebCore::TimerBase::fireTimers (fireTime=1179384417.077419, firingTimers=@0xbfffe480) at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:336
#35 0x0126b7a8 in WebCore::TimerBase::sharedTimerFired () at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:353
#36 0x0126ab98 in timerFired () at /Volumes/Data/WebKit/WebCore/platform/mac/SharedTimerMac.cpp:46
#37 0x907f2578 in __CFRunLoopDoTimer ()
#38 0x907deef8 in __CFRunLoopRun ()
#39 0x907de4ac in CFRunLoopRunSpecific ()
#40 0x93298b20 in RunCurrentEventLoopInMode ()
#41 0x932981b4 in ReceiveNextEventCommon ()
#42 0x93298020 in BlockUntilNextEventMatchingListInMode ()
#43 0x9379eae4 in _DPSNextEvent ()
#44 0x9379e7a8 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#45 0x00006740 in ?? ()
#46 0x9379acec in -[NSApplication run] ()
#47 0x9388b87c in NSApplicationMain ()
#48 0x0005c77c in ?? ()
#49 0x0005c624 in ?? ()

The page load when the bug occurs looks like this (with the debug patch applied):

>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173ebc20 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ed0680 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173ebc20 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ed0680 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17332250 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ef0eb0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17332250 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ef0eb0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17767070 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x15c615e0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17767070 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x15c615e0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
(timer firing): function () 
{
  rmvScroll(msg);
}
(timer firing): function () 
{
  rmvScroll(msg);
}
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1792f740 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1734ff60 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1792f740 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1734ff60 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x177badd0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17317180 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x177badd0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17317180 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1704f100 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175b8be0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1704f100 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175b8be0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17731ff0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16eeef70 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17731ff0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16eeef70 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1792de00 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e7dba0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1792de00 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e7dba0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ea9490 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e92cc0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ea9490 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e92cc0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1790d830 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x177eb2f0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1790d830 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x177eb2f0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175861d0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175ee8f0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175861d0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175ee8f0 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173e57b0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175c4250 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173e57b0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175c4250 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17746ae0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ef7d60 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17746ae0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ef7d60 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleSheet::deleteRule(index = 0d, ec = 0)
>>> Deleting CSSStyleRule(#message) = 0x17031430
Deleting CSSSelector(#message) = 0x170313d0
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17746ae0 CSSSelector* d->selector() = 0x170cb160 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16ef7d60 CSSSelector* d->selector() = 0x1708d010 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'

Note that when the bug does NOT occur, there is no relayout between the time that rmvScroll(msg) is called and when the deleteRule()/insertRule() code is called.  Also note that there are much fewer relayouts:

>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173587c0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e93780 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x173587c0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e93780 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17044a90 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17353420 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17044a90 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17353420 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
(timer firing): function () 
{
  rmvScroll(msg);
}
(timer firing): function () 
{
  rmvScroll(msg);
}
>>> CSSStyleSheet::deleteRule(index = 0d, ec = 0)
>>> Deleting CSSStyleRule(#message) = 0x1702d680
Deleting CSSSelector(#message) = 0x1702d810
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x170592f0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1750c470 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x170592f0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x1750c470 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175da4d0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17026b90 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x175da4d0 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x17026b90 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e7a230 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x170051d0 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x16e7a230 CSSSelector* d->selector() = 0x17017490 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'
>>> CSSStyleRule = 'div#message' CSSRuleData* d = 0x170051d0 CSSSelector* d->selector() = 0x17569b50 QualifiedName d->selector()->m_tag = 'div' AtomicString d->selector()->m_tag.localName() = 'div'

*NOTE: I am assuming a "relayout" occurs each time CSSStyleSelector::matchRulesForList() is being called, although I haven't looked at a backtrace for those functions when they're being called.
Comment 21 David Kilzer (:ddkilzer) 2007-05-17 00:49:37 PDT
(In reply to comment #20)
> Created an attachment (id=14588) [edit]
> Debug patch
> 
> This is the patch I used to determine what's happening when this bug is
> triggered.
> 
> Basically, the bug occurs when:
> 
> 1. The rmvScroll(msg) JavaScript method fires.
> 
> 2. Before rmvScroll(msg) calls deleteRule(), its code triggers a partial
> relayout.  If I had to guess, it would be one of these two lines:
> 
>     msg.style.overflow = "visible";
>     msg.style.visibility = "visible";

WRONG.  The relayouts occurs with the following JavaScript (although I don't know why this happens sometimes when loading the page and not others):

msg.clientHeight
msg.scrollHeight
msg.offsetWidth
msg.clientWidth
msg.scrollWidth


> 3. The deleteRule() and InsertRule() methods are called, replacing the rules.
> 
> 4. The relayout continues after the stylesheet change, except that some data
> structures still have references to deleted objects causing the crash.

The layouts that occur after the rule has been deleted and added are triggered by KJS::ScheduledAction::execute() in WebCore/bindings/js/kjs_window.cpp:1940 with this big, smelly comment:

    // Update our document's rendering following the execution of the timeout callback.
    // FIXME: Why not use updateDocumentsRendering to update rendering of all documents?
    // FIXME: Is this really the right point to do the update? We need a place that works
    // for all possible entry points that might possibly execute script, but this seems
    // to be a bit too low-level.
    if (Document* doc = frame->document())
        doc->updateRendering();

> *NOTE: I am assuming a "relayout" occurs each time
> CSSStyleSelector::matchRulesForList() is being called, although I haven't
> looked at a backtrace for those functions when they're being called.

This appears to be a valid assumption based on backtraces taken when the bug occurred.

Backtrace from accessing "msg.clientHeight":

Breakpoint 4, WebCore::CSSStyleSelector::matchRulesForList (this=0x187f1e40, rules=0x19559bb0, firstRuleIndex=@0xbfffd2dc, lastRuleIndex=@0xbfffd2e0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:435
435     fprintf(stderr, ">>> CSSStyleRule = '%s' ", rule->selectorText().ascii().data());
#0  WebCore::CSSStyleSelector::matchRulesForList (this=0x187f1e40, rules=0x19559bb0, firstRuleIndex=@0xbfffd2dc, lastRuleIndex=@0xbfffd2e0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:435
#1  0x0114fc9c in WebCore::CSSStyleSelector::matchRules (this=0x187f1e40, rules=0x18f28610, firstRuleIndex=@0xbfffd2dc, lastRuleIndex=@0xbfffd2e0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:395
#2  0x0115ef54 in WebCore::CSSStyleSelector::styleForElement (this=0x187f1e40, e=0x189854e0, defaultParent=0x0, allowSharing=true, resolveForRootDefault=false) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:877
#3  0x012b9844 in WebCore::Element::recalcStyle (this=0x189854e0, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:676
#4  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1878e5d0, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#5  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1893c670, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#6  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1893c730, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#7  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x195bd150, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#8  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1976b6a0, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#9  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1873c400, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#10 0x01100184 in WebCore::Document::recalcStyle (this=0x2bcb600, change=WebCore::Node::Force) at /Volumes/Data/WebKit/WebCore/dom/Document.cpp:1006
#11 0x01105f8c in WebCore::Document::updateStyleSelector (this=0x2bcb600) at /Volumes/Data/WebKit/WebCore/dom/Document.cpp:1931
#12 0x0110661c in WebCore::Document::updateLayoutIgnorePendingStylesheets (this=0x2bcb600) at /Volumes/Data/WebKit/WebCore/dom/Document.cpp:1076
#13 0x012b8b78 in WebCore::Element::clientHeight (this=0x189854e0) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:334
#14 0x012a68cc in WebCore::JSElement::getValueProperty (this=0x1881fc00, exec=0xbfffde2c, token=10) at /symroots/Debug/DerivedSources/WebCore/JSElement.cpp:217
#15 0x016e4eac in KJS::staticValueGetter<WebCore::JSElement> (exec=0xbfffde2c, slot=@0xbfffda08) at lookup.h:149
#16 0x005e9820 in KJS::PropertySlot::getValue (this=0xbfffda08, exec=0xbfffde2c, originalObject=0x1881fc00, propertyName=@0x17033a4c) at property_slot.h:47
#17 0x0056e018 in KJS::JSObject::get (this=0x1881fc00, exec=0xbfffde2c, propertyName=@0x17033a4c) at object.cpp:166
#18 0x005c1730 in KJS::DotAccessorNode::evaluate (this=0x17033a40, exec=0xbfffde2c) at nodes.cpp:563
#19 0x005be790 in KJS::AddNode::evaluate (this=0x189b6ed0, exec=0xbfffde2c) at nodes.cpp:1209
#20 0x0057c8d4 in KJS::AssignExprNode::evaluate (this=0x17033ab0, exec=0xbfffde2c) at nodes.cpp:1578
#21 0x005bd44c in KJS::VarDeclNode::evaluate (this=0x195c2550, exec=0xbfffde2c) at nodes.cpp:1596
#22 0x005bd2f4 in KJS::VarDeclListNode::evaluate (this=0x16e8d370, exec=0xbfffde2c) at nodes.cpp:1643
#23 0x005bd088 in KJS::VarStatementNode::execute (this=0x195c2570, exec=0xbfffde2c) at nodes.cpp:1667
#24 0x005b97fc in KJS::SourceElementsNode::execute (this=0x195c2330, exec=0xbfffde2c) at nodes.cpp:2528
#25 0x005894d4 in KJS::BlockNode::execute (this=0x170d6c50, exec=0xbfffde2c) at nodes.cpp:1699
#26 0x00589624 in KJS::DeclaredFunctionImp::execute (this=0x1881fcc0, exec=0xbfffde2c) at function.cpp:317
#27 0x00598ac8 in KJS::FunctionImp::callAsFunction (this=0x1881fcc0, exec=0xbfffe18c, thisObj=0x16f9fdc0, args=@0xbfffdf70) at function.cpp:104
#28 0x0059b4f8 in KJS::JSObject::call (this=0x1881fcc0, exec=0xbfffe18c, thisObj=0x16f9fdc0, args=@0xbfffdf70) at object.cpp:98
#29 0x005c1088 in KJS::FunctionCallResolveNode::evaluate (this=0x16e91130, exec=0xbfffe18c) at nodes.cpp:694
#30 0x005bceb8 in KJS::ExprStatementNode::execute (this=0x195c23c0, exec=0xbfffe18c) at nodes.cpp:1723
#31 0x005b96a8 in KJS::SourceElementsNode::execute (this=0x195c23e0, exec=0xbfffe18c) at nodes.cpp:2522
#32 0x005894d4 in KJS::BlockNode::execute (this=0x195c2400, exec=0xbfffe18c) at nodes.cpp:1699
#33 0x00589624 in KJS::DeclaredFunctionImp::execute (this=0x1881d320, exec=0xbfffe18c) at function.cpp:317
#34 0x00598ac8 in KJS::FunctionImp::callAsFunction (this=0x1881d320, exec=0x187262cc, thisObj=0x16f9fdc0, args=@0x189f1f24) at function.cpp:104
#35 0x0059b4f8 in KJS::JSObject::call (this=0x1881d320, exec=0x187262cc, thisObj=0x16f9fdc0, args=@0x189f1f24) at object.cpp:98
#36 0x012ec3cc in KJS::ScheduledAction::execute (this=0x189f1f20, window=0x16f9fdc0) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:1918
#37 0x012ef734 in KJS::Window::timerFired (this=0x16f9fdc0, timer=0x1894ae10) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2054
#38 0x012ef7d0 in KJS::DOMWindowTimer::fired (this=0x1894ae10) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2641
#39 0x0126b6dc in WebCore::TimerBase::fireTimers (fireTime=1179386457.14042, firingTimers=@0xbfffe480) at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:336
#40 0x0126b7a8 in WebCore::TimerBase::sharedTimerFired () at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:353
#41 0x0126ab98 in timerFired () at /Volumes/Data/WebKit/WebCore/platform/mac/SharedTimerMac.cpp:46
#42 0x907f2578 in __CFRunLoopDoTimer ()
#43 0x907deef8 in __CFRunLoopRun ()
#44 0x907de4ac in CFRunLoopRunSpecific ()
#45 0x93298b20 in RunCurrentEventLoopInMode ()
#46 0x932981b4 in ReceiveNextEventCommon ()
#47 0x93298020 in BlockUntilNextEventMatchingListInMode ()
#48 0x9379eae4 in _DPSNextEvent ()
#49 0x9379e7a8 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#50 0x00006740 in ?? ()
#51 0x9379acec in -[NSApplication run] ()
#52 0x9388b87c in NSApplicationMain ()
#53 0x0005c77c in ?? ()
#54 0x0005c624 in ?? ()

And a backtrace after rmvScroll(msg) has run showing where the final relayout occurs:

Breakpoint 4, WebCore::CSSStyleSelector::matchRulesForList (this=0x187f1e40, rules=0x1700a910, firstRuleIndex=@0xbfffddbc, lastRuleIndex=@0xbfffddc0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:435
435     fprintf(stderr, ">>> CSSStyleRule = '%s' ", rule->selectorText().ascii().data());
#0  WebCore::CSSStyleSelector::matchRulesForList (this=0x187f1e40, rules=0x1700a910, firstRuleIndex=@0xbfffddbc, lastRuleIndex=@0xbfffddc0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:435
#1  0x0114fc9c in WebCore::CSSStyleSelector::matchRules (this=0x187f1e40, rules=0x18f28610, firstRuleIndex=@0xbfffddbc, lastRuleIndex=@0xbfffddc0) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:395
#2  0x0115ef54 in WebCore::CSSStyleSelector::styleForElement (this=0x187f1e40, e=0x189854e0, defaultParent=0x0, allowSharing=true, resolveForRootDefault=false) at /Volumes/Data/WebKit/WebCore/css/cssstyleselector.cpp:877
#3  0x012b9844 in WebCore::Element::recalcStyle (this=0x189854e0, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:676
#4  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1878e5d0, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#5  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1893c670, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#6  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1893c730, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#7  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x195bd150, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#8  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1976b6a0, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#9  0x012b9bc4 in WebCore::Element::recalcStyle (this=0x1873c400, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Element.cpp:716
#10 0x01100184 in WebCore::Document::recalcStyle (this=0x2bcb600, change=WebCore::Node::NoChange) at /Volumes/Data/WebKit/WebCore/dom/Document.cpp:1006
#11 0x010f6960 in WebCore::Document::updateRendering (this=0x2bcb600) at /Volumes/Data/WebKit/WebCore/dom/Document.cpp:1028
#12 0x012ec624 in KJS::ScheduledAction::execute (this=0x189f1f20, window=0x16f9fdc0) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:1940
#13 0x012ef734 in KJS::Window::timerFired (this=0x16f9fdc0, timer=0x1894ae10) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2054
#14 0x012ef7d0 in KJS::DOMWindowTimer::fired (this=0x1894ae10) at /Volumes/Data/WebKit/WebCore/bindings/js/kjs_window.cpp:2641
#15 0x0126b6dc in WebCore::TimerBase::fireTimers (fireTime=1179386457.14042, firingTimers=@0xbfffe480) at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:336
#16 0x0126b7a8 in WebCore::TimerBase::sharedTimerFired () at /Volumes/Data/WebKit/WebCore/platform/Timer.cpp:353
#17 0x0126ab98 in timerFired () at /Volumes/Data/WebKit/WebCore/platform/mac/SharedTimerMac.cpp:46
#18 0x907f2578 in __CFRunLoopDoTimer ()
#19 0x907deef8 in __CFRunLoopRun ()
#20 0x907de4ac in CFRunLoopRunSpecific ()
#21 0x93298b20 in RunCurrentEventLoopInMode ()
#22 0x932981b4 in ReceiveNextEventCommon ()
#23 0x93298020 in BlockUntilNextEventMatchingListInMode ()
#24 0x9379eae4 in _DPSNextEvent ()
#25 0x9379e7a8 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#26 0x00006740 in ?? ()
#27 0x9379acec in -[NSApplication run] ()
#28 0x9388b87c in NSApplicationMain ()
#29 0x0005c77c in ?? ()
#30 0x0005c624 in ?? ()
Comment 22 David Kilzer (:ddkilzer) 2007-05-17 00:52:56 PDT
Based on the information in the last few comments, it should be possible to create a test case for this issue, although if someone else wants to take a stab at it before tomorrow, be my guest!
Comment 23 Dave Hyatt 2007-05-17 01:03:17 PDT
updateStyleSelector happens synchronously when insertRule/deleteRule are called.  So it should be up to date.  Not sure what is happening here.
Comment 24 David Kilzer (:ddkilzer) 2007-05-17 01:44:05 PDT
(In reply to comment #23)
> updateStyleSelector happens synchronously when insertRule/deleteRule are
> called.  So it should be up to date.  Not sure what is happening here.

Okay, I'll try to figure out what's not getting updated properly.

Comment 25 mitz 2007-05-20 02:07:40 PDT
Created attachment 14634 [details]
Reduction (will crash when you click Test)

The reduction includes comments on how it works.
Comment 26 mitz 2007-05-20 10:04:43 PDT
Wondering if there's an elegant fix that doesn't involve adding another bit of state to Document.
Comment 27 mitz 2007-05-20 11:59:49 PDT
Comment on attachment 14634 [details]
Reduction (will crash when you click Test)

Not that it makes any difference, but I used the wrong attribute in the test: where it says "src" it should say "href".

I discovered that when I tried to replace the URL with something that takes a long time to load. If you do that and comment-out the last line of the script, then the color will not change from pink to black until the slow-loading URL has finished loading. That's a less catastrophic symptom of the same bug, namely that updateStyleSelector() bails out when it should not.
Comment 28 mitz 2007-05-20 15:58:21 PDT
Created attachment 14637 [details]
Keep updating the style selector once you calculated it

The layout tests fail to crash a release build of TOT, maybe because of fast malloc not trashing the deleted style rule immediately. One of them crashes a debug build quite reliably. The other one not so much (but crashes eventually in Safari).
Comment 29 Dave Hyatt 2007-05-21 01:19:52 PDT
Comment on attachment 14637 [details]
Keep updating the style selector once you calculated it

r=me

This bug is just plain cool.
Comment 30 David Kilzer (:ddkilzer) 2007-05-23 19:10:32 PDT
Committed revision 21690.