VirtualBox

Changeset 10792

Show
Ignore:
Timestamp:
07/22/08 00:19:26 (4 months ago)
Author:
vboxsync
Message:

IPRT: Fixed issue where RTCreateThread would race against the termination of the new thread, if RTCreateThread didn't manage to insert the thread before the new thread completed, we would be inserting a thread into the tree that was terminated and which native ID should not be in the tree. If the OS then reused the native thread ID immediately (OS/2 and now glibc/linux), we would end up with a duplicate in the tree and get all confused. The fix is to check the state in rtThreadInsert and never insert a terminated thread.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/VBox/Runtime/common/misc/thread.cpp

    r8679 r10792  
    256256        { 
    257257            rtThreadInsert(pThread, NativeThread); 
    258             pThread->enmState = RTTHREADSTATE_RUNNING
     258            ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING)
    259259            rtThreadRelease(pThread); 
    260260        } 
     
    370370 
    371371    /* 
    372      * Before inserting we must check if there is a thread with this id 
    373      * in the tree already. We're racing parent and child on insert here 
    374      * so that the handle is valid in both ends when they return / start. 
     372     * Do not insert a terminated thread. 
    375373     * 
    376      * If it's not ourself we find, it's a dead alien thread and we will 
    377      * unlink it from the tree. Alien threads will be released at this point. 
    378      */ 
    379     PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread); 
    380     if (pThreadOther != pThread) 
    381     { 
    382         /* remove dead alien if any */ 
    383         if (pThreadOther) 
     374     * This may happen if the thread finishes before the RTThreadCreate call 
     375     * gets this far. Since the OS may quickly reuse the native thread ID 
     376     * it should not be reinserted at this point. 
     377     */ 
     378    if (pThread->enmState != RTTHREADSTATE_TERMINATED) 
     379    { 
     380        /* 
     381         * Before inserting we must check if there is a thread with this id 
     382         * in the tree already. We're racing parent and child on insert here 
     383         * so that the handle is valid in both ends when they return / start. 
     384         * 
     385         * If it's not ourself we find, it's a dead alien thread and we will 
     386         * unlink it from the tree. Alien threads will be released at this point. 
     387         */ 
     388        PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread); 
     389        if (pThreadOther != pThread) 
    384390        { 
    385             Assert(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN); 
    386             ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT); 
    387             rtThreadRemoveLocked(pThreadOther); 
    388             if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN) 
    389                 rtThreadRelease(pThreadOther); 
     391            /* remove dead alien if any */ 
     392            if (pThreadOther) 
     393            { 
     394                AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName)); 
     395                ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT); 
     396                rtThreadRemoveLocked(pThreadOther); 
     397                if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN) 
     398                    rtThreadRelease(pThreadOther); 
     399            } 
     400 
     401            /* insert the thread */ 
     402            ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread); 
     403            bool fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core); 
     404            ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE); 
     405 
     406            AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName)); 
     407            NOREF(fRc); 
    390408        } 
    391  
    392         /* insert the thread */ 
    393         pThread->Core.Key = (void *)NativeThread; 
    394         bool fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core); 
    395         ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE); 
    396  
    397         AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName)); 
    398         NOREF(fRc); 
    399409    } 
    400410 
     
    544554     * Free resources. 
    545555     */ 
    546     pThread->Core.Key   = (void *)NIL_RTTHREAD
     556    ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD)
    547557    pThread->enmType    = RTTHREADTYPE_INVALID; 
    548558    RTSemEventMultiDestroy(pThread->EventUser); 
     
    579589     */ 
    580590    pThread->rc = rc; 
    581     ASMAtomicXchgSize(&pThread->enmState, RTTHREADSTATE_TERMINATED); 
     591    ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_TERMINATED); 
    582592    ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED); 
    583593    if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI) 
     
    625635     * Call thread function and terminate when it returns. 
    626636     */ 
    627     pThread->enmState = RTTHREADSTATE_RUNNING
     637    ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING)
    628638    rc = pThread->pfnThread(pThread, pThread->pvUser); 
    629639 
     
    13671377        pThread->uBlockLine     = uLine; 
    13681378        pThread->uBlockId       = uId; 
    1369         ASMAtomicXchgSize(&pThread->enmState, enmState); 
     1379        ASMAtomicWriteSize(&pThread->enmState, enmState); 
    13701380 
    13711381        /* 
     
    14521462{ 
    14531463    if (pThread && pThread->enmState == enmCurState) 
    1454         ASMAtomicXchgSize(&pThread->enmState, RTTHREADSTATE_RUNNING); 
     1464        ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING); 
    14551465} 
    14561466 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy