Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to cancel a `boost::asio::read` operation while it's waiting

I am using boost::asio to transfer data to & fro from client to server. I have a reader thread on client side to read data received on the socket on client side. Please note that I am using boost::asio::read on client side & boost::asio::writeon server side. Not using async_read or async_write. Everything works great.

However when I close my application, 2 out 10 times the app does not cleanly tear down or close properly. It gets hung while closing down The issue is the following:

My closing function gets called when destructors get called during my app's close down. Following is the code of the Close function:

socket.cancel();
socket.close();
boost::system::error_code ec;
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);

The problem is that the boost::asio::read call does not return when it does not get any data & keeps waiting on it. This should be fine as long as I can cancel it. I am trying to do a socket.cancel on it to cancel all read operations while exiting. However, it doesn't seems to work. I read in some forums that socket.cancel only cancels async_read operations. Is it so ? Then what is the way to cancel a boost::asio::read` operation when my app needs to exit ?

like image 911
TheWaterProgrammer Avatar asked Jan 06 '17 16:01

TheWaterProgrammer


People also ask

How does boost ASIO work?

At its core, Boost Asio provides a task execution framework that you can use to perform operations of any kind. You create your tasks as function objects and post them to a task queue maintained by Boost Asio. You enlist one or more threads to pick these tasks (function objects) and invoke them.

Does boost ASIO use threads?

If the run() method is called on an object of type boost::asio::io_service, the associated handlers are invoked on the same thread. By using multiple threads, an application can call multiple run() methods simultaneously.


1 Answers

That's the nature of blocking IO.

Indeed socket.cancel() (or even io_service::stop()) will not work on synchronous operations.

The only way to interrupt this is to use socket-level timeouts (but Asio doesn't expose that) or to use asynchronous signals (e.g. pressing Ctrl-C in a terminal sends the child process a SIGINT).

I've previously created a poor-man's wrapper if you insist on running single operations with a timeout:

  • boost::asio + std::future - Access violation after closing socket
like image 79
sehe Avatar answered Sep 26 '22 14:09

sehe