Boost logo

Boost Users :

Subject: Re: [Boost-users] asio: cancelling a named pipe client
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2018-01-31 07:14:28


On 31/01/2018 20:00, Stian Zeljko Vrba wrote:
> And this what the C++11 HTTP server example does to abort a read/write
> loop for the client:
>
> void connection::stop()
> {
>   socket_.close();
> }
>
>
> Exactly what I wanted to avoid. Why?
>
> The mundane reason is that I want to have clean event logs. This is how
> the example(s) you're referring to "handle" errors (an excerpt):
>
> ...
> else if (ec != boost::asio::error::operation_aborted)
>         {
>           connection_manager_.stop(shared_from_this());
>         }
> ...
>
> The principled reason ist that I'd like that error code != 0 really
> means that a hard error happened, instead of "maybe error, maybe my
> program wants to abort the handler loop". With the example "solution"
> I'd be de-facto repurposing errc::invalid_handle (or whatever it's
> called) to mean the same as errc::operation_aborted, which  I don't like
> at all. If I have to explain why: because I want all the help I can get
> from the  OS to diagnose my own mess-ups.

If you close the socket while an operation is pending, it will trigger
operation_aborted, which should not be logged (as this is an "expected"
error). It will also *not start another operation* (for any error).

So you will never see an invalid_handle error as a result of that as
long as some operation is pending at all times. Thus invalid_handle is
always an actual error.

What about the case when a read has completed? This is not a problem as
long as you make sure that you post the (method that calls) close() to
the io_service, ensuring that it is on the same strand as the read (or
any other operations) -- which is automatic if you only have one worker
thread.

Why? Because the completion handler of the read operation will always
start another read operation if it succeeds, and never do so if it
fails. And posted tasks are always executed in the order posted (when
there is one worker thread, or they are posted through the same strand).

So either the read is pending, and the close/cancel will abort it and
give you an operation_aborted; or the read is completed, and the read's
completion handler will execute and start a new read before the
close/cancel can execute.

What you *don't* want to do is to execute the close/cancel in some other
context, as then you'll get weirder behaviour without some other
mechanism (such as an extra flag) to track that you're trying to shut down.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net