没有用户代码的死锁

时间:2015-02-06 20:08:43

标签: c++ multithreading c++11 visual-studio-2013 deadlock

我在我的C ++程序中遇到了死锁,它使用了std :: thread,std :: mutex,std :: condition_variable等。

在我看到我的进程中的每个线程的堆栈之前,对此没有任何异议:

8532    0   Main Thread Main Thread msvcr120.dll!Concurrency::details::ExternalContextBase::Block   Normal
                        ntdll.dll!_ZwWaitForSingleObject@12()    
                        KernelBase.dll!_WaitForSingleObjectEx@12()   
                        kernel32.dll!_WaitForSingleObjectExImplementation@12()   
                        msvcr120.dll!Concurrency::details::ExternalContextBase::Block() Line 145     
                        ntdll.dll!_ZwQueryVirtualMemory@24()     
                        kernel32.dll!_BasepFillUEFInfo@8()   
                        ntdll.dll!_ZwQueryInformationProcess@20()    
                        msvcr120.dll!_initterm(void (void) * * pfbegin, void (void) * * pfend) Line 954  

-

6484    0   Worker Thread   ntdll.dll!_TppWaiterpThread@4() ntdll.dll!_NtWaitForMultipleObjects@20  Normal
                        ntdll.dll!_NtWaitForMultipleObjects@20()     
                        ntdll.dll!_TppWaiterpThread@4()  
                        kernel32.dll!@BaseThreadInitThunk@12()   
                        ntdll.dll!___RtlUserThreadStart@8()  
                        ntdll.dll!__RtlUserThreadStart@8()   

-

6296    0   Worker Thread   msvcr120.dll!_threadstartex msvcr120.dll!Concurrency::details::ExternalContextBase::Block   Normal
                        ntdll.dll!_ZwWaitForSingleObject@12()    
                        KernelBase.dll!_WaitForSingleObjectEx@12()   
                        kernel32.dll!_WaitForSingleObjectExImplementation@12()   
                        msvcr120.dll!Concurrency::details::ExternalContextBase::Block() Line 145     
                        msvcp120.dll!std::_Thrd_startX(struct _Thrd_imp_t *,unsigned int (*)(void *),void *)     
                        msvcr120.dll!_callthreadstartex() Line 376   
                        msvcr120.dll!_threadstartex(void * ptd) Line 354     
                        kernel32.dll!@BaseThreadInitThunk@12()   
                        ntdll.dll!___RtlUserThreadStart@8()  
                        ntdll.dll!__RtlUserThreadStart@8()   

没有线程似乎正在执行我的代码,而且我知道我们已经进入main的事实,因为程序在挂起之前做了一些事情。

我使用以下类与我的std :: thread进行通信,以防我在那里犯了一些错误:

template <typename T>
class BlockingQueue
{
public:
    BlockingQueue() : _active(true) {}

    bool Get(T& out)
    {
        std::unique_lock<std::mutex> lock(_mutex);

        _cv.wait(lock, [&](){ return !_queue.empty() || !_active; });

        if (_queue.empty())
        {
            assert(!_active);

            return false;
        }

        out = std::move(_queue.front());
        _queue.pop();

        return true;
    }

    void Put(const T& in)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);

            _queue.push(in);
        }

        _cv.notify_one();
    }

    void Put(T&& in)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);

            _queue.push(std::move(in));
        }

        _cv.notify_one();
    }

    void Finish()
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);

            _active = false;
        }

        _cv.notify_all();
    }

private:
    bool _active;
    std::mutex _mutex;
    std::condition_variable _cv;
    std::queue<T> _queue;
};

我现在有两个想法:

  1. Main已经因某种原因退出了。这是一个PoC,所以当出现错误时我们会记录到stdout并调用exit()(是的,我知道,不是最好的,这是从另一个用C ++编写的C风格的程序改编而来)。我没有看到任何记录到终端的内容,但我认为输出可能已被缓冲并且还没有被写出来?
  2. 调试器以某种方式骗我。通常它在执行此操作时会将[frames below may be missing/incorrect]放入堆栈跟踪中,但可能会在没有它的情况下发生。

1 个答案:

答案 0 :(得分:0)

事实证明我没有替换队列中的项目,导致我的线程在从队列中检索时死锁,这意味着调试器对我说谎。 :(