summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2011-02-22 10:27:40 +0100
committerMurray Cumming <murrayc@murrayc.com>2011-02-22 11:04:03 +0100
commit18d3559c84c27549b312e2100d9918ec540bda2b (patch)
tree3de820ecdb27232e012444b8622f17a5458ce8b5
parentfaabe1f90c142a5ea836884a04c0eef250e69f94 (diff)
downloadsigc++-18d3559c84c27549b312e2100d9918ec540bda2b.tar.gz
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.
-rw-r--r--ChangeLog8
-rw-r--r--sigc++/trackable.cc19
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 */