Changeset 179900 in webkit
- Timestamp:
- Feb 10, 2015, 4:12:18 PM (12 years ago)
- Location:
- branches/safari-600.1.4.15-branch/Source/JavaScriptCore
- Files:
-
- 3 edited
-
API/tests/testapi.mm (modified) (3 diffs)
-
ChangeLog (modified) (1 diff)
-
heap/MachineStackMarker.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-600.1.4.15-branch/Source/JavaScriptCore/API/tests/testapi.mm
r167326 r179900 30 30 #import "JSExportTests.h" 31 31 32 #import <pthread.h> 33 32 34 extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef); 33 35 extern "C" void JSSynchronousEdenCollectForDebugging(JSContextRef); … … 469 471 }(); 470 472 return containsClass; 473 } 474 475 static void* threadMain(void* contextPtr) 476 { 477 JSContext *context = (__bridge JSContext*)contextPtr; 478 479 // Do something to enter the VM. 480 TestObject *testObject = [TestObject testObject]; 481 context[@"testObject"] = testObject; 482 pthread_exit(nullptr); 471 483 } 472 484 … … 1360 1372 } 1361 1373 1374 @autoreleasepool { 1375 JSContext *context = [[JSContext alloc] init]; 1376 1377 pthread_t threadID; 1378 pthread_create(&threadID, NULL, &threadMain, (__bridge void*)context); 1379 pthread_join(threadID, nullptr); 1380 JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]); 1381 1382 checkResult(@"Did not crash after entering the VM from another thread", true); 1383 } 1384 1362 1385 currentThisInsideBlockGetterTest(); 1363 1386 runDateTests(); -
branches/safari-600.1.4.15-branch/Source/JavaScriptCore/ChangeLog
r179890 r179900 1 2015-02-10 Babak Shafiei <bshafiei@apple.com> 2 3 Merge r179576, r179648. 4 5 2015-02-04 Mark Lam <mark.lam@apple.com> 6 7 r179576 introduce a deadlock potential during GC thread suspension. 8 <https://webkit.org/b/141268> 9 10 Reviewed by Michael Saboff. 11 12 http://trac.webkit.org/r179576 introduced a potential for deadlocking. 13 In the GC thread suspension loop, we currently delete 14 MachineThreads::Thread that we detect to be invalid. This is unsafe 15 because we may have already suspended some threads, and one of those 16 suspended threads may still be holding the C heap lock which we need 17 for deleting the invalid thread. 18 19 The fix is to put the invalid threads in a separate toBeDeleted list, 20 and delete them only after GC has resumed all threads. 21 22 * heap/MachineStackMarker.cpp: 23 (JSC::MachineThreads::removeCurrentThread): 24 - Undo refactoring removeThreadWithLockAlreadyAcquired() out of 25 removeCurrentThread() since it is no longer needed. 26 27 (JSC::MachineThreads::tryCopyOtherThreadStacks): 28 - Put invalid Threads on a threadsToBeDeleted list, and delete those 29 Threads only after all threads have been resumed. 30 31 (JSC::MachineThreads::removeThreadWithLockAlreadyAcquired): Deleted. 32 * heap/MachineStackMarker.h: 33 34 2015-02-03 Mark Lam <mark.lam@apple.com> 35 36 Workaround a thread library bug where thread destructors may not get called. 37 <https://webkit.org/b/141209> 38 39 Reviewed by Michael Saboff. 40 41 There's a bug where thread destructors may not get called. As far as 42 we know, this only manifests on darwin ports. We will work around this 43 by checking at GC time if the platform thread is still valid. If not, 44 we'll purge it from the VM's registeredThreads list before proceeding 45 with thread scanning activity. 46 47 Note: it is important that we do this invalid thread detection during 48 suspension, because the validity (and liveness) of the other thread is 49 only guaranteed while it is suspended. 50 51 * API/tests/testapi.mm: 52 (threadMain): 53 - Added a test to enter the VM from another thread before we GC on 54 the main thread. 55 56 * heap/MachineStackMarker.cpp: 57 (JSC::MachineThreads::removeThreadWithLockAlreadyAcquired): 58 (JSC::MachineThreads::removeCurrentThread): 59 - refactored removeThreadWithLockAlreadyAcquired() out from 60 removeCurrentThread() so that we can also call it for purging invalid 61 threads. 62 (JSC::suspendThread): 63 - Added a return status to tell if the suspension succeeded or not. 64 (JSC::MachineThreads::tryCopyOtherThreadStacks): 65 - Check if the suspension failed, and purge the thread if we can't 66 suspend it. Failure to suspend implies that the thread has 67 terminated without calling its destructor. 68 * heap/MachineStackMarker.h: 69 1 70 2015-02-10 Babak Shafiei <bshafiei@apple.com> 2 71 -
branches/safari-600.1.4.15-branch/Source/JavaScriptCore/heap/MachineStackMarker.cpp
r179295 r179900 241 241 } 242 242 243 static inline void suspendThread(const PlatformThread& platformThread) 244 { 245 #if OS(DARWIN) 246 thread_suspend(platformThread); 247 #elif OS(WINDOWS) 248 SuspendThread(platformThread); 243 static inline bool suspendThread(const PlatformThread& platformThread) 244 { 245 #if OS(DARWIN) 246 kern_return_t result = thread_suspend(platformThread); 247 return result == KERN_SUCCESS; 248 #elif OS(WINDOWS) 249 bool threadIsSuspended = (SuspendThread(platformThread) != (DWORD)-1); 250 ASSERT(threadIsSuspended); 251 return threadIsSuspended; 249 252 #elif USE(PTHREADS) 250 253 pthread_kill(platformThread, SigThreadSuspendResume); 254 return true; 251 255 #else 252 256 #error Need a way to suspend threads on this platform … … 453 457 MutexLocker lock(m_registeredThreadsMutex); 454 458 459 Thread* threadsToBeDeleted = nullptr; 460 455 461 #ifndef NDEBUG 456 462 // Forbid malloc during the gather phase. The gather phase suspends … … 459 465 fastMallocForbid(); 460 466 #endif 461 for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { 462 if (!equalThread(thread->platformThread, currentPlatformThread)) 463 suspendThread(thread->platformThread); 467 int numberOfThreads = 0; // Using 0 to denote that we haven't counted the number of threads yet. 468 int index = 1; 469 Thread* previousThread = nullptr; 470 for (Thread* thread = m_registeredThreads; thread; index++) { 471 if (!equalThread(thread->platformThread, currentPlatformThread)) { 472 bool success = suspendThread(thread->platformThread); 473 #if OS(DARWIN) 474 if (!success) { 475 if (!numberOfThreads) { 476 for (Thread* countedThread = m_registeredThreads; countedThread; countedThread = countedThread->next) 477 numberOfThreads++; 478 } 479 480 // Re-do the suspension to get the actual failure result for logging. 481 kern_return_t error = thread_suspend(thread->platformThread); 482 ASSERT(error != KERN_SUCCESS); 483 484 WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 485 "JavaScript garbage collection encountered an invalid thread (err 0x%x): Thread [%d/%d: %p] platformThread %p.", 486 error, index, numberOfThreads, thread, reinterpret_cast<void*>(thread->platformThread)); 487 488 // Put the invalid thread on the threadsToBeDeleted list. 489 // We can't just delete it here because we have suspended other 490 // threads, and they may still be holding the C heap lock which 491 // we need for deleting the invalid thread. Hence, we need to 492 // defer the deletion till after we have resumed all threads. 493 Thread* nextThread = thread->next; 494 thread->next = threadsToBeDeleted; 495 threadsToBeDeleted = thread; 496 497 if (previousThread) 498 previousThread->next = nextThread; 499 else 500 m_registeredThreads = nextThread; 501 thread = nextThread; 502 continue; 503 } 504 #else 505 UNUSED_PARAM(numberOfThreads); 506 ASSERT_UNUSED(success, success); 507 #endif 508 } 509 previousThread = thread; 510 thread = thread->next; 464 511 } 465 512 … … 479 526 fastMallocAllow(); 480 527 #endif 528 for (Thread* thread = threadsToBeDeleted; thread; ) { 529 Thread* nextThread = thread->next; 530 delete thread; 531 thread = nextThread; 532 } 481 533 } 482 534 }
Note:
See TracChangeset
for help on using the changeset viewer.