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

fix for waitset api change #7

Merged
merged 2 commits into from
Jan 13, 2016
Merged

fix for waitset api change #7

merged 2 commits into from
Jan 13, 2016

Conversation

jacquelinekay
Copy link
Contributor

Connects to ros2/rmw#49

@jacquelinekay jacquelinekay added the in progress Actively being worked on (Kanban column) label Dec 18, 2015
@wjwwood
Copy link
Member

wjwwood commented Dec 18, 2015

It doesn't look like you ever destroy the waitset?

@@ -111,6 +112,9 @@ rcl_wait_set_init(
wait_set->impl->rmw_subscriptions.subscriber_count = 0;
wait_set->impl->rmw_guard_conditions.guard_conditions = NULL;
wait_set->impl->rmw_guard_conditions.guard_condition_count = 0;
wait_set->impl->rmw_waitset = rmw_create_waitset(
NULL, 2*number_of_subscriptions + number_of_guard_conditions);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should check to make sure this function succeeded, and if it doesn't you should goto fail and make sure it is cleaned up in __wait_set_clean_up.

@wjwwood
Copy link
Member

wjwwood commented Dec 18, 2015

C is like crawling on your hands and knees. I'd recommend putting the wait set clean up in __wait_set_clean_up that way it is cleanup on failure in the init function as well as in the fini function.

@jacquelinekay
Copy link
Contributor Author

Yeah man. Life is hard. c50ab45

@@ -77,6 +78,7 @@ __wait_set_clean_up(rcl_wait_set_t * wait_set, rcl_allocator_t allocator)
assert(ret == RCL_RET_OK); // Defensive, shouldn't fail with size 0.
}
if (wait_set->impl) {
assert(rmw_destroy_waitset(wait_set->impl->rmw_waitset) == RMW_RET_OK);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be guarded by a if (wait_set->impl->rmw_waitset) {...} because it is possible for allocation of wait_set->impl to be successful, but wait_set->impl->rmw_waitset is still NULL or does not point to allocated memory.

@wjwwood
Copy link
Member

wjwwood commented Dec 18, 2015

+1

@@ -79,6 +80,9 @@ __wait_set_clean_up(rcl_wait_set_t * wait_set, rcl_allocator_t allocator)
assert(ret == RCL_RET_OK); // Defensive, shouldn't fail with size 0.
}
if (wait_set->impl) {
if (wait_set->impl->rmw_waitset) {
assert(rmw_destroy_waitset(wait_set->impl->rmw_waitset) == RMW_RET_OK);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be checked in release builds too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following the pattern of the above code here. Since this function signature has no way of returning an error code, I'm not sure how to propagate the error to the highest level. @wjwwood any thoughts on how these functions should report errors in release builds?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I had to do some research first. This is definitely a bug and needs to be fixed through out. I'm in the process of auditing rcl for this problem.

In the example above rmw_destroy_waitset(...) is never run if -DNDEBUG is passed to the compiler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As to whether or not the check should be made, it is a situation where the it should never fail, but because it could in other scenarios there is a warning when you don't check the return value. This check is really defensive and should never be false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't see any other problematic uses of asserts (where needed code is avoided with NDEBUG) right now.

Perhaps we need a custom assert (it's a fairly common thing in projects) which is always checked. I think there's a need for "I want to make a defensive check that should never be false, and if it is it is not recoverable" but that is not disabled when -DNDEBUG is used. The consensus on the internet is that you can easily make one with printf and abort which are portable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think checking it in debug only is ok (that was the idea with the assert anyways), but then it results in a unused variable warnings which requires us to but in that obnoxious other "no lint" line. I'm not sure whether or not the performance difference is appreciable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing I'll mention here is that the other functions are implemented in this file and I can ensure they shouldn't fail in that scenario fairly easily. But the same might not be so easy to say of the rmw_destroy_waitset function since it is presumably implemented by each middleware implementation and might fail in some scenario. In which an assert might not be the right action to take here. But I think it's ok to handle that when it comes up and leave the assert for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the existing implementations of rmw_destroy_waitset do return an error code in certain situations I think the return value should definitely be checked here (meaning also in release). Otherwise the rmw impl. might detect a problem but it stays unnoticed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good point that rmw_destroy_waitset isn't implemented in this file, unlike the other functions.

Should I change the signature of this function to return an error code to propagate it to the user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided the minimal viable solution here is to mirror what's in publisher.c and move the rmw_destroy_waitset call to wait_set_fini, which already has the right function signature to propagate an error code.

jacquelinekay added a commit that referenced this pull request Jan 13, 2016
fix for waitset api change
@jacquelinekay jacquelinekay merged commit 18c3cd6 into master Jan 13, 2016
@jacquelinekay jacquelinekay deleted the waitset_handle branch January 13, 2016 01:48
@jacquelinekay jacquelinekay removed the in progress Actively being worked on (Kanban column) label Jan 13, 2016
BorjaOuterelo referenced this pull request in micro-ROS/rcl Nov 5, 2018
ivanpauno pushed a commit that referenced this pull request Jan 2, 2020
Add allocators for clients and services
mauropasse pushed a commit to mauropasse/rcl that referenced this pull request Dec 1, 2020
Rename set_events_executor_callback->set_listener_callback
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants