# Usrp2 dtor can throw!

**URL:** <https://www.ruby-forum.com/t/usrp2-dtor-can-throw/201793>\
**Category:** GNU Radio\
**Created:** [January 14, 2011, 5:39pm UTC](https://www.ruby-forum.com/t/usrp2-dtor-can-throw/201793 "2011-01-14T17:39:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [January 14, 2011, 5:39pm UTC](https://www.ruby-forum.com/t/usrp2-dtor-can-throw/201793/1 "2011-01-14T17:39:43Z")

</div>

Hi all,  
the usrp2 destructor can throw an exeption due the fact that while  
destroying the  
implementation ( usrp2::impl::~impl() ) a stop\_bg() is performed.

The stop\_bg implementation is:

void  
usrp2::impl::stop\_bg()  
{  
d\_bg\_running = false;  
d\_bg\_pending\_cond.notify\_one(); // FIXME: check if needed  
d\_rx\_tg.join\_all();  
}

indeed the boost::thread\_group::join\_all is an interruption point for  
boost thread.  
This can lead to a crash in case an user thread (using boost threads)  
receives an  
interruption while a stack unwinding is already occurring and an usrp2  
is destroyed.

There are two ways to correct the problem:

1. Instanziate a boost::this\_thread::disable\_interruption inside the  
stop\_bg()
2. or do a try{ } catch() { } inside the impl destructor.

This is very dangerous because normaly the user code acquire a usrp  
instance  
with a boost::shared\_ptr, I guess this was done to reliefe the user to  
perform an  
explicit delete, however due this bug the user is forced to do:

usrp2::usrp2::sptr myDevice = usrp2::usrp2::make(“eth1”, “”, 1024\*1024)  
…  
try {  
myDevice.reset();  
}  
catch(…) {  
}

Regards  
Gaetano M.

–

> **[c++ today](http://cpp-today.blogspot.com)**
>
> "Almost" day by day thoughts on code inspected

---

<div class="post-metadata">

**Author:** ![Gaetano\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/45deac/32.png) [@Gaetano\_M](https://www.ruby-forum.com/u/Gaetano_M)\
**Post date:** [January 15, 2011, 8:35pm UTC](https://www.ruby-forum.com/t/usrp2-dtor-can-throw/201793/2 "2011-01-15T20:35:50Z")

</div>

I dont think that this is an issue. Are you actually seeing exceptions  
thrown at deconstruction time?

There is nothing that would cause the dtor to get interrupted AFAIK. The  
only way this would be an issue is when thread “A” calls interrupt() on  
thread “B” when “B” is blocking in the join\_all call within the  
usrp2::impl::~impl(). Which could happen if you had a usrp2::impl sptr  
count reset to 0 at the exit of thread “B”.

On the other hand, its possible for boost::thread\_interruption to be  
thrown in a thread when the scheduler shuts down. This is due to the  
gr-scheduler calling interrupt\_all() on the thread group. If thats the  
case, then the usrp2::impl thread body is probably missing a disable  
interruption or a try/catch. If you are seeing an exception thrown,  
maybe this is the problem?

In any case, putting a boost::this\_thread::disable\_interruption at the  
first line of the dtor wouldnt hurt to do. 🙂

-josh

---

<div class="post-metadata">

**Author:** ![Gaetano\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/45deac/32.png) [@Gaetano\_M](https://www.ruby-forum.com/u/Gaetano_M)\
**Post date:** [January 16, 2011, 12:13am UTC](https://www.ruby-forum.com/t/usrp2-dtor-can-throw/201793/3 "2011-01-16T00:13:59Z")

</div>

On Sat, Jan 15, 2011 at 8:34 PM, Josh B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I dont think that this is an issue. Are you actually seeing exceptions  
> thrown at deconstruction time?

It is a very issue because it was for us and I digged this due to our  
application  
experiencing crash.

> There is nothing that would cause the dtor to get interrupted AFAIK. The  
> only way this would be an issue is when thread “A” calls interrupt() on  
> thread “B” when “B” is blocking in the join\_all call within the  
> usrp2::impl::~impl(). Which could happen if you had a usrp2::impl sptr  
> count reset to 0 at the exit of thread “B”.

Consider this code snipset:

boost:🧵:operator()() {  
usrp2::usrp2::sptr myDevice = usrp2::usrp2::make(…)  
…  
boost:🧵:sleep(…)  
}

if a boost thread running that code gets an interrupt while sleeping, it  
throws an exception (boost::thread\_interrupted) due the fact that sleep  
is an interruption point for boost. At this point the stack unwinding  
starts  
the destruction of the smartpointer myDevice calling then the destructor  
of usrp2::usrp2::impl performing a thread\_group::join\_all (another  
interruption  
point), at this point if the thread gets another interrupt the  
thread\_group::join\_all  
throws another exception while a stack unwinding is already going on =\>  
program aborts.

To rub salt into wound consider that boost (I believe corrected only  
on 1.45) was  
affected by the bug #2330 and thread under some circumstances just  
ignore  
interrupt (even if passing from an interruption point), so some  
application  
(like our one) in order to be sure to not stuck for ever on a join  
after an interrupt  
does instead a timed\_join and reissuing the interrupt in case the join  
times out.

> In any case, putting a boost::this\_thread::disable\_interruption at the  
> first line of the dtor wouldnt hurt to do. 🙂

I would suggest a try catch instead for two reasons, first of all a  
DTOR should not  
throw ever (even next c++ standard has the requirement to check at  
compile time of a  
DTOR can throw) and disable interruption can have as effect a delay in  
the thread  
exiting if the thread\_group::join all inside the usrp2::impl::stop\_bg()  
doesn’t  
terminate quick enough (or may be never).

Regards  
Gaetano M.

–

> **[c++ today](http://cpp-today.blogspot.com)**
>
> "Almost" day by day thoughts on code inspected
