[libsigc++2] trackable: Avoid calling the same callback function twice



commit 18d3559c84c27549b312e2100d9918ec540bda2b
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Tue Feb 22 10:27:40 2011 +0100

    trackable: Avoid calling the same callback function twice
    
    * sigc++/trackable.cc: Invalidate a callback function entry in
    trackable_callback_list::remove_callback() when the list is being cleared.
    Bug 589202.

 ChangeLog           |    8 ++++++++
 sigc++/trackable.cc |   19 ++++++++++++-------
 2 files changed, 20 insertions(+), 7 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 39f7558..ffd0e60 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-02-22  Kjell Ahlstedt  <kjell ahlstedt bredband net>
+
+	trackable: Avoid calling the same callback function twice
+
+	* sigc++/trackable.cc: Invalidate a callback function entry in
+	trackable_callback_list::remove_callback() when the list is being cleared.
+	Bug 589202.
+
 2011-02-04  Kalev Lember  <kalev smartlink ee>
 
 	Fix the build with GCC 4.6
diff --git a/sigc++/trackable.cc b/sigc++/trackable.cc
index a4f1f54..f7e4cb7 100644
--- a/sigc++/trackable.cc
+++ b/sigc++/trackable.cc
@@ -86,7 +86,8 @@ trackable_callback_list::~trackable_callback_list()
   clearing_ = true;
 
   for (callback_list::iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
-    (*i).func_((*i).data_);
+    if ((*i).func_) 
+      (*i).func_((*i).data_);
 }
 
 void trackable_callback_list::add_callback(void* data, func_destroy_notify func)
@@ -102,7 +103,8 @@ void trackable_callback_list::clear()
   clearing_ = true;
 
   for (callback_list::iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
-    (*i).func_((*i).data_);
+    if ((*i).func_) 
+      (*i).func_((*i).data_);
 
   callbacks_.clear();
 
@@ -111,17 +113,20 @@ void trackable_callback_list::clear()
 
 void trackable_callback_list::remove_callback(void* data)
 {
-  if (clearing_) return; // No circular notices
-
   for (callback_list::iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
-    if ((*i).data_ == data)
+    if ((*i).data_ == data && (*i).func_ != 0)
     {
-      callbacks_.erase(i);
+      //Don't remove a list element while the list is being cleared.
+      //It could invalidate the iterator in ~trackable_callback_list() or clear().
+      //But it may be necessary to invalidate the callback. See bug 589202.
+      if (clearing_)
+        (*i).func_ = 0;
+      else
+        callbacks_.erase(i);
       return;
     }
 }
 
 } /* namespace internal */
 
-
 } /* namespace sigc */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]