[libsigc++2] signal_impl::notify(): Don't delete signal_impl during erase()



commit dfa4998657946b3ef6c769f74ceb00748b1049c4
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Fri Jul 25 13:08:45 2014 +0200

    signal_impl::notify(): Don't delete signal_impl during erase()
    
    * sigc++/signal_base.cc: signal_impl::notify() and sweep(): Don't delete
    signal_impl while its slot list is being manipulated. Without this fix,
    tests/test_bind_refptr crashes in MS Visual C++ in debug mode.
    The behaviour without the fix is risky, and shall be avoided. Bug #564005.

 sigc++/signal_base.cc |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)
---
diff --git a/sigc++/signal_base.cc b/sigc++/signal_base.cc
index 2ccb8d0..7033c66 100644
--- a/sigc++/signal_base.cc
+++ b/sigc++/signal_base.cc
@@ -1,4 +1,3 @@
-// -*- c++ -*-
 /*
  * Copyright 2003, The libsigc++ Development Team
  *
@@ -15,7 +14,6 @@
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this library; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
 #include <sigc++/signal_base.h>
 #include <memory> // std::auto_ptr
@@ -123,6 +121,11 @@ signal_impl::iterator_type signal_impl::insert(signal_impl::iterator_type i, con
 
 void signal_impl::sweep()
 {
+  // The deletion of a slot may cause the deletion of a signal_base,
+  // a decrementation of ref_count_, and the deletion of this.
+  // In that case, the deletion of this is deferred to ~signal_exec().
+  signal_exec exec(this);
+
   deferred_ = false;
   iterator_type i = slots_.begin();
   while (i != slots_.end())
@@ -138,7 +141,13 @@ void* signal_impl::notify(void* d)
   std::auto_ptr<self_and_iter> si(static_cast<self_and_iter*>(d));
 
   if (si->self_->exec_count_ == 0)
+  {
+    // The deletion of a slot may cause the deletion of a signal_base,
+    // a decrementation of si->self_->ref_count_, and the deletion of si->self_.
+    // In that case, the deletion of si->self_ is deferred to ~signal_exec().
+    signal_exec exec(si->self_);
     si->self_->slots_.erase(si->iter_);
+  }
   else                           // This is occuring during signal emission or slot erasure.
     si->self_->deferred_ = true; // => sweep() will be called from ~signal_exec() after signal emission.
   return 0;                      // This is safer because we don't have to care about our


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