commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 01/01: gnuradio-runtime: Fix sptr magic whe


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/01: gnuradio-runtime: Fix sptr magic when exception thrown in hier2 constructor
Date: Wed, 27 Jan 2016 22:24:41 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch maint
in repository gnuradio.

commit 11973c64437683cc99c48eae9eb4db8234f1ac42
Author: Sylvain Munaut <address@hidden>
Date:   Wed Jan 27 11:24:19 2016 +0100

    gnuradio-runtime: Fix sptr magic when exception thrown in hier2 constructor
    
    Fixes #528
    
    Previously, if an exception is thrown in constructor of a hier_block2
    subclass, then :
     - The hier_block2 base destructor _will_ be called
     - The actual object is destroyed
     - But the initial sptr would be left in the static map and point to
       an invalid object
     - Whatever connection() were made might have an invalid sptr ref as well
    
    So to fix this:
     - In the hier_block2 destructor, we explicitely disconnect() everything
     - In the base hier_block2 destructor, we call a new 'cancel sptr' method
       that will check if this object is still in the static map or not
       - If it's not: Then this is a legit call to the destructor by shared_ptr
         and everything is fine
       - If it's: Then there was an isue and the object is already being
         destroyed and we need to make sure shared_ptr doesn't try to do it
         again. We do this using a special 'disarmable' custom deleter.
    
    Signed-off-by: Sylvain Munaut <address@hidden>
---
 gnuradio-runtime/include/gnuradio/sptr_magic.h |  1 +
 gnuradio-runtime/lib/hier_block2.cc            |  2 ++
 gnuradio-runtime/lib/sptr_magic.cc             | 35 +++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/gnuradio-runtime/include/gnuradio/sptr_magic.h 
b/gnuradio-runtime/include/gnuradio/sptr_magic.h
index 898edc8..6deb306 100644
--- a/gnuradio-runtime/include/gnuradio/sptr_magic.h
+++ b/gnuradio-runtime/include/gnuradio/sptr_magic.h
@@ -38,6 +38,7 @@ namespace gnuradio {
     public:
       static boost::shared_ptr<gr::basic_block> 
fetch_initial_sptr(gr::basic_block *p);
       static void create_and_stash_initial_sptr(gr::hier_block2 *p);
+      static void cancel_initial_sptr(gr::hier_block2 *p);
     };
   };
 
diff --git a/gnuradio-runtime/lib/hier_block2.cc 
b/gnuradio-runtime/lib/hier_block2.cc
index eeb5669..597ae03 100644
--- a/gnuradio-runtime/lib/hier_block2.cc
+++ b/gnuradio-runtime/lib/hier_block2.cc
@@ -57,6 +57,8 @@ namespace gr {
 
   hier_block2::~hier_block2()
   {
+    disconnect_all();
+    gnuradio::detail::sptr_magic::cancel_initial_sptr(this);
     delete d_detail;
   }
 
diff --git a/gnuradio-runtime/lib/sptr_magic.cc 
b/gnuradio-runtime/lib/sptr_magic.cc
index 70596ab..e5e8372 100644
--- a/gnuradio-runtime/lib/sptr_magic.cc
+++ b/gnuradio-runtime/lib/sptr_magic.cc
@@ -36,14 +36,47 @@ namespace gnuradio {
   typedef std::map<gr::basic_block*, gr::basic_block_sptr> sptr_map;
   static sptr_map s_map;
 
+  struct disarmable_deleter
+  {
+    bool armed;
+
+    disarmable_deleter()
+    {
+      armed = true;
+    }
+
+    void operator()(void *p) const
+    {
+      if (armed)
+        delete static_cast<gr::basic_block *>(p);
+    }
+
+    void disarm()
+    {
+      armed = false;
+    }
+  };
+
   void
   detail::sptr_magic::create_and_stash_initial_sptr(gr::hier_block2 *p)
   {
-    gr::basic_block_sptr sptr(p);
+    gr::basic_block_sptr sptr(p, disarmable_deleter());
     gr::thread::scoped_lock guard(s_mutex);
     s_map.insert(sptr_map::value_type(static_cast<gr::basic_block *>(p), 
sptr));
   }
 
+  void
+  detail::sptr_magic::cancel_initial_sptr(gr::hier_block2 *p)
+  {
+    gr::thread::scoped_lock guard(s_mutex);
+    sptr_map::iterator pos = s_map.find(static_cast<gr::basic_block *>(p));
+    if(pos == s_map.end())
+      return; /* Not in the map, nothing to do */
+    gr::basic_block_sptr sptr = pos->second;
+    s_map.erase(pos);
+    boost::get_deleter<disarmable_deleter, gr::basic_block>(sptr)->disarm();
+  }
+
   gr::basic_block_sptr
   detail::sptr_magic::fetch_initial_sptr(gr::basic_block *p)
   {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]