[asio-users] timer does only work once when building with BOOST_ASIO_HAS_IO_URING_AS_DEFAULT
Brought to you by:
chris_kohlhoff
From: Christian E. <CE...@gm...> - 2024-09-12 14:51:23
|
OS: linux-6.6.49 Boost: 1.84.0 I have taken an older "blocking read with timeout" example from here: https://lists.boost.org/Archives/boost/2007/04/120339.php This example (updated source code below) works fine as long as using the epoll reactor (simply try with a non connected UART, the program should finish after two seconds). But as soon as I switch to the io_uring implementation (by defining BOOST_ASIO_HAS_IO_URING and BOOST_ASIO_HAS_IO_URING_AS_DEFAULT), the 2nd timeout is not reached (program exits after 301 seconds). When I only define BOOST_ASIO_HAS_IO_URING (without BOOST_ASIO_HAS_IO_URING_AS_DEFAULT), the program works fine. Additionally I recognized that the behavior depends on the timing. When single stepping in a debugger, also the 2nd timeout works correctly. Q: Is the example program correct? Q: Why does it not work as expected with io_uring? regards, Christian #include <chrono> #include <iostream> #include <boost/asio.hpp> #include <boost/bind/bind.hpp> #include <boost/optional.hpp> #include <boost/system/error_code.hpp> using namespace boost; using namespace boost::asio; using namespace std::chrono; using namespace boost::placeholders; using namespace boost::system; void set_result(optional<boost::system::error_code>* a, boost::system::error_code b) { a->reset(b); } template <typename MutableBufferSequence> void read_with_timeout(io_context& io_context, serial_port& port, const MutableBufferSequence& buffers) { optional<error_code> timer_result; steady_timer timer(io_context); timer.expires_after(seconds(1)); timer.async_wait( boost::bind(set_result, &timer_result, _1)); optional<error_code> port_result; async_read(port, buffers, boost::bind(set_result, &port_result, _1)); io_context.restart(); while (io_context.run_one()) { if (timer_result) port.cancel(); else if (port_result) timer.cancel(); } if (port_result && *port_result) throw system_error(*port_result); } int main(int argc, char *argv[]) { io_context io_context; serial_port port(io_context, "/dev/ttymxc6"); char buf[4096]; try { std::cout << "Read (1) ...\n"; read_with_timeout(io_context, port, buffer(buf)); } catch (const std::exception& e) { std::cerr << "Exception: " << e.what() << '\n'; } try { std::cout << "Read (2) ...\n"; read_with_timeout(io_context, port, buffer(buf)); } catch (const std::exception& e) { std::cerr << "Exception: " << e.what() << '\n'; } } |