Skip to content

Crash when destroying subscription #896

@csmith-rtr

Description

@csmith-rtr

Description
Presumably this occurs destroying any entity, but rclnodejs may crash if you destroy a subscription. Example below

  • Library Version: 0.21.4
  • ROS Version: foxy
  • Platform / OS: 20.04
    I'm using cyclonedds if that's relevant

Steps To Reproduce

const rclnodejs = require('rclnodejs');

function createSub1(node) {
  return node.createSubscription('std_msgs/msg/String', '/chatter1', msg => {
    console.log(`Chatter1 got: ${msg.data}`);
  });
}

function createSub1And2(node) {
  let sub1 = createSub1(node);

  let sub2 = node.createSubscription(
    'std_msgs/msg/String',
    '/chatter2',
    msg => {
      console.log(`Chatter2 got: ${msg.data}`);
      // process.nextTick(() => {
        // uncommenting the nextTick call (while still destroying/recreating) may change the behavior
        node.destroySubscription(sub1);
        sub1 = createSub1(node);
      // });
    },
  );
}

function spin(node) {
  setInterval(() => {
    node.spinOnce();
  }, 1);
}

async function main() {
  await rclnodejs.init();
  const node = new rclnodejs.Node('test_node');
  // node.spin();  // changing how spin is implemented changes the error
  spin(node);

  createSub1And2(node);

  const pub1 = node.createPublisher('std_msgs/msg/String', '/chatter1');
  const pub2 = node.createPublisher('std_msgs/msg/String', '/chatter2');

  let i = 0;
  setInterval(() => {
    pub1.publish({ data: 'Chatter1 ' + i++ });
    pub2.publish({ data: 'Chatter2 ' + i++ });
  }, 1);
}

main();

Expected Behavior
rclnodejs doesn't crash when destroying entities

Actual Behavior
rclnodejs may crash if entities are destroyed. My guess is that both subscriptions have data available and get marked as such. In the first callback the second subscription is destroyed. The executor then tries to execute the callback for a subscription that no longer exists.

There are a few comments in the code about small tweaks that change the outcome

  1. using node.spin - this always ends in a segfault for me
// ... more message logs above
Chatter2 got: Chatter2 167
Chatter2 got: Chatter2 169
Chatter2 got: Chatter2 171
Segmentation fault (core dumped)
  1. use spin(node) and destroy the subscription without process.nextTick- this almost immediately crashes with this error
Chatter1 got: Chatter1 0
Chatter2 got: Chatter2 1
Chatter2 got: Chatter2 3
rclnodejs/lib/node.js:191
          let success = rclnodejs.rclTake(subscription.handle, message);
                                  ^

Error: subscription pointer is invalid, at /tmp/binarydeb/ros-foxy-rcl-1.1.14/src/rcl/subscription.c:461
    at rclnodejs/lib/node.js:191:35
    at Node._runWithMessageType (rclnodejs/lib/node.js:1627:5)
    at rclnodejs/lib/node.js:188:12
    at Array.forEach (<anonymous>)
    at Node.execute (rclnodejs/lib/node.js:180:24)
    at Node.spinOnce (rclnodejs/lib/node.js:440:11)
  1. use spin(node) and destroy the subscription in process.nextTick - this never crashes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions