简体   繁体   中英

How to use a single Boost::asio::io_context for multiple sockets and serial ports

I'm using Boost::Asio to create multiple UDP sockets and serial ports, and I use a single boost::asio::io_context that is shared among all of them (given in the constructor). All devices are configured to run with async reads and writes. Then, I only call io_context.run(); to let it run forever. It works very well most of the time.

However, at some point, for example when a sudden traffic load reaches one socket, my process suddenly jumps to 100% on the CPU and stays at 100% forever, with the global communication dying. When this happens, using perf , I see that the process is stuck 99.99% of the time at the same place, with a stack looking like:

main
asio::detail::scheduler::run
asio::detail::epoll_reactor::descriptor_state::do_complete
asio::descriptor_read_op<asio::mutable_buffers_1, std::_Bind<void
my_serial_port::on_async_data_received <- this is my receiving function for serial ports
...

So it seems that it is stuck processing only one serial port in loop, but nothing else anymore, as if a same event was processed endlessly, while there is still a lot of other data coming in the system.

  • Is there something I'm doing wrong by sharing the io_context ?
  • Is there a way to debug such issues with events with Boost::Asio?

I have seen a similar hang, but where the stack only shows a function called by a timer event instead of the serial port (ie a timer sending a statistics packet at 1 Hz, but taking 100% of the CPU and blocking everything else).

Context: On an embedded system using ROS and Linux, I'm running a process (ROS node) that acts as a communication router. It has 7 inputs/outputs: 2 serial ports (3 Mb/s), 2.network UDP sockets and 3 local UDP sockets (UNIX domain). It also listens to some ROS topics coming from other processes. Packets can be received on all ports and a custom protocol is used to decode the packets, read their destination and send them out further on the given port. Some packets are also generated in the process and sent out on some ports, based on data subscribed through ROS. To keep things simple, to avoid concurrency and because I only have one core available, I try to run this process on a single main thread. To merge ROS and Boost::Asio together in a single thread, I'm using librosasio to forward events from ROS to the asio::io_context .

Thanks !

The BOOST_ENABLE_HANDLER_TRACKING may give you some insight into where the problem lies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM