У меня другое поведение на MA C против Linux (ubuntu), когда дело доходит до async_read
/ async_write
на asio::posix::stream_descriptor
. На моей ма c итерация выполняется один раз (вывод iter 13
), а затем зависает на второй итерации в std::future<...>::get()
из-за того, что дескрипторы завершения async_read(...)
и async_write(...)
никогда не вызываются. На моей машине Linux вывод соответствует ожидаемому, то есть
iter 13
iter 14
Интересно, что если я переключу порядок чтения / записи, то он будет работать правильно на ma c. Кроме того, если я всегда читаю / записываю данные размером не более 8192=(1<<13)
байт, то будут вызываться дескрипторы завершения чтения / записи.
Файл, которому назначен stream_descriptor
, является именованным каналом, созданным mkfifo(...)
. Ниже приведен минимальный пример, который я смог сделать.
Кто-нибудь знает, почему это висит на ма c и есть ли исправление?
#include "boost/asio.hpp"
#include <future>
#include <iostream>
#include <cstdio>
int main()
{
using stream_descriptor = boost::asio::posix::stream_descriptor;
// setup the background thread.
boost::asio::io_context ioc;
auto worker = std::make_unique<boost::asio::io_context::work>(ioc);
std::thread thrd([&] {ioc.run(); });
// remove and make the named pipe.
std::string name = "/home/peter/myFifo";
std::remove(name.c_str());
if (mkfifo(name.c_str(), 0666))
throw std::runtime_error("error opening fifo");
// open the two ends of the named pipe. The
// std::async is there since the first will block
// until the second is opened.
int ifd, ofd;
auto f = std::async([&]() {
ifd = open(name.c_str(), O_RDONLY);
});
ofd = open(name.c_str(), O_WRONLY);
f.get();
// create the asio adapter
stream_descriptor in(ioc), out(ioc);
in.assign(ifd);
out.assign(ofd);
// these lines seems to make no difference.
//in.non_blocking(true);
//out.non_blocking(true);
// iterate the the messages sizes that are causing issues.
for (int i = 13; i < 15; ++i)
{
int size = (1 << i);
std::vector<char> buff(size);
boost::asio::mutable_buffer mb(buff.data(), buff.size());
std::promise<boost::system::error_code> p0, p1;
boost::asio::async_read(in, mb,
[&](const boost::system::error_code& ec, size_t bt) {
p1.set_value(ec);
});
boost::asio::async_write(out, mb,
[&](const boost::system::error_code& ec, size_t bt) {
p0.set_value(ec);
});
p0.get_future().get();
p1.get_future().get();
std::cout << "iter " << i << std::endl;
}
// cleanup
worker.reset();
thrd.join();
return 0;
}