Deadlock with no user code

十年热恋 提交于 2019-12-22 10:35:23

问题


I'm getting a deadlock in my C++ program, which used std::thread, std::mutex, std::condition_variable, etc.

There's nothing in itself strange about that, until I look at the stacks for each of the threads in my process:

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()   

None of the threads seem to be executing my code, and I know for a fact that we had already entered main, since the program had done some stuff before hanging.

I'm using the following class to communicate with my std::thread, in case I made some mistake there:

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;
};

I have two ideas right now:

  1. Main has already exited for some reason. This is a PoC, so when there's an error we log to stdout and call exit() (Yeah I know, not the greatest, this is being adapted from another C-style program written in C++). I do not see anything being logged to the terminal, but I suppose it's possible that the output was being buffered and hasn't been written out yet?
  2. The debugger is lying to me in some way. Usually it puts in [frames below may be missing/incorrect] into the stack trace when it does this, but maybe it can happen without that.

回答1:


It turns out I was failing to replace an item in a queue, causing my thread to deadlock on retrieving from the queue, which means that the debugger was lying to me. :(



来源:https://stackoverflow.com/questions/28373904/deadlock-with-no-user-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!