0

I'm noticing that in many of the Boost ASIO examples, calls are being made to functions which can throw on error, but no try/catch is used. For example, the blocking UDP client example here has the following function:

  void check_deadline()
  {
    // Check whether the deadline has passed. We compare the deadline against
    // the current time since a new asynchronous operation may have moved the
    // deadline before this actor had a chance to run.
    if (deadline_.expires_at() <= deadline_timer::traits_type::now())
    {
      // The deadline has passed. The outstanding asynchronous operation needs
      // to be cancelled so that the blocked receive() function will return.
      //
      // Please note that cancel() has portability issues on some versions of
      // Microsoft Windows, and it may be necessary to use close() instead.
      // Consult the documentation for cancel() for further information.
      socket_.cancel();

      // There is no longer an active deadline. The expiry is set to positive
      // infinity so that the actor takes no action until a new deadline is set.
      deadline_.expires_at(boost::posix_time::pos_infin);
    }

    // Put the actor back to sleep.
    deadline_.async_wait(boost::bind(&client::check_deadline, this));
  }

The documention for deadline_.expires_at (here) states that this function throws a boost::system::system_error exception.

Is this not caught in this example because it is simply an example, or do exceptions thrown from calls like this propagate up through a call to run, run-one, etc? In other words, is it sufficient to wrap the call to io_service.run() with a try catch to handle these types of exceptions?

Further, I also noticed that the deadline_.async_wait documentation here states that the handler requires a signature with a reference to a boost::system::system_error::error_code. I'm not seeing a reference or a placeholder in the check_deadline() function.

pertre
  • 266
  • 1
  • 6
  • @sehe - Thanks for the link to the other question, but I'm still not making the connection. Perhaps to clarify - I understand according to the ASIO documentation that exceptions from handlers are allowed to propagate through the io_service.run call. It would seem to me that the boost bound check_deadline passed into async_wait is a handler, but is the "deadline_.expires_at" call also considered a handler in this case? Further, I still don't know why the check_deadline function doesn't supply a boost error code reference. – pertre Nov 04 '16 at 20:22
  • 2
    The largest problem I see is that you asked multiple questions; it's hard to give targeted, reusable answers - that will help many people - that way. `expires_at` is obviously just a function call, but it happens in the course of your handler (`check_deadline`). – sehe Nov 04 '16 at 23:23

1 Answers1

2

basic_deadline_timer::async_wait documentation states:

Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io_service::post().

This means that the handler will be called from the inside io_service::run() (in the thread that called it), so exception will be automatically propagated to user code and no special handling is required inside Asio. Usually samples doesn't include error handling for simplicity.

Sorry, I don't know why error_code placeholder is not specified in the sample. Would need to have a look at Asio sources.

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • 4
    To elaborate on the handler, per the [WaitHandler](http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/reference/WaitHandler.html) documentation, if `h` is a handler and `ec` is an lvalue of type `const error_code`, then the expression `h(ec)` must be valid. The functor returned from `bind()` accepts arguments by-value, and will silently ignore extra arguments. Hence, Asio will call the functor with an `error_code`, but the argument will be discarded when invoking the bound function. – Tanner Sansbury Nov 04 '16 at 20:09