Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak in uORB teardown #12537

Open
jkflying opened this issue Jul 22, 2019 · 6 comments
Open

Memory leak in uORB teardown #12537

jkflying opened this issue Jul 22, 2019 · 6 comments

Comments

@jkflying
Copy link
Contributor

Describe the bug
In the uORBDeviceMaster memory is allocated for the device path and handed to the node, but the node doesn't take ownership of said memory.

Allocated, and if all is successful handed to DeviceNode:
https://github.com/PX4/Firmware/blob/e23e3d7baed6871841911a3aa19812ddb1547b6b/src/modules/uORB/uORBDeviceMaster.cpp#L99

DeviceNode gives it to CDev:
https://github.com/PX4/Firmware/blob/e23e3d7baed6871841911a3aa19812ddb1547b6b/src/modules/uORB/uORBDeviceNode.cpp#L60

which won''t delete it on destruction
https://github.com/PX4/Firmware/blob/e23e3d7baed6871841911a3aa19812ddb1547b6b/src/lib/cdev/CDev.cpp#L62

This isn't an issue on the FCU in real flights, but I'm trying to set up valgrind to find problems in tests, and this is one of them that shows up. It also prevents tearing down and setting up the uORB framework in between unit tests, each test will need to be run in its own process.

@bkueng
Copy link
Member

bkueng commented Jul 23, 2019

We can delete it in DeviceNode's destructor, we just need to make sure CDev::~CDev() doesn't access it anymore.

Generally with uORB tear-down we need to ensure that no other thread is running anymore that potentially calls an uORB API.

@jkflying
Copy link
Contributor Author

I tried this patch, but then sitl-uorb test started failing with a "double free or corruption":

diff --cc src/modules/uORB/uORBDeviceNode.cpp
index d6aad04,d6aad04..d047ce9
--- a/src/modules/uORB/uORBDeviceNode.cpp
+++ b/src/modules/uORB/uORBDeviceNode.cpp
@@@ -61,7 -61,7 +61,8 @@@ uORB::DeviceNode::DeviceNode(const stru
        _meta(meta),
        _instance(instance),
        _priority(priority),
--      _queue_size(queue_size)
++      _queue_size(queue_size),
++      _devname(path)
  {
  }

@@@ -70,6 -70,6 +71,11 @@@ uORB::DeviceNode::~DeviceNode(
        if (_data != nullptr) {
                delete[] _data;
        }
++
++      if (_devname != nullptr) {
++              free((void *)_devname);
++              _devname = nullptr;
++      }
  }

  int
diff --cc src/modules/uORB/uORBDeviceNode.hpp
index ef0a7b0,ef0a7b0..228bcd4
--- a/src/modules/uORB/uORBDeviceNode.hpp
+++ b/src/modules/uORB/uORBDeviceNode.hpp
@@@ -56,7 -56,7 +56,7 @@@ class uORB::DeviceNode : public cdev::C
  public:
        DeviceNode(const struct orb_metadata *meta, const uint8_t instance, const char *path, uint8_t priority,
                   uint8_t queue_size = 1);
--      ~DeviceNode();
++      virtual ~DeviceNode();

        // no copy, assignment, move, move assignment
        DeviceNode(const DeviceNode &) = delete;
@@@ -281,6 -281,6 +281,7 @@@ private
        bool _published{false};  /**< has ever data been published */
        uint8_t _queue_size; /**< maximum number of elements in the queue */
        int8_t _subscriber_count{0};
++      const char *_devname; /**< keep this to delete at teardown, since CDev doesn't */

        px4_task_t _publisher{0}; /**< if nonzero, current publisher. Only used inside the advertise call.
                                                We allow one publisher to have an open file descriptor at the same time. *

So clearly there's more to this story. Maybe in the tests we're passing in literals somewhere?

@bkueng
Copy link
Member

bkueng commented Jul 23, 2019

Did you see https://github.com/PX4/Firmware/blob/e23e3d7baed6871841911a3aa19812ddb1547b6b/src/modules/uORB/uORBDeviceMaster.cpp#L137?

@jkflying
Copy link
Contributor Author

Did you see

Awesome, that fixes it 👍 Dunno how I missed that...

I'll add the fix to #12521

@dagar
Copy link
Member

dagar commented Jul 25, 2019

Each device node knows enough to construct the path on demand. We might be able to structure this to ditch the dynamic allocation entirely.

@stale
Copy link

stale bot commented Oct 23, 2019

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.

@stale stale bot added the stale label Oct 23, 2019
@stale stale bot removed the stale label Mar 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants