BIND 10 #296: Timeouts on msgq's cc-channel

BIND 10 Development do-not-reply at isc.org
Mon Aug 16 18:29:51 UTC 2010


#296: Timeouts on msgq's cc-channel
-------------------------------+--------------------------------------------
      Reporter:  jelte         |        Owner:  jelte               
          Type:  enhancement   |       Status:  reviewing           
      Priority:  major         |    Milestone:  y2 6 month milestone
     Component:  Unclassified  |   Resolution:                      
      Keywords:                |    Sensitive:  0                   
Estimatedhours:  0.0           |        Hours:  0                   
      Billable:  1             |   Totalhours:  0                   
      Internal:  0             |  
-------------------------------+--------------------------------------------
Changes (by jinmei):

  * owner:  jinmei => jelte


Comment:

 Replying to [comment:15 jelte]:

 > >  - is it okay to do io_service().reset()?  According to the ASIO
 reference "this function must not be called while there are any unfinished
 calls".  I'm afraid we cannot assume such a thing in general.
 >
 > thing is, we can't assume we don't need it either; if io_service has
 decided it ran out of work, it'll stop doing anything on run_one(), and
 our while loop will run forever (this happens in one of the test cases
 here). The documentation also says that you need to call it before any
 second or later set of calls to run() or run_one().
 >
 Hmm, I see, but I'm afraid reset() can acutally "be called while there are
 unfinished calls to run()" in practice.  In fact, if I understand the code
 correctly, almost all calls to SessionImpl::readData() are performed
 inside a main io_service loop (i.e run()) in case of b10-auth (exceptions
 are the very first ones to establish sessions before starting a mail
 loop).

 From a quick look at the implementation of reset() (which I think is in
 asio/detail/xxx_io_service.hpp), reset() actually doesn't trigger an
 exception or otherwise indicate an error even if the assumption isn't met.
 But I'm not so sure if this means this usage is actually safe or it
 actually breaks something fundamental inside io_serivce which could cause
 strange failures in rare cases.

 One possible workaround would be
  - to set session timeout to 0 (meaning no timeout) in b10-auth just
 before starting the main loop, and
  - in readData(), skip the reset()->run_one() trick completely, if
 getTimeout() == 0

 And we should eventually integrate it to the asio wrapper so that we can
 handle this in the same io_service().run context or make everything
 asynchronous.

 > >  - I don't understand why we need to check getTimeout() != 0 here:
 > > {{{
 > >             if (read_result && getTimeout() != 0) {
 > > }}}
 >
 > If timeout is set to 0, the timer isn't started, and waiting for it to
 end would result in an eternal loop (after data has arrived). Added
 comment.
 >
 Hmm, but doesn't timer.cancel() triggers the setResult() event for the
 timer?  Perhaps it's not the case when the timer hasn't started in the
 first place?

 > >  - The following line isn't necessarily incorrect but looks a bit
 awkward:
 > > {{{
 > >         if (read_result->value() != 0) {
 > > }}}
 > >   why not this?  This seems to be more consistent with the other usage
 of asio::error_code in this code:
 > > {{{
 > >         if (*read_result) {
 > > }}}
 >
 > Personal preference; I don't have a strong opinion, but it is more clear
 to me as a reader what we are checking for here (success result). Unless
 i'm wrong in reading the code, there's no asio::error_code::success or
 something similar, so this would have to do. If you think *read_result
 directly is more clear, we can change it.
 >
 To me, the problem of this code is that it implicitly assumes the
 relationship between the low level value() and the abstract level of
 asio::error_code, that is, it assumes if value() is non 0 it means an
 error (not a success).

 This is true in the current implementation, and it's quite unlikely to
 change in future versions, but it's not guaranteed (the reference only
 says value() returns "the error value").  What if, again unlikely, a
 future version of ASIO introduces a new "success" error_category to
 separate different types of successful results?  In that case value()
 would return non 0 values while it can still indicate a success via
 operator! or the type conversion operator.

 I'm not sure if I fully understand "there's no asio::error_code::success
 or something similar", but if what you mean is a way to know if a
 particular error_code indicates a success or failure, you can use
 operator! or the type conversion operator (to bool), and the reference
 explicitly says so (unlike the semantics of value()):

  - operator unspecified_bool_type: Operator returns non-null if there is a
 non-success error code.
  - operator!: Operator to test if the error represents success.

 In fact, this code explicitly tests if there's a non-success error code
 using "operator unspecified_bool_type":

 {{{
         if (*read_result) {
 }}}

 Having said that, these are relatively pedantic argument, and it's not or
 probably won't be different from the current code usig value() in
 practice.  So, if this is not convincing and you still think value() is a
 more intuitive representation, please move forward with it.  (but please
 make a comment that the code assumes the implicit relationship between the
 raw value() and the success/failure semantics).

-- 
Ticket URL: <http://bind10.isc.org/ticket/296#comment:16>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list