boost::asio async handlers invoked without error after cancellation

一个人想着一个人 提交于 2019-12-07 06:09:19

问题


My code uses boost::asio and io_service in a single thread to perform various socket operations. All operations are asynchronous and every handler depends on the boost::system::error_code (particularly boost::asio::error::operation_aborted) to determine the result of the operation.

It's been working perfectly well until I changed the logic to make several concurrent connections and pick the fastest one. That is, when the first async_read_some handler fires, I cancel other sockets (shutdown, close - everything) and proceed with the current one. In 95% of cases other sockets' read handlers are invoked with the operation_aborted error. However sometimes, these read handlers are invoked without errors, telling me that they have successfully received N bytes.

But the documentation for socket::cancel() states:

This function causes all outstanding asynchronous connect, send and receive operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation_aborted error.

So, the questions: Can I really rely on the operation_aborted error in production code? If I can, is it a bug in Asio from boost 1.46.1? If I can't, is there any official documentation regarding this?


回答1:


Ok, the answers:

  1. No, I cannot rely on the operation_aborted error only.
  2. Of course, it's not a bug in Asio, just a lack of experience on my side.
  3. There is a little bit of official documentation. It's for timers, not sockets, however the same principles apply:

If the timer has already expired when cancel() is called, then the handlers for asynchronous wait operations will:

  • have already been invoked; or
  • have been queued for invocation in the near future.

Basically, I was wrong in assumption that if I use a single thread for io_service, then every operation will be blocked while some handler executes.

The behavior I'm reporting actually makes a lot of sense and it seems that everyone who uses Asio knows that. I've combed through Asio's mailing lists and have found a lot of discussion on the subject here, here, here and here.

For instance, a write operation may complete successfully while you are inside a handler but before you have got around to calling socket cancel, causing its completion handler to be posted to the queue. As I understand it, the error code is determined by the status of the operation that completed, not the state of the socket at the time the handler is picked off the queue and executed.




回答2:


Consider two connections establishing at the same time. Both handlers will fire, one will be handled first, second is in the queue (or being handled on a different thread). One can think of more examples like that.

So in order to implement your requirement you need a bit more logic.



来源:https://stackoverflow.com/questions/10718593/boostasio-async-handlers-invoked-without-error-after-cancellation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!