没有用户代码的死锁 [英] Deadlock with no user code
问题描述
我在我的C ++程序中遇到了死锁,它使用std :: thread,std :: mutex,std :: condition_variable等。
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()
没有线程似乎在执行我的代码,我知道一个事实,我们已经输入main,因为程序在挂起之前做了一些东西。
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.
我使用下面的类来与我的std ::线程沟通,万一我犯了一些错误:
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;
};
我现在有两个想法:
- 主要由于某种原因已退出。这是一个PoC,所以当有一个错误,我们记录到stdout并调用exit()(是的,我知道,不是最大的,这是从另一个C风格的程序编写的C + +)。我没有看到任何东西记录到终端,但我想这可能是输出被缓冲,还没有写出来?
- 调试器在我躺在一些办法。通常它会把
[下面的框架可能会丢失/不正确]
进入堆栈跟踪,当它这样做,但也许会发生没有这个。
- 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?
- 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.
推荐答案
原来我没有替换队列中的项目,导致我的线程从队列,这意味着调试器对我说谎。 :(
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. :(
这篇关于没有用户代码的死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!