-
Notifications
You must be signed in to change notification settings - Fork 237
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
Make destroy_node
thread safe
#330
Conversation
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
CI (testing all packages above rclpy)
|
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
Signed-off-by: Shane Loretz <[email protected]>
# Assume lock is held | ||
assert not self.__lock.acquire(blocking=False) | ||
# Assume capsule has not been destroyed | ||
assert self.__valid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Destruction can be delayed waiting for dependents. Previously self.__valid = False
meant the capsule itself has been destroyed. Now setting it to false means destroy()
was called and __use_count
hit zero. The purpose is to prevent new users of this handle while waiting for dependent handles to be destroyed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (after convincing myself I understood how the call hierarchy happens)
Signed-off-by: Shane Loretz <[email protected]>
CI (testing rclpy with 8c95ea6) |
Blocks #319
I was going to make this part of #319, but I think it would be easier to review separately. This makes
Node.handle
use theHandle
class from #308. It also addshandle.requires(another_handle)
to make surehandle
is destroyed beforeanother_handle
.Problem this solves
#308 makes
destroy_subscription
thread safe by delaying destruction if the handle is currently being used. This makes it possible for a subscription to be destroyed after the node; which crashes when doing the same strategy with services using fast-rtps. See #319 (comment) for a better explanation.Breaking changes
node.destroy_node()
either returnedTrue
or raised an exception. I removed the return value since it was only everTrue
.node.handle
was set toNone
after the node was destroyed. Now it raisesInvalidHandle
when someone tries to use it after it is destroyed.node.handle
was a pycapsule and could be used directly. Now one must use:How handle.requires() works
Subscriptions must be destroyed before the node that created them, so
When
node.handle.destroy()
is called the subscription handle is destroyed first. Once the node handle is no longer being used it will mark itself invalid so no one else can use it. Then the node handle tells the subscription handle to destroy itself. Once the subscription handle is no longer in use it will delete itself, and then tell the node it can destroy itself.If the user does not call
destroy()
on either handle, the subscription handle holds a reference to the node handle so the subscription handle will be garbage collected first. The node handle only holds a weak reference to the subscription handle.Next steps
After incorporating feedback, assuming this approach is OK I would like to merge this PR. Then I'll rebase #319 to make all the other entities require the
node
so everything can be destroyed safely.