From 53d18e6a03a1ebdcd2e2da91a296179c333155fd Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 15 Jun 2020 09:37:11 -0700 Subject: [PATCH] SharedPV handle bad_weak_ptr earlier Avoid operating on partly destroyed object. --- src/server/sharedstate_pv.cpp | 42 +++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/server/sharedstate_pv.cpp b/src/server/sharedstate_pv.cpp index 9151391..4e91aa2 100644 --- a/src/server/sharedstate_pv.cpp +++ b/src/server/sharedstate_pv.cpp @@ -164,16 +164,18 @@ void SharedPV::open(const pvd::PVStructure &value, const epics::pvData::BitSet& FOR_EACH(puts_t::const_iterator, it, end, puts) { if((*it)->channel->dead) continue; + std::tr1::shared_ptr self; try { - try { - (*it)->mapper.compute(*current, *(*it)->pvRequest, config.mapperMode); - p_put.push_back(PutInfo((*it)->shared_from_this(), (*it)->mapper.requested(), (*it)->mapper.warnings())); - }catch(std::runtime_error& e) { - // compute() error - p_put.push_back(PutInfo((*it)->shared_from_this(), pvd::StructureConstPtr(), pvd::Status::error(e.what()))); - } + self = (*it)->shared_from_this(); }catch(std::tr1::bad_weak_ptr&) { - //racing destruction + continue; //racing destruction + } + try { + (*it)->mapper.compute(*current, *(*it)->pvRequest, config.mapperMode); + p_put.push_back(PutInfo(self, (*it)->mapper.requested(), (*it)->mapper.warnings())); + }catch(std::runtime_error& e) { + // compute() error + p_put.push_back(PutInfo(self, pvd::StructureConstPtr(), pvd::Status::error(e.what()))); } } FOR_EACH(rpcs_t::const_iterator, it, end, rpcs) { @@ -184,12 +186,16 @@ void SharedPV::open(const pvd::PVStructure &value, const epics::pvData::BitSet& } FOR_EACH(monitors_t::const_iterator, it, end, monitors) { if((*it)->channel->dead) continue; + std::tr1::shared_ptr self; try { - (*it)->open(newtype); - // post initial update - (*it)->post(*current, valid); - p_monitor.push_back((*it)->shared_from_this()); - }catch(std::tr1::bad_weak_ptr&) {} + self = (*it)->shared_from_this(); + }catch(std::tr1::bad_weak_ptr&) { + continue; //racing destruction + } + (*it)->open(newtype); + // post initial update + (*it)->post(*current, valid); + p_monitor.push_back(self); } // consume getField FOR_EACH(getfields_t::iterator, it, end, getfields) { @@ -344,12 +350,14 @@ void SharedPV::post(const pvd::PVStructure& value, p_monitor.reserve(monitors.size()); // ick, for lack of a list with thread-safe iteration FOR_EACH(monitors_t::const_iterator, it, end, monitors) { - (*it)->post(value, changed); + std::tr1::shared_ptr self; try { - p_monitor.push_back((*it)->shared_from_this()); - }catch(std::tr1::bad_weak_ptr& e){ - // ignore post to dead monitor + self = (*it)->shared_from_this(); + }catch(std::tr1::bad_weak_ptr&) { + continue; //racing destruction } + (*it)->post(value, changed); + p_monitor.push_back(self); } } FOR_EACH(xmonitors_t::iterator, it, end, p_monitor) {