none
Assert in rtllocks.cpp LockQueueNode::Copy() function when using recursive_timed_mutex

    Domanda

  • On my system the following code causes an assert to fire in a Debug build in the CRT file rtlocks.cpp, line 754, in the function Concurrency::details::LockQueueNode::Copy(). In my test If I reduce the number of threads to thread::hardware_concurrency() I don't see the assert fire but I'm not sure if the problem is just less frequent with fewer threads or if it actually goes away. Am I doing something unsafe in this code or is this an issue with the Concurrency Runtime?

    #include <chrono>
    #include <thread>
    #include <mutex>
    #include <atomic>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    #include <cstdlib>
    #include <cassert>
    
    using namespace std;
    using namespace std::chrono;
    
    
    struct WorkData
    {
        atomic<bool> mbShouldQuit;
        recursive_timed_mutex mMutex;
    
        WorkData() : mbShouldQuit(false) {}
    };
    
    void ThreadSleepRandom(int minSleepMs, int maxSleepMs)
    {
        int sleepTimeMs = minSleepMs;
        if ((maxSleepMs - minSleepMs) > 0)
            sleepTimeMs += (rand() % (maxSleepMs - minSleepMs));
    
        this_thread::sleep_for(milliseconds(sleepTimeMs));
    }
    
    intptr_t MutexTestThreadFunction(WorkData* pWorkData)
    {
        while (!pWorkData->mbShouldQuit)
        {
            const int nRecursiveLockCount(rand() % 3);
            int nLocks = 0;
    
            for (int i = 0; i < nRecursiveLockCount; ++i)
            {
                // Do a lock but allow for the possibility of occasional timeout.
                const auto expectedTime(system_clock::now() + milliseconds(1000));
                if (pWorkData->mMutex.try_lock_until(expectedTime)) // If there was no timeout...
                {
                    ++nLocks;
                    ThreadSleepRandom(10, 20);
                }
            }
    
            while (nLocks > 0)
            {
                --nLocks;
                pWorkData->mMutex.unlock();
            }
    
            ThreadSleepRandom(100, 200);
        }
    
        return 0;
    }
    
    
    void TestThreadMutex()
    {
        cout << "Starting " __FUNCTION__ << endl;
    
        WorkData workData; 
    
        const int kThreadCount = 16;
        vector<thread> threads;
        for (int i = 0; i < kThreadCount; ++i) {
            threads.emplace_back(MutexTestThreadFunction, &workData);
        }
    
        const auto testLengthSeconds = 1;
        ThreadSleepRandom(testLengthSeconds*1000, testLengthSeconds*1000);
    
        workData.mbShouldQuit = true;
    
        for_each(begin(threads), end(threads), [](thread& t) { 
            t.join(); 
        });
    
        cout << "Ending " __FUNCTION__ << endl << endl;
    }
    
    int main()
    {
        TestThreadMutex();
        return 0;
    }



    • Modificato mattnewport giovedì 19 aprile 2012 20:11 Removed redundant code
    giovedì 19 aprile 2012 20:09

Risposte

  • Hi mattnewport,

    I believe this is caused by a known internal bug in concurrency::critical_section, which we are working on solution.

    thanks for your dogfooding.

    Hong

    • Contrassegnato come risposta mattnewport giovedì 26 aprile 2012 19:54
    giovedì 26 aprile 2012 19:44