[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)
{