c++ asio posix流描述符async_read未在MAC上完成

oxcyiej7  于 2023-03-14  发布在  Mac
关注(0)|答案(1)|浏览(171)

我在MAC和Linux上的行为不同(ubuntu)当涉及到在asio::posix::stream_descriptor上执行async_read/async_write时。在我的mac上,迭代执行一次(输出iter 13),然后由于async_read(...)async_write(...)完成句柄从未被调用而挂起在std::future<...>::get()处的第二次迭代。输出符合预期,即

iter 13
iter 14

有趣的是,如果我切换读/写的顺序,那么它在Mac上可以正常工作。另外,如果我总是读/写最多8192=(1<<13)字节的数据,那么读/写完成句柄将被调用。
stream_descriptor被分配到的文件是由mkfifo(...)创建的命名管道。
有没有人知道为什么这是挂在mac上,如果有一个修复?

#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;
}
9lowa7mx

9lowa7mx1#

ioc.run没有待执行的操作,www.example.com()将退出。如果它退出,将没有异步操作的执行线程。
需要work_guard来防止ioc.run()退出。
可能未使用自动工作保护= asio::使工作保护(ioc);
ioc.run();

相关问题