我正在编写一个小应用程序,它通过串口处理预定义的消息交换(基本上是一个自定义应用程序级协议)。 它的主要部分是一个状态机,它定义了对某个预期消息的响应,停止条件,预期消息的超时等,以及一个单独监听(通过阻塞调用)的“事件循环”线程到通信事件,当它被唤醒时,它将它传递给要处理的状态机。这反过来将使状态流动并重复该过程,直到达到最终状态,此时主线程被唤醒(正在等待std :: cond_var)并加入线程。
出现问题时,出乎意料的是,对运营商的呼叫<< cout无限期地阻塞事件循环线程。调用堆栈显示线程正在WriteFile调用中等待。这似乎是一个僵局。我没有关于Windows API和内部工作的文档,但它似乎显然不会给用户带来任何潜在的同步问题(死锁),即使它可能无法按预期工作(我明白不排除访问权限)例如stdout的那个部分至少会导致交错消息 - 这不是我的问题。)
我附加了2个printcreens,其中我捕获了Visual Studio显示的线程堆栈。我真的相信应该没有应用程序编写用户空间,无论多么糟糕,都会导致控制台输出死锁,这就是为什么我不在这里粘贴代码。
搜索网络一天半,此时我不知道如何重新搜索谷歌搜索以获取一些有用的信息。即使我确实得到了,也不要认为我必须知道。你能指点我一些方向吗?也许是stdout的常见问题。或者在我的代码中我可以做的非常糟糕的事情导致这种死锁。提前谢谢。
First operator<< sometimes reproduces the issue
void CSerialConnection::funct(std::tuple<bool, bool, int> args)
{
bool singleByteExpected = get<1>(args), stopped = get<0>(args);
unsigned int timeoutValue = get<2>(args);
bool terminate = false;
DWORD modemStatus;
OVERLAPPED osStatus;
memset(&osStatus, 0, sizeof(OVERLAPPED));
osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
cout << "Starting communication event loop ... " << endl;
BOOL fWaitingOnStat = FALSE;
BOOL bReadStatus = FALSE;
do
{
if (!fWaitingOnStat)
{
cout << "Listening for " << (singleByteExpected ? "control character .. " : "command payload .. ") << endl;
SetCommMask(mHandle, (singleByteExpected ? EV_RXCHAR : EV_RXFLAG ));
bReadStatus = WaitCommEvent(mHandle, &modemStatus, &osStatus);
}
if (bReadStatus)
{
cout << "Event occured sync" << endl;
mProtocol.processEvent(terminate);
if (terminate)
{
break;
}
}
else
{
if (GetLastError() == ERROR_IO_PENDING)
{
fWaitingOnStat = TRUE;
}
else
{
cout << "Communication event failed with code: " << GetLastError() << endl;
mProtocol.processTermination();
stopped = true;
}
if ( fWaitingOnStat )
{
cout << dec << "WAITING FOR " << ( timeoutValue ? timeoutValue : INFINITE ) << endl;
auto dwRes = WaitForSingleObject(osStatus.hEvent, timeoutValue ? timeoutValue : INFINITE);
cout << "WAIT ENDED :)" << endl;
if (dwRes == WAIT_OBJECT_0)
{
//cout << "Event occured async" << endl;
mProtocol.processEvent(terminate);
fWaitingOnStat = false;
if (terminate)
{
mProtocol.processTermination();
break;
}
}
else if (dwRes == WAIT_TIMEOUT)
{
cout << "Timeout" << endl;
mProtocol.processTimeout();
fWaitingOnStat = false;
}
else
{
cout << "Communication event failed with code: " << GetLastError( ) << endl;
mProtocol.processTermination();
stopped = true;
}
}
}
stopped = mProtocol.getStopRequiredFlag();
singleByteExpected = mProtocol.getWaitingForControlCharFlag();
timeoutValue = mProtocol.getTimeout();
}
while (!stopped);
cout << "Stopped communication event loop ... " << endl;
}
答案 0 :(得分:-1)
解决!根据UKMonkey的建议,行为是由我在控制台窗口上标记文本引起的。如果我单独留下它并且阻止我标记一个角色,它现在一定有效。我需要更改这些设置:)。感谢您对我的问题和答案感兴趣!