⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179900 in webkit


Ignore:
Timestamp:
Feb 10, 2015, 4:12:18 PM (12 years ago)
Author:
bshafiei@apple.com
Message:

Merged r179576, r179648. rdar://problem/19709260

Location:
branches/safari-600.1.4.15-branch/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-600.1.4.15-branch/Source/JavaScriptCore/API/tests/testapi.mm

    r167326 r179900  
    3030#import "JSExportTests.h"
    3131
     32#import <pthread.h>
     33
    3234extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
    3335extern "C" void JSSynchronousEdenCollectForDebugging(JSContextRef);
     
    469471    }();
    470472    return containsClass;
     473}
     474
     475static 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);
    471483}
    472484
     
    13601372    }
    13611373
     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   
    13621385    currentThisInsideBlockGetterTest();
    13631386    runDateTests();
  • branches/safari-600.1.4.15-branch/Source/JavaScriptCore/ChangeLog

    r179890 r179900  
     12015-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
    1702015-02-10  Babak Shafiei  <bshafiei@apple.com>
    271
  • branches/safari-600.1.4.15-branch/Source/JavaScriptCore/heap/MachineStackMarker.cpp

    r179295 r179900  
    241241}
    242242
    243 static inline void suspendThread(const PlatformThread& platformThread)
    244 {
    245 #if OS(DARWIN)
    246     thread_suspend(platformThread);
    247 #elif OS(WINDOWS)
    248     SuspendThread(platformThread);
     243static 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;
    249252#elif USE(PTHREADS)
    250253    pthread_kill(platformThread, SigThreadSuspendResume);
     254    return true;
    251255#else
    252256#error Need a way to suspend threads on this platform
     
    453457        MutexLocker lock(m_registeredThreadsMutex);
    454458
     459        Thread* threadsToBeDeleted = nullptr;
     460
    455461#ifndef NDEBUG
    456462        // Forbid malloc during the gather phase. The gather phase suspends
     
    459465        fastMallocForbid();
    460466#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;
    464511        }
    465512
     
    479526        fastMallocAllow();
    480527#endif
     528        for (Thread* thread = threadsToBeDeleted; thread; ) {
     529            Thread* nextThread = thread->next;
     530            delete thread;
     531            thread = nextThread;
     532        }
    481533    }
    482534}
Note: See TracChangeset for help on using the changeset viewer.