VirtualBox

Changeset 10792 in vbox for trunk


Ignore:
Timestamp:
Jul 21, 2008 10:19:26 PM (16 years 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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette