WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
245968
Crash in pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl
https://bugs.webkit.org/show_bug.cgi?id=245968
Summary
Crash in pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl
Michael Catanzaro
Reported
2022-10-03 09:20:23 PDT
In WebKitGTK 2.38.0 we have an occasional crash in libpas: #0 0x00007f219811d515 in pas_compare_and_swap_uint8_strong (new_value=1 '\001', old_value=0 '\000', ptr=0x10 <error: Cannot access memory at address 0x10>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_utils.h:602 result = <optimized out> owner = 0x7f217d4267e8 page_lock = 0x7f217c00e910 exclusive = <optimized out> got_right_lock = <optimized out> #1 pas_compare_and_swap_bool_strong (new_value=true, old_value=false, ptr=0x10) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_utils.h:780 result = <optimized out> owner = 0x7f217d4267e8 page_lock = 0x7f217c00e910 exclusive = <optimized out> got_right_lock = <optimized out> #2 pas_lock_try_lock (lock=0x10) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_lock.h:94 result = <optimized out> owner = 0x7f217d4267e8 page_lock = 0x7f217c00e910 exclusive = <optimized out> got_right_lock = <optimized out> #3 pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl (page=0x7f218a114000, held_lock=0x7f07edffa768, cache_node=0x0) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_segregated_page.c:146 owner = 0x7f217d4267e8 page_lock = 0x7f217c00e910 exclusive = <optimized out> got_right_lock = <optimized out> #4 0x00007f21980e1ed7 in pas_segregated_page_switch_lock_and_rebias_while_ineligible (page_config=..., cache_node=0x0, held_lock=0x7f07edffa768, page=0x7f218a114000) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_segregated_page_inlines.h:313 new_view = <optimized out> held_lock = 0x7f217c00e910 directory = <optimized out> partial = <optimized out> old_view = <optimized out> shared = <optimized out> cache = <optimized out> new_page = 0x7f218a114000 did_get_view = <optimized out> old_page = 0x7f218a114000 size_directory = <optimized out> cache_node = <optimized out> refill_result = <optimized out> #5 pas_local_allocator_refill_with_known_config (page_config=..., counts=0x7fff66cb7361, allocator=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h:1163 new_view = <optimized out> held_lock = 0x7f217c00e910 directory = <optimized out> partial = <optimized out> old_view = <optimized out> shared = <optimized out> cache = <optimized out> new_page = 0x7f218a114000 did_get_view = <optimized out> old_page = 0x7f218a114000 size_directory = <optimized out> cache_node = <optimized out> refill_result = <optimized out> #6 pas_local_allocator_try_allocate_small_segregated_slow_impl (counts=0x7fff66cb7361, config=..., allocator=0x7f217c00df98) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h:1566 refill_result = <optimized out> #7 pas_local_allocator_try_allocate_small_segregated_slow (result_filter=0x7f21980dbb40 <pas_allocation_result_identity(pas_allocation_result)>, counts=0x7fff66cb7361, config=..., allocator=0x7f217c00df98) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h:1587 #8 bmalloc_heap_config_specialized_local_allocator_try_allocate_small_segregated_slow(pas_local_allocator*, pas_allocator_counts*, pas_allocation_result_filter) (allocator=allocator@entry=0x7f217d4836f8, count=count@entry=0x7f21984d04c0 <bmalloc_allocator_counts>, result_filter=result_filter@entry=0x7f21980dbb40 <pas_allocation_result_identity(pas_allocation_result)>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_config.c:43 #9 0x00007f21980e7ca3 in pas_local_allocator_try_allocate (result_filter=0x7f21980dbb40 <pas_allocation_result_identity(pas_allocation_result)>, counts=0x7f21984d04c0 <bmalloc_allocator_counts>, config=..., alignment=1, size=120, allocator=0x7f217d4836f8) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h:1831 result = {begin = <optimized out>, did_succeed = <optimized out>, zero_mode = <optimized out>} baseline_allocator_result = {did_succeed = <optimized out>, allocator = 0x7f217d4836f8, lock = 0x7f217d4836f0} heap = <optimized out> directory = <optimized out> result = {begin = <optimized out>, did_succeed = <optimized out>, zero_mode = <optimized out>} cached_index = <optimized out> #10 pas_try_allocate_common_impl_slow (size_lookup_mode=<optimized out>, allocator_counts=<optimized out>, runtime_config=<optimized out>, config=..., alignment=1, size=<optimized out>, heap_ref_kind=<optimized out>, heap_ref=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_try_allocate_common.h:187 baseline_allocator_result = {did_succeed = <optimized out>, allocator = 0x7f217d4836f8, lock = 0x7f217d4836f0} heap = <optimized out> directory = <optimized out> result = {begin = <optimized out>, did_succeed = <optimized out>, zero_mode = <optimized out>} cached_index = <optimized out> #11 bmalloc_heap_config_specialized_try_allocate_common_impl_slow(__pas_heap_ref*, pas_heap_ref_kind, size_t, size_t, pas_heap_runtime_config*, pas_allocator_counts*, pas_size_lookup_mode) (heap_ref=<optimized out>, heap_ref_kind=<optimized out>, size=120, alignment=<optimized out>, runtime_config=<optimized out>, allocator_counts=<optimized out>, size_lookup_mode=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_config.c:43 #12 0x00007f21980cc688 in bmalloc_allocate_impl_impl_slow(__pas_heap_ref*, size_t, size_t) (heap_ref=heap_ref@entry=0x7f07edffa870, size=size@entry=120, alignment=alignment@entry=1) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_inlines.h:70 #13 0x00007f21980cf713 in pas_try_allocate_intrinsic_impl_casual_case (designation_mode=pas_intrinsic_heap_is_designated, try_allocate_common_slow=<optimized out>, try_allocate_common_fast=<optimized out>, config=..., intrinsic_support=0x7f21984d04e0 <bmalloc_common_primitive_heap_support>, alignment=1, size=120, heap=0x7f21984b4080 <bmalloc_common_primitive_heap>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_try_allocate_intrinsic.h:174 aligned_size = 120 index = 8 fake_heap_ref = {type = 0x7f2198481380 <bmalloc_common_primitive_type>, heap = 0x7f21984b4080 <bmalloc_common_primitive_heap>, allocator_index = 0} cache = <optimized out> #14 bmalloc_allocate_impl_casual_case(size_t, size_t) (size=120, alignment=1) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_inlines.h:70 #15 0x00007f21980cfa8d in bmalloc_allocate_casual(size_t) (size=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap.c:64 #16 0x00007f21980c6480 in WTF::ThreadSafeRefCountedBase::operator new(unsigned long) (size=120) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ThreadSafeRefCounted.h:43 thread = {m_ptr = <optimized out>} #17 WTF::Thread::initializeCurrentTLS() () at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/posix/ThreadingPOSIX.cpp:387 thread = {m_ptr = <optimized out>} #18 0x00007f219805f3b5 in WTF::Thread::current() () at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Threading.h:433 result = <optimized out> threadData = 0x7f218a00c110 initializeOnce = {_M_once = 2} enqueueResult = <optimized out> didDequeue = <optimized out> result = {wasUnparked = <optimized out>, token = <optimized out>} #19 WTF::(anonymous namespace)::ThreadData::ThreadData (this=0x7f218a0cfd80) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ParkingLot.cpp:424 result = <optimized out> threadData = 0x7f218a00c110 initializeOnce = {_M_once = 2} enqueueResult = <optimized out> didDequeue = <optimized out> result = {wasUnparked = <optimized out>, token = <optimized out>} #20 WTF::(anonymous namespace)::myThreadData () at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ParkingLot.cpp:459 result = <optimized out> threadData = 0x7f218a00c110 initializeOnce = {_M_once = 2} enqueueResult = <optimized out> didDequeue = <optimized out> result = {wasUnparked = <optimized out>, token = <optimized out>} #21 WTF::ParkingLot::parkConditionallyImpl(void const*, WTF::ScopedLambda<bool ()> const&, WTF::ScopedLambda<void ()> const&, WTF::TimeWithDynamicClockType const&) (address=address@entry=0x7f21984ca734 <WTF::Thread::s_allThreadsLock>, validation=..., beforeSleep=..., timeout=...) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ParkingLot.cpp:570 enqueueResult = <optimized out> didDequeue = <optimized out> result = {wasUnparked = <optimized out>, token = <optimized out>} #22 0x00007f2198051b35 in WTF::ParkingLot::parkConditionally<WTF::ParkingLot::compareAndPark<unsigned char, unsigned char>(WTF::Atomic<unsigned char> const*, unsigned char)::{lambda()#1}, WTF::ParkingLot::compareAndPark<unsigned char, unsigned char>(WTF::Atomic<unsigned char> const*, unsigned char)::{lambda()#2}>(void const*, WTF::ParkingLot::compareAndPark<unsigned char, unsigned char>(WTF::Atomic<unsigned char> const*, unsigned char)::{lambda()#1} const&, WTF::ParkingLot::compareAndPark<unsigned char, unsigned char>(WTF::Atomic<unsigned char> const*, unsigned char)::{lambda()#2} const&, WTF::TimeWithDynamicClockType const&) (timeout=..., beforeSleep=..., validation=..., address=0x7f21984ca734 <WTF::Thread::s_allThreadsLock>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ParkingLot.h:82 currentValue = <optimized out> parkResult = {wasUnparked = <optimized out>, token = <optimized out>} spinCount = 0 #23 WTF::ParkingLot::compareAndPark<unsigned char, unsigned char>(WTF::Atomic<unsigned char> const*, unsigned char) (expected=<optimized out>, address=0x7f21984ca734 <WTF::Thread::s_allThreadsLock>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/ParkingLot.h:94 currentValue = <optimized out> parkResult = {wasUnparked = <optimized out>, token = <optimized out>} spinCount = 0 #24 WTF::LockAlgorithm<unsigned char, (unsigned char)1, (unsigned char)2, WTF::EmptyLockHooks<unsigned char> >::lockSlow(WTF::Atomic<unsigned char>&) (lock=...) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/LockAlgorithmInlines.h:84 currentValue = <optimized out> parkResult = {wasUnparked = <optimized out>, token = <optimized out>} spinCount = 0 #25 0x00007f2198051979 in WTF::Lock::lockSlow() (this=this@entry=0x7f21984ca734 <WTF::Thread::s_allThreadsLock>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Lock.cpp:51 #26 0x00007f2198065acf in WTF::Lock::lock() (this=0x7f21984ca734 <WTF::Thread::s_allThreadsLock>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Lock.h:66 #27 WTF::Locker<WTF::Lock>::Locker(WTF::Lock&) (lock=..., this=<synthetic pointer>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Lock.h:158 #28 WTF::Thread::didExit() (this=0x7f07bf0f1580) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Threading.cpp:298 #29 0x00007f21980c6405 in WTF::Thread::destructTLS(void*) (data=0x7f07bf0f1580) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/posix/ThreadingPOSIX.cpp:545 thread = 0x7f07bf0f1580 #30 WTF::Thread::destructTLS(void*) (data=0x7f07bf0f1580) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/posix/ThreadingPOSIX.cpp:539 thread = 0x7f07bf0f1580 #31 0x00007f219859e1c0 in __GI___nptl_deallocate_tsd () at nptl_deallocate_tsd.c:73 data = <optimized out> inner = <optimized out> level2 = 0x7f07edffb950 idx = <optimized out> cnt = 0 self = <optimized out> #32 __GI___nptl_deallocate_tsd () at nptl_deallocate_tsd.c:22 self = <optimized out> #33 0x00007f21985a1049 in start_thread (arg=<optimized out>) at pthread_create.c:453 pd = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {139672034457152, 4554196666265126491, 139672034457152, -128, 0, 140734918001152, 4554196666451773019, 4575422984186906203}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}} not_first_call = <optimized out> #34 0x00007f2198629d84 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100 Some observations: * In frame 2, pas_lock_try_lock is called with a bogus lock pointer, 0x10 * In frame 3, pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl is called with cache_node=0x0 * It should be impossible to reach the call to pas_lock_try_lock() at pas_segregated_page.c:146 with cache_node=0x0 There is a check: if (!pas_segregated_view_is_some_exclusive(owner) || !cache_node) on line 137 which will by hit if cache_node=0x0, that code always continues or returns, so the rest of the loop should be unreachable: if (!pas_segregated_view_is_some_exclusive(owner) || !cache_node) { pas_lock_switch(held_lock, page_lock); if (page->lock_ptr != page_lock) continue; return; } And yet, somehow we proceeded past that anyway: did_lock_quickly = (*held_lock == &cache_node->page_lock && pas_lock_try_lock(page_lock)) || (*held_lock == page_lock && pas_lock_try_lock(&cache_node->page_lock)); The crash occurs on the last line here, calling pas_lock_try_lock(&cache_node->page_lock) with cache_node=nullptr. Should be impossible. Looking at other threads, I see only two that are potentially suspicious: Thread 67 (Thread 0x7f218bfff640 (LWP 135)): #0 0x00007f2198623acb in madvise () at ../sysdeps/unix/syscall-template.S:117 #1 0x00007f21981115ca in decommit_impl (ptr=0x7f213a037000, size=4096, mmap_capability=<optimized out>, do_mprotect=true) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_page_malloc.c:266 #2 0x00007f21981119f9 in pas_page_malloc_decommit (ptr=<optimized out>, size=<optimized out>, mmap_capability=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_page_malloc.c:279 #3 0x00007f21980f8bfb in decommit_all (log=log@entry=0x7f218bffe6e0, for_real=for_real@entry=true) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_deferred_decommit_log.c:239 #4 0x00007f21980f924e in pas_deferred_decommit_log_decommit_all (log=log@entry=0x7f218bffe6e0) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_deferred_decommit_log.c:280 #5 0x00007f2198113746 in pas_physical_page_sharing_pool_scavenge (max_epoch=8692565532023) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_page_sharing_pool.c:804 #6 0x00007f2198116df9 in scavenger_thread_main (arg=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_scavenger.c:269 #7 0x00007f21985a11da in start_thread (arg=<optimized out>) at pthread_create.c:442 Probably OK? And also: Thread 2 (Thread 0x7f07d0800640 (LWP 151)): #0 0x00007f219860f5ab in sched_yield () at ../sysdeps/unix/syscall-template.S:120 #1 0x00007f21981102e2 in pas_lock_lock_slow (lock=lock@entry=0x7f217d4836f0) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_lock.c:66 #2 0x00007f219812320a in pas_lock_lock (lock=0x7f217d4836f0) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_lock.h:87 #3 pas_segregated_size_directory_select_allocator_slow (directory=0x7f217c00e100) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_segregated_size_directory.c:492 #4 0x00007f21980e7af4 in pas_segregated_size_directory_select_allocator (cached_index=<optimized out>, config=0x7f21984a1a40 <bmalloc_heap_config>, size_lookup_mode=<optimized out>, size=272, directory=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_segregated_size_directory_inlines.h:72 #5 pas_try_allocate_common_impl_slow (size_lookup_mode=<optimized out>, allocator_counts=<optimized out>, runtime_config=<optimized out>, config=..., alignment=1, size=<optimized out>, heap_ref_kind=<optimized out>, heap_ref=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_try_allocate_common.h:184 #6 bmalloc_heap_config_specialized_try_allocate_common_impl_slow(__pas_heap_ref*, pas_heap_ref_kind, size_t, size_t, pas_heap_runtime_config*, pas_allocator_counts*, pas_size_lookup_mode) (heap_ref=<optimized out>, heap_ref_kind=<optimized out>, size=272, alignment=<optimized out>, runtime_config=<optimized out>, allocator_counts=<optimized out>, size_lookup_mode=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_config.c:43 #7 0x00007f21980cc688 in bmalloc_allocate_impl_impl_slow(__pas_heap_ref*, size_t, size_t) (heap_ref=heap_ref@entry=0x7f07d07ff9d0, size=size@entry=272, alignment=alignment@entry=1) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_inlines.h:70 #8 0x00007f21980cf713 in pas_try_allocate_intrinsic_impl_casual_case (designation_mode=pas_intrinsic_heap_is_designated, try_allocate_common_slow=<optimized out>, try_allocate_common_fast=<optimized out>, config=..., intrinsic_support=0x7f21984d04e0 <bmalloc_common_primitive_heap_support>, alignment=1, size=272, heap=0x7f21984b4080 <bmalloc_common_primitive_heap>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/pas_try_allocate_intrinsic.h:174 #9 bmalloc_allocate_impl_casual_case(size_t, size_t) (size=272, alignment=1) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap_inlines.h:70 #10 0x00007f21980cfa8d in bmalloc_allocate_casual(size_t) (size=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/bmalloc/libpas/src/libpas/bmalloc_heap.c:64 #11 0x00007f219803e1b5 in WTF::fastZeroedMalloc(unsigned long) (n=n@entry=272) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/FastMalloc.cpp:118 #12 0x00007f219806694a in WTF::FastMalloc::zeroedMalloc(unsigned long) (size=272) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/FastMalloc.h:230 #13 WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::allocateTable(unsigned int) (size=32) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:1165 #14 WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::rehash(unsigned int, WTF::Thread**) (this=this@entry=0x7f21984ca740 <WTF::Thread::allThreads()::allThreads>, newTableSize=32, entry=entry@entry=0x0) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:1277 #15 0x00007f2198065ac2 in WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::shrink() (this=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:562 #16 WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::remove(WTF::Thread**) (pos=<optimized out>, this=0x7f21984ca740 <WTF::Thread::allThreads()::allThreads>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:1086 #17 WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::removeAndInvalidateWithoutEntryConsistencyCheck(WTF::Thread**) (pos=<optimized out>, this=0x7f21984ca740 <WTF::Thread::allThreads()::allThreads>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:1060 #18 WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >::removeWithoutEntryConsistencyCheck(WTF::HashTableConstIterator<WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >, WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >) (it=..., this=<optimized out>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashTable.h:1115 #19 WTF::HashSet<WTF::Thread*, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTableTraits>::remove(WTF::HashTableConstIteratorAdapter<WTF::HashTable<WTF::Thread*, WTF::Thread*, WTF::IdentityExtractor, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTraits<WTF::Thread*> >, WTF::Thread*>) (it=..., this=0x7f21984ca740 <WTF::Thread::allThreads()::allThreads>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashSet.h:321 #20 WTF::HashSet<WTF::Thread*, WTF::DefaultHash<WTF::Thread*>, WTF::HashTraits<WTF::Thread*>, WTF::HashTableTraits>::remove(WTF::Thread* const&) (value=@0x7f07d07ffb10: 0x7f07bf0f0d80, this=0x7f21984ca740 <WTF::Thread::allThreads()::allThreads>) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/HashSet.h:328 #21 WTF::Thread::didExit() (this=0x7f07bf0f0d80) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/Threading.cpp:299 #22 0x00007f21980c6405 in WTF::Thread::destructTLS(void*) (data=0x7f07bf0f0d80) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/posix/ThreadingPOSIX.cpp:545 #23 WTF::Thread::destructTLS(void*) (data=0x7f07bf0f0d80) at /usr/lib/debug/source/sdk/webkit2gtk-4.1.bst/Source/WTF/wtf/posix/ThreadingPOSIX.cpp:539 #24 0x00007f219859e1c0 in __GI___nptl_deallocate_tsd () at nptl_deallocate_tsd.c:73 #25 __GI___nptl_deallocate_tsd () at nptl_deallocate_tsd.c:22 #26 0x00007f21985a1049 in start_thread (arg=<optimized out>) at pthread_create.c:453 #27 0x00007f2198629d84 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
Attachments
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2022-10-10 09:21:20 PDT
<
rdar://problem/100982033
>
Michael Catanzaro
Comment 2
2022-11-07 15:49:48 PST
This crash happens quite lot, and based on the code it really should be impossible unless GCC is removing the check if (!pas_segregated_view_is_some_exclusive(owner) || !cache_node) on line 137. So I'm going to paste the assembler dump from gdb and hope somebody who understands assembler decides to look at this. It seems gdb was kind enough to put an arrow next to => 0x00007f6902108a45 <+133>: lock cmpxchg %dl,(%r14), which I presume means that is where the crash occurred? Dump of assembler code for function pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl: 0x00007f69021089c0 <+0>: endbr64 0x00007f69021089c4 <+4>: push %rbp 0x00007f69021089c5 <+5>: mov %rsp,%rbp 0x00007f69021089c8 <+8>: push %r15 0x00007f69021089ca <+10>: mov %rdx,%r15 0x00007f69021089cd <+13>: push %r14 0x00007f69021089cf <+15>: push %r13 0x00007f69021089d1 <+17>: mov %rsi,%r13 0x00007f69021089d4 <+20>: lea 0x10(%rdx),%rsi 0x00007f69021089d8 <+24>: push %r12 0x00007f69021089da <+26>: mov %rdi,%r12 0x00007f69021089dd <+29>: push %rbx 0x00007f69021089de <+30>: sub $0x18,%rsp 0x00007f69021089e2 <+34>: mov 0x8(%r12),%rbx 0x00007f69021089e7 <+39>: mov 0x0(%r13),%rdx 0x00007f69021089eb <+43>: cmp %rbx,%rdx 0x00007f69021089ee <+46>: je 0x7f6902108a28 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+104> 0x00007f69021089f0 <+48>: mov 0x20(%r12),%rcx 0x00007f69021089f5 <+53>: test $0x6,%cl 0x00007f69021089f8 <+56>: jne 0x7f6902108a02 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+66> 0x00007f69021089fa <+58>: test %r15,%r15 0x00007f69021089fd <+61>: sete %al 0x00007f6902108a00 <+64>: jne 0x7f6902108a78 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+184> 0x00007f6902108a02 <+66>: mov 0x0(%r13),%rax 0x00007f6902108a06 <+70>: cmp %rax,%rbx 0x00007f6902108a09 <+73>: jne 0x7f6902108b50 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+400> 0x00007f6902108a0f <+79>: cmp %rbx,0x8(%r12) 0x00007f6902108a14 <+84>: jne 0x7f69021089e2 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+34> 0x00007f6902108a16 <+86>: add $0x18,%rsp 0x00007f6902108a1a <+90>: pop %rbx 0x00007f6902108a1b <+91>: pop %r12 0x00007f6902108a1d <+93>: pop %r13 0x00007f6902108a1f <+95>: pop %r14 0x00007f6902108a21 <+97>: pop %r15 0x00007f6902108a23 <+99>: pop %rbp 0x00007f6902108a24 <+100>: ret 0x00007f6902108a25 <+101>: nopl (%rax) 0x00007f6902108a28 <+104>: mov %rsi,%r14 0x00007f6902108a2b <+107>: cmp %rsi,%rdx 0x00007f6902108a2e <+110>: je 0x7f6902108bfa <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+570> 0x00007f6902108a34 <+116>: mov 0x20(%r12),%rcx 0x00007f6902108a39 <+121>: test $0x6,%cl 0x00007f6902108a3c <+124>: jne 0x7f6902108a02 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+66> 0x00007f6902108a3e <+126>: xor %eax,%eax 0x00007f6902108a40 <+128>: mov $0x1,%edx => 0x00007f6902108a45 <+133>: lock cmpxchg %dl,(%r14) 0x00007f6902108a4a <+138>: test %al,%al 0x00007f6902108a4c <+140>: jne 0x7f6902108b80 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+448> 0x00007f6902108a52 <+146>: cmp %r14,%rbx 0x00007f6902108a55 <+149>: je 0x7f6902108bf8 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+568> 0x00007f6902108a5b <+155>: cmp %rbx,0x8(%r12) 0x00007f6902108a60 <+160>: je 0x7f6902108b30 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+368> 0x00007f6902108a66 <+166>: xor %eax,%eax 0x00007f6902108a68 <+168>: xchg %al,(%rbx) 0x00007f6902108a6a <+170>: mov %r14,0x0(%r13) 0x00007f6902108a6e <+174>: jmp 0x7f69021089e2 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+34> 0x00007f6902108a73 <+179>: nopl 0x0(%rax,%rax,1) 0x00007f6902108a78 <+184>: lea 0x10(%r15),%r14 0x00007f6902108a7c <+188>: cmp %r14,%rdx 0x00007f6902108a7f <+191>: jne 0x7f6902108a97 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+215> 0x00007f6902108a81 <+193>: mov $0x1,%edx 0x00007f6902108a86 <+198>: lock cmpxchg %dl,(%rbx) 0x00007f6902108a8a <+202>: test %al,%al 0x00007f6902108a8c <+204>: je 0x7f6902108a52 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+146> 0x00007f6902108a8e <+206>: mov 0x0(%r13),%rdx 0x00007f6902108a92 <+210>: cmp %rdx,%rbx 0x00007f6902108a95 <+213>: je 0x7f6902108a3e <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+126> 0x00007f6902108a97 <+215>: test %rdx,%rdx 0x00007f6902108a9a <+218>: je 0x7f6902108aa0 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+224> 0x00007f6902108a9c <+220>: xor %eax,%eax 0x00007f6902108a9e <+222>: xchg %al,(%rdx) 0x00007f6902108aa0 <+224>: cmp %r14,%rbx 0x00007f6902108aa3 <+227>: je 0x7f6902108b00 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+320> 0x00007f6902108aa5 <+229>: and $0xfffffffffffffff8,%rcx 0x00007f6902108aa9 <+233>: add $0x12,%rcx 0x00007f6902108aad <+237>: cmp %rcx,%rbx 0x00007f6902108ab0 <+240>: je 0x7f6902108bd0 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+528> 0x00007f6902108ab6 <+246>: cmp %rbx,%r14 0x00007f6902108ab9 <+249>: jae 0x7f6902108b98 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+472> 0x00007f6902108abf <+255>: xor %edx,%edx 0x00007f6902108ac1 <+257>: mov $0x1,%ecx 0x00007f6902108ac6 <+262>: mov %edx,%eax 0x00007f6902108ac8 <+264>: lock cmpxchg %cl,(%r14) 0x00007f6902108acd <+269>: sete %al 0x00007f6902108ad0 <+272>: jne 0x7f6902108c26 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+614> 0x00007f6902108ad6 <+278>: mov %edx,%eax 0x00007f6902108ad8 <+280>: lock cmpxchg %cl,(%rbx) 0x00007f6902108adc <+284>: je 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108ae2 <+290>: mov %rbx,%rdi 0x00007f6902108ae5 <+293>: mov %rsi,-0x38(%rbp) 0x00007f6902108ae9 <+297>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108aee <+302>: mov -0x38(%rbp),%rsi 0x00007f6902108af2 <+306>: jmp 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108af7 <+311>: nopw 0x0(%rax,%rax,1) 0x00007f6902108b00 <+320>: xor %eax,%eax 0x00007f6902108b02 <+322>: mov $0x1,%edx 0x00007f6902108b07 <+327>: lock cmpxchg %dl,(%r14) 0x00007f6902108b0c <+332>: jne 0x7f6902108c66 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+678> 0x00007f6902108b12 <+338>: mov %r14,0x0(%r13) 0x00007f6902108b16 <+342>: cmp %r14,0x8(%r12) 0x00007f6902108b1b <+347>: jne 0x7f69021089e2 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+34> 0x00007f6902108b21 <+353>: jmp 0x7f6902108a16 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+86> 0x00007f6902108b26 <+358>: cs nopw 0x0(%rax,%rax,1) 0x00007f6902108b30 <+368>: mov %r14,0x8(%r12) 0x00007f6902108b35 <+373>: xor %eax,%eax 0x00007f6902108b37 <+375>: xchg %al,(%rbx) 0x00007f6902108b39 <+377>: mov %r14,0x0(%r13) 0x00007f6902108b3d <+381>: add $0x18,%rsp 0x00007f6902108b41 <+385>: pop %rbx 0x00007f6902108b42 <+386>: pop %r12 0x00007f6902108b44 <+388>: pop %r13 0x00007f6902108b46 <+390>: pop %r14 0x00007f6902108b48 <+392>: pop %r15 0x00007f6902108b4a <+394>: pop %rbp 0x00007f6902108b4b <+395>: ret 0x00007f6902108b4c <+396>: nopl 0x0(%rax) 0x00007f6902108b50 <+400>: test %rax,%rax 0x00007f6902108b53 <+403>: je 0x7f6902108b59 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+409> 0x00007f6902108b55 <+405>: xor %edx,%edx 0x00007f6902108b57 <+407>: xchg %dl,(%rax) 0x00007f6902108b59 <+409>: test %rbx,%rbx 0x00007f6902108b5c <+412>: je 0x7f6902108b6f <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+431> 0x00007f6902108b5e <+414>: xor %eax,%eax 0x00007f6902108b60 <+416>: mov $0x1,%edx 0x00007f6902108b65 <+421>: lock cmpxchg %dl,(%rbx) 0x00007f6902108b69 <+425>: jne 0x7f6902108c11 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+593> 0x00007f6902108b6f <+431>: mov %rbx,0x0(%r13) 0x00007f6902108b73 <+435>: jmp 0x7f6902108a0f <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+79> 0x00007f6902108b78 <+440>: nopl 0x0(%rax,%rax,1) 0x00007f6902108b80 <+448>: mov 0x0(%r13),%rdx 0x00007f6902108b84 <+452>: test %rdx,%rdx 0x00007f6902108b87 <+455>: jne 0x7f6902108a9c <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+220> 0x00007f6902108b8d <+461>: jmp 0x7f6902108aa0 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+224> 0x00007f6902108b92 <+466>: nopw 0x0(%rax,%rax,1) 0x00007f6902108b98 <+472>: xor %eax,%eax 0x00007f6902108b9a <+474>: mov $0x1,%edx 0x00007f6902108b9f <+479>: lock cmpxchg %dl,(%rbx) 0x00007f6902108ba3 <+483>: jne 0x7f6902108c51 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+657> 0x00007f6902108ba9 <+489>: xor %eax,%eax 0x00007f6902108bab <+491>: mov $0x1,%edx 0x00007f6902108bb0 <+496>: lock cmpxchg %dl,(%r14) 0x00007f6902108bb5 <+501>: je 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108bbb <+507>: mov %r14,%rdi 0x00007f6902108bbe <+510>: mov %rsi,-0x38(%rbp) 0x00007f6902108bc2 <+514>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108bc7 <+519>: mov -0x38(%rbp),%rsi 0x00007f6902108bcb <+523>: jmp 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108bd0 <+528>: xor %eax,%eax 0x00007f6902108bd2 <+530>: mov $0x1,%edx 0x00007f6902108bd7 <+535>: lock cmpxchg %dl,(%r14) 0x00007f6902108bdc <+540>: jne 0x7f6902108bff <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+575> 0x00007f6902108bde <+542>: xor %eax,%eax 0x00007f6902108be0 <+544>: mov $0x1,%edx 0x00007f6902108be5 <+549>: lock cmpxchg %dl,(%rbx) 0x00007f6902108be9 <+553>: je 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108bef <+559>: jmp 0x7f6902108ae2 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+290> 0x00007f6902108bf4 <+564>: nopl 0x0(%rax) 0x00007f6902108bf8 <+568>: ud2 0x00007f6902108bfa <+570>: jmp 0x7f6902108a16 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+86> 0x00007f6902108bff <+575>: mov %r14,%rdi 0x00007f6902108c02 <+578>: mov %rsi,-0x38(%rbp) 0x00007f6902108c06 <+582>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108c0b <+587>: mov -0x38(%rbp),%rsi 0x00007f6902108c0f <+591>: jmp 0x7f6902108bde <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+542> 0x00007f6902108c11 <+593>: mov %rbx,%rdi 0x00007f6902108c14 <+596>: mov %rsi,-0x38(%rbp) 0x00007f6902108c18 <+600>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108c1d <+605>: mov -0x38(%rbp),%rsi 0x00007f6902108c21 <+609>: jmp 0x7f6902108b6f <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+431> 0x00007f6902108c26 <+614>: mov %r14,%rdi 0x00007f6902108c29 <+617>: mov %al,-0x38(%rbp) 0x00007f6902108c2c <+620>: mov %rsi,-0x40(%rbp) 0x00007f6902108c30 <+624>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108c35 <+629>: movzbl -0x38(%rbp),%eax 0x00007f6902108c39 <+633>: mov $0x1,%ecx 0x00007f6902108c3e <+638>: lock cmpxchg %cl,(%rbx) 0x00007f6902108c42 <+642>: mov -0x40(%rbp),%rsi 0x00007f6902108c46 <+646>: je 0x7f6902108a5b <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+155> 0x00007f6902108c4c <+652>: jmp 0x7f6902108ae2 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+290> 0x00007f6902108c51 <+657>: mov %rbx,%rdi 0x00007f6902108c54 <+660>: mov %rsi,-0x38(%rbp) 0x00007f6902108c58 <+664>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108c5d <+669>: mov -0x38(%rbp),%rsi 0x00007f6902108c61 <+673>: jmp 0x7f6902108ba9 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+489> 0x00007f6902108c66 <+678>: mov %r14,%rdi 0x00007f6902108c69 <+681>: mov %rsi,-0x38(%rbp) 0x00007f6902108c6d <+685>: call 0x7f6900e0a180 <pas_lock_lock_slow@plt> 0x00007f6902108c72 <+690>: mov -0x38(%rbp),%rsi 0x00007f6902108c76 <+694>: jmp 0x7f6902108b12 <pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl+338> End of assembler dump.
Michael Catanzaro
Comment 3
2022-11-07 16:19:03 PST
I guess the problem must be that the check: if (*held_lock == page_lock && *held_lock == &cache_node->page_lock) { implies that cache_node is not NULL if *helf_lock == page_lock. Then maybe the subsequent || !cache_node check can be optimized away in that case? At any rate, it looks pretty suspicious that the dereference occurs *before* the nullptr check.
Michael Catanzaro
Comment 4
2022-11-07 16:53:07 PST
Maybe this would be as simple as: diff --git a/Source/bmalloc/libpas/src/libpas/pas_segregated_page.c b/Source/bmalloc/libpas/src/libpas/pas_segregated_page.c index 7d3cc2e05953..cc7350455d68 100644 --- a/Source/bmalloc/libpas/src/libpas/pas_segregated_page.c +++ b/Source/bmalloc/libpas/src/libpas/pas_segregated_page.c @@ -127,7 +127,7 @@ void pas_segregated_page_switch_lock_and_rebias_while_ineligible_impl( page_lock = page->lock_ptr; PAS_TESTING_ASSERT(page_lock); - if (*held_lock == page_lock && *held_lock == &cache_node->page_lock) { + if (*held_lock == page_lock && cache_node && *held_lock == &cache_node->page_lock) { pas_compiler_fence(); return; } But I'm not at all confident due to my lack of experience with assembly.
Michael Catanzaro
Comment 5
2022-11-08 13:46:44 PST
(In reply to Michael Catanzaro from
comment #4
)
> But I'm not at all confident due to my lack of experience with assembly.
So I built with and without this change locally, and stared at the disassembled code for a while. Adding the && cache_node check really changes things. That's about all I can say for sure, because I'm not smart enough to make heads or tails of what's going on, but seems worth a try....
Michael Catanzaro
Comment 6
2022-11-08 13:55:14 PST
Pull request:
https://github.com/WebKit/WebKit/pull/6261
EWS
Comment 7
2022-11-09 08:45:35 PST
Committed
256486@main
(0b3756093c94): <
https://commits.webkit.org/256486@main
> Reviewed commits have been landed. Closing PR #6261 and removing active labels.
Michael Catanzaro
Comment 8
2022-12-19 17:54:06 PST
BTW I'm pretty sure this speculative fix actually worked, because I have not seen this crash in a while.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug