BIND 10 trac957, updated. 8abc6698d085aeb474d705403f7b15c2e3505fc2 [trac957] Fixed the bug that destructIntervalTimer segfaults.

BIND 10 source code commits bind10-changes at lists.isc.org
Mon May 23 07:31:18 UTC 2011


The branch, trac957 has been updated
       via  8abc6698d085aeb474d705403f7b15c2e3505fc2 (commit)
      from  c37ebedf94c5dbbed3c685272a0cdc4bea67fb04 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8abc6698d085aeb474d705403f7b15c2e3505fc2
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date:   Mon May 23 16:29:04 2011 +0900

    [trac957] Fixed the bug that destructIntervalTimer segfaults.
    
      - pass boost::shared_ptr of IntervalTimerImpl wrapped with boost::bind
        as a handler of asio::deadline_timer
      - use boost::shared_ptr to hold pImpl

-----------------------------------------------------------------------

Summary of changes:
 src/lib/asiolink/interval_timer.cc |   41 +++++++++++++++++++++---------------
 src/lib/asiolink/interval_timer.h  |   10 +++-----
 2 files changed, 28 insertions(+), 23 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/asiolink/interval_timer.cc b/src/lib/asiolink/interval_timer.cc
index 0ed06eb..2830a3b 100644
--- a/src/lib/asiolink/interval_timer.cc
+++ b/src/lib/asiolink/interval_timer.cc
@@ -19,6 +19,8 @@
 #include <netinet/in.h>
 
 #include <boost/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <exceptions/exceptions.h>
 
@@ -29,7 +31,11 @@
 namespace isc {
 namespace asiolink {
 
-class IntervalTimerImpl {
+/// This class uses shared_from_this in its methods. It must live inside
+/// a shared_ptr.
+class IntervalTimerImpl :
+    public boost::enable_shared_from_this<IntervalTimerImpl>
+{
 private:
     // prohibit copy
     IntervalTimerImpl(const IntervalTimerImpl& source);
@@ -81,42 +87,43 @@ IntervalTimerImpl::setup(const IntervalTimer::Callback& cbfunc,
     // At this point the timer is not running yet and will not expire.
     // After calling IOService::run(), the timer will expire.
     update();
-    return;
 }
 
 void
 IntervalTimerImpl::update() {
-    if (interval_ == 0) {
-        // timer has been canceled.  Do nothing.
-        return;
-    }
     try {
         // Update expire time to (current time + interval_).
         timer_.expires_from_now(boost::posix_time::millisec(interval_));
+        // Reset timer.
+        timer_.async_wait(boost::bind(&IntervalTimerImpl::callback,
+                                      shared_from_this(),
+                                      asio::placeholders::error));
     } catch (const asio::system_error& e) {
         isc_throw(isc::Unexpected, "Failed to update timer");
+    } catch (const boost::bad_weak_ptr& e) {
+        isc_throw(isc::Unexpected, "Failed to update timer");
     }
-    // Reset timer.
-    timer_.async_wait(boost::bind(&IntervalTimerImpl::callback, this, _1));
 }
 
 void
-IntervalTimerImpl::callback(const asio::error_code& cancelled) {
-    // Do not call cbfunc_ in case the timer was cancelled.
-    // The timer will be canelled in the destructor of asio::deadline_timer.
-    if (!cancelled) {
-        cbfunc_();
+IntervalTimerImpl::callback(const asio::error_code& ec) {
+    if (interval_ == 0 || ec) {
+        // timer has been canceled. Do nothing.
+    } else {
         // Set next expire time.
         update();
+        // Invoke the call back function.
+        cbfunc_();
     }
 }
 
-IntervalTimer::IntervalTimer(IOService& io_service) {
-    impl_ = new IntervalTimerImpl(io_service);
-}
+IntervalTimer::IntervalTimer(IOService& io_service) :
+    impl_(new IntervalTimerImpl(io_service))
+{}
 
 IntervalTimer::~IntervalTimer() {
-    delete impl_;
+    // Cancel the timer to make sure cbfunc_() will not be called any more.
+    cancel();
 }
 
 void
diff --git a/src/lib/asiolink/interval_timer.h b/src/lib/asiolink/interval_timer.h
index 8de16cb..57ec1c3 100644
--- a/src/lib/asiolink/interval_timer.h
+++ b/src/lib/asiolink/interval_timer.h
@@ -16,6 +16,7 @@
 #define __ASIOLINK_INTERVAL_TIMER_H 1
 
 #include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <asiolink/io_service.h>
 
@@ -42,9 +43,6 @@ class IntervalTimerImpl;
 /// The call back function will not be called if the instance of this class is
 /// destroyed before the timer is expired.
 ///
-/// Note: Destruction of an instance of this class while call back is pending
-/// causes throwing an exception from \c IOService.
-///
 /// Sample code:
 /// \code
 ///  void function_to_call_back() {
@@ -100,12 +98,12 @@ public:
     /// \param interval Interval in milliseconds (greater than 0)
     ///
     /// Note: IntervalTimer will not pass \c asio::error_code to
-    /// call back function. In case the timer is cancelled, the function
+    /// call back function. In case the timer is canceled, the function
     /// will not be called.
     ///
     /// \throw isc::InvalidParameter cbfunc is empty
     /// \throw isc::BadValue interval is less than or equal to 0
-    /// \throw isc::Unexpected ASIO library error
+    /// \throw isc::Unexpected internal runtime error
     void setup(const Callback& cbfunc, const long interval);
 
     /// Cancel the timer.
@@ -127,7 +125,7 @@ public:
     long getInterval() const;
 
 private:
-    IntervalTimerImpl* impl_;
+    boost::shared_ptr<IntervalTimerImpl> impl_;
 };
 
 } // namespace asiolink




More information about the bind10-changes mailing list