环境是UOS。
代码原来是针对父子进程间的匿名管道的,跑着没啥问题。
现在改为命名管道(fifo)。原来用async_pipe操作匿名管道,改为用stream_descriptor来操作fifo,其他没变。
但是发现async_write()、deadline_timer的async_wait()的完成函数没被调用,所以卡死。
io_context的run()是在一个单独的线程中调用的,那个线程只执行run()这一句。线程个数是1,所以不会并发执行run。
搜了一下,发现有人也遇到过这个问题,他在linux ok,但是macos上有问题:
https://stackoverflow.com/questions/60446097/asio-posix-stream-descriptor-async-read-not-completing-on-mac
bool CPipeIPC::SendMessageInternal(const std::string &payload, size_t timeout) {
// 我们用于写入的fifo是按需打开的,因为只有当对端打开用于读取后,我们才能成功打开。
if (m_pipe_fd1 == -1) {
if (!OpenPipe(PIPE_NAME1, m_pipe_fd1, m_pipe_stream1, O_WRONLY | O_NONBLOCK)) {
LOG(ERROR, "can't open pipe for writing");
return false;
} else {
LOG(INFO, "open pipe success for writing");
}
}
m_status = STATUS::NONE;
ResetEvent(m_event);
volatile bool timer_done = false;
volatile bool write_done = false;
boost::asio::deadline_timer timer{*m_io};
timer.expires_from_now(boost::posix_time::millisec(timeout));
timer.async_wait([&](const boost::system::error_code &ec) {
timer_done = true;
if (ec == boost::asio::error::operation_aborted) {
LOG(INFO, "writer timer cancelled");
} else if (ec) {
LOG(INFO, "writer timer error: " << ec);
} else {
LOG(INFO, "writer timer timeout");
if (m_status == STATUS::NONE) {
m_status = STATUS::SEND_TIMEOUT;
m_pipe_stream1->cancel();
}
}
if (timer_done && write_done) SetEvent(m_event);
});
boost::asio::async_write(*m_pipe_stream1, boost::asio::buffer(payload),
[&](const boost::system::error_code &ec, std::size_t n) {
write_done = true;
if (ec == boost::asio::error::operation_aborted) {
LOG(INFO, "writer oper aborted by timer");
} else if (ec) {
LOG(INFO, "writer oper error: " << ec);
m_status = STATUS::SEND_FAILED;
timer.cancel();
} else {
LOG(INFO, "writer oper success");
m_status = STATUS::SEND_SUCCESS;
timer.cancel();
}
if (timer_done && write_done) SetEvent(m_event);
});
WaitForEvent(m_event, WAIT_INFINITE);
return m_status == STATUS::SEND_SUCCESS;
}
--
修改:z16166 FROM 222.131.206.*
FROM 222.131.206.*