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

Dynamic Subscription (BONUS: Allocators): rosidl #737

Merged
merged 4 commits into from
Apr 11, 2023

Conversation

methylDragon
Copy link
Contributor

Signed-off-by: methylDragon <methylDragon@gmail.com>
@methylDragon methylDragon reopened this Apr 9, 2023
Signed-off-by: methylDragon <methylDragon@gmail.com>
Copy link
Member

@wjwwood wjwwood left a comment

Choose a reason for hiding this comment

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

one comment, otherwise lgtm

ret = rcutils_hash_map_fini(hash_map);
if (ret != RCUTILS_RET_OK) {
RCUTILS_SET_ERROR_MSG("Could not finalize hash map");
return ret;
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear to me if you should deallocate the hash_map in this case. I think you might need to. Otherwise it's a guaranteed memory leak, because you didn't deallocate it, but it also is no longer accessible after this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, in this case it isn't used anywhere else, so I think it's okay?

I did this because valgrind was complaining

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we're not talking about the same thing. Do you mean that if you deallocate hash_map here (before return ret;) that valgrind was complaining?

Copy link
Contributor Author

@methylDragon methylDragon Apr 10, 2023

Choose a reason for hiding this comment

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

Ah, I meant that I added the deallocation because valgrind was complaining about the leak

The hash map isn't accessible from outside the function, and deallocating it doesn't cause what it points to to get deallocated, so I don't think there are any issues

Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I can tell, this is a correct bugfix. That is, rosidl_runtime_c_type_description_utils_get_field_map allocates and adds values to a hash_map, which is the responsibility of the caller to free. Further, the hash map stores a key -> value mapping of char * -> rosidl_runtime_c__type_description__Field *. That is, we are only getting the pointers to the underlying data, not the underlying data itself. Thus, it is entirely appropriate for this function to initialize a hash_map to NULL, have that allocated and filled in by rosidl_runtime_c_type_description_utils_get_field_map, use that data, and then free it.

That said, this is buggy. If we end up at line 693, then we'll skip cleaning up the hash_map. I'll suggest moving this above the if (description->fields.size != map_length) { block, since we already got the data we need from the hash_map.

Finally, this actually seems like a very expensive way to get the number of unique items in the type description field. It would be far more efficient to have a rosidl_runtime_c_type_description_utils_get_size which iterates over the individual descriptions and just returns a count. @methylDragon you don't need to fix this now, but it would be good to open up an issue for follow-up which includes comments like this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, you know, never mind my comment about this being buggy; the end case was actually handling this. Still, I think if we move this block up above, we can avoid having this in two places.

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'll put opening up a followup issue on my docket for now!

Copy link
Contributor Author

@methylDragon methylDragon Apr 10, 2023

Choose a reason for hiding this comment

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

Regarding rosidl_runtime_c_type_description_utils_get_size, we would still need to check for duplicate individual descriptions, which I think would end up needing a hash set, or a growing list of individual description names that we check against as we're building the count (or we sort it and check for neighbouring duplicates?)

I ended up going with the hash set method (with the hash map construction), but yes we can defer this

Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is still open about getting rid of the duplicate rcutils_hash_map_fini. But it is correct right now, it is just code that is unnecessary. So we can defer that to a follow-up as well.

Signed-off-by: methylDragon <methylDragon@gmail.com>
ret = rcutils_hash_map_fini(hash_map);
if (ret != RCUTILS_RET_OK) {
RCUTILS_SET_ERROR_MSG("Could not finalize hash map");
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I can tell, this is a correct bugfix. That is, rosidl_runtime_c_type_description_utils_get_field_map allocates and adds values to a hash_map, which is the responsibility of the caller to free. Further, the hash map stores a key -> value mapping of char * -> rosidl_runtime_c__type_description__Field *. That is, we are only getting the pointers to the underlying data, not the underlying data itself. Thus, it is entirely appropriate for this function to initialize a hash_map to NULL, have that allocated and filled in by rosidl_runtime_c_type_description_utils_get_field_map, use that data, and then free it.

That said, this is buggy. If we end up at line 693, then we'll skip cleaning up the hash_map. I'll suggest moving this above the if (description->fields.size != map_length) { block, since we already got the data we need from the hash_map.

Finally, this actually seems like a very expensive way to get the number of unique items in the type description field. It would be far more efficient to have a rosidl_runtime_c_type_description_utils_get_size which iterates over the individual descriptions and just returns a count. @methylDragon you don't need to fix this now, but it would be good to open up an issue for follow-up which includes comments like this.

Signed-off-by: methylDragon <methylDragon@gmail.com>
ret = rcutils_hash_map_fini(hash_map);
if (ret != RCUTILS_RET_OK) {
RCUTILS_SET_ERROR_MSG("Could not finalize hash map");
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is still open about getting rid of the duplicate rcutils_hash_map_fini. But it is correct right now, it is just code that is unnecessary. So we can defer that to a follow-up as well.

@methylDragon methylDragon merged commit 7583b95 into rolling Apr 11, 2023
@delete-merged-branch delete-merged-branch bot deleted the runtime_interface_reflection_allocators branch April 11, 2023 06:02
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.

4 participants