# IODevice ownership and destruction

**URL:** <https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688>\
**Category:** Support\
**Created:** [July 27, 2010, 7:57pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688 "2010-07-27T19:57:46Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 27, 2010, 7:57pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/1 "2010-07-27T19:57:46Z")

</div>

We’re having a problem with our LabJack driver not letting go of the USB port when an experiment is unloaded after being run.

If you load the experiment, then _don’t_ run it, then unload it, the destructor is called as expected (although the call stack reveals it is being called when an IODeviceVariableNotification is being destroyed, which is not what I would expect.)

If you load the experiment, then run it, then stop it, then unload the experiment, the destructor is _not_ being called. As a result the cleanup is not happening and the USB port is not being released. If we then load the experiment, the load fails, because the driver can’t acquire the USB port.

It’s not clear why the destructor isn’t being called after a run, but I suspect a shared\_ptr is involved, keeping it alive. Some of the shared\_ptrs in the API, such as the one held by IODeviceVariableNotification, probably ought to be weak\_ptrs because they don’t really ‘own’ the device, and ownership should be limited to the IODeviceManager.

Any suggestions on tracking down the ownership issue, or otherwise making sure the device is destroyed and cleaned up when we want it to be?

Thx,

Jon

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 4:59pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/2 "2010-07-28T16:59:57Z")

</div>

Hi Jon,

I’ve reproduced the problem (using a FakeMonkey instance as the I/O device, so it’s not specific to your plugin). You’re probably right that there’s a shared\_ptr hanging around somewhere. I’ll dig around some more and see if I can figure out what’s happening.

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 5:34pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/3 "2010-07-28T17:34:00Z")

</div>

Hi Jon,

Quick question: Does your device class derive from IODevice or LegacyIODevice?

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 6:05pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/4 "2010-07-28T18:05:05Z")

</div>

IODevice. It was written for 0.4.3.

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 7:00pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/5 "2010-07-28T19:00:09Z")

</div>

> using a FakeMonkey instance as the I/O device, so it’s not specific to your plugin

I take that back. Although I did get the same symptoms with both FakeMonkey and MSSWGamepad, it turns out that the plugins themselves were at fault.

Both plugins were creating ScheduleTask instances, which they held onto via shared\_ptr’s but failed to release in stopDeviceIO. Since the ScheduleTask instances hold a shared\_ptr to the IODevice, this left a reference cycle in place after the experiment was run and closed, meaning neither object was destroyed.

I resolved the problem by adding a bit of code like the following to stopDeviceIO:

```
if (schedule_node) {
    schedule_node->cancel();
    schedule_node.reset(); // Release the reference
}

```

Maybe your plugin needs a similar fix?

> IODevice. It was written for 0.4.3.

OK. Although you shouldn’t need to, if you _do_ end up subclassing LegacyIODevice, be sure that LegacyIODevice::stopAllScheduleNodes gets called in your stopDeviceIO. (One option is just to call LegacyIODevice::stopDeviceIO for your subclass’s stopDeviceIO.)

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 7:11pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/6 "2010-07-28T19:11:24Z")

</div>

Thanks! I’ll check what we’re doing.

- Jon

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 7:20pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/7 "2010-07-28T19:20:37Z")

</div>

We have:

if (pollScheduleNode != NULL) {  
boost::mutex::scoped\_lock(pollScheduleNodeLock);  
pollScheduleNode-\>cancel();  
}

We have another scheduleNode that we use, for a non-repeating timed function invocation to turn off the reward. That one is only canceled in the destructor.

However, I’m seeing the problem even if I comment out the code blocks where the scheduleNodes are created and bound.

- Jon

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 28, 2010, 7:59pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/8 "2010-07-28T19:59:36Z")

</div>

In addition to cancel(), you need to call reset():

```
pollScheduleNode->cancel(); 
pollScheduleNode.reset();

```

Otherwise, you keep a reference to the ScheduleTask instance, and it can’t be deallocated.

> However, I’m seeing the problem even if I comment out the code blocks where the scheduleNodes are created and bound.

OK, but I still suspect the problem is in your code. If you send me a URL, I’ll take a look and see if I can spot any issues.

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 29, 2010, 11:16pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/9 "2010-07-29T23:16:42Z")

</div>

Hm. I’m not getting anywhere with this. And I noticed no use of reset() on shared\_ptrs in other devices.

I’ve committed some changes.

The repository is:  
[git@github.com](mailto:git@github.com):jonhendry/MWorks.git

The branch is wip/labjack

The commit id is 937bc6a417533078d3c6

(Not sure if there’s a better way of getting a URL you can use from github.)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 30, 2010, 6:52pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/10 "2010-07-30T18:52:32Z")

</div>

> (Not sure if there’s a better way of getting a URL you can use from github.)

This works:

[http://github.com/jonhendry/MWorks/tree/937bc6a417533078d3c6](http://github.com/jonhendry/MWorks/tree/937bc6a417533078d3c6)

> And I noticed no use of reset() on shared\_ptrs in other devices.

Normally, you don’t need it. But you do need it in the situation I described, where there’s a reference cycle between the IODevice and a ScheduleTask (because each holds a shared\_ptr to the other).

In your code, the only place you would need it is in LabJackU6Device::stopDeviceIO, where you cancel pollScheduleNode (and probably should cancel pulseScheduleNode, too). I say “would” because you’ve presumably eliminated the reference cycle by passing weak\_ptr’s to boost::bind when creating the schedule nodes.

As it is, I don’t see any obvious reference cycles or leaks in your code. However, I also don’t think the problem you’re experiencing applies to IO devices in general, since (after making the bug fixes I described previously) the destructors for FakeMonkey and MSSWGamepad are being called consistently. At least, that’s true with the latest HEAD code. If you’re still using your own fork of “0.4.3”, then there may be other issues that you have and I don’t.

As a workaround, you could make the USB port handle a static class member, so that it’s shared by all instances. That way, if one instance fails to release it, the next one can take over ownership. (This assumes that you only have one physical device.)

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 30, 2010, 8:15pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/11 "2010-07-30T20:15:00Z")

</div>

Thanks, Chris.

Perhaps the thing to do is try it on 0.4.4, and if that doesn’t help, go to the static member.

- Jon

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [April 8, 2011, 3:20pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/12 "2011-04-08T15:20:12Z")

</div>

I believe this issue was resolved a while back. (See [this dicussion](https://mworks.discourse.group/discussions/problems/23) and the accompanying [bug fix](https://github.com/mworks-project/mw_core/commit/7f2decccbbb7164239d3b42c60b9f1444bcdc782)). If you run into it again, please let us know.

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [July 19, 2022, 11:50pm UTC](https://mworks.discourse.group/t/iodevice-ownership-and-destruction/688/13 "2022-07-19T23:50:01Z")

</div>


