-
Notifications
You must be signed in to change notification settings - Fork 92
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
Ensure compliant publisher API #210
Conversation
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
return destroy_publisher(publisher); | ||
|
||
rmw_ret_t inner_ret = destroy_publisher(publisher); | ||
if (RMW_RET_OK != inner_ret) { |
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.
I don't like having to do this to ensure the first error that occurs is the one that pops up and that no subsequent error goes unnoticed.
If we had a way to tell rcutils
that we're in error handling or finalization/cleanup mode so that it doesn't complain about error states being overwritten (and prints the new one to stderr
, or aborts the program, or whatever), this code would simpler (and a bit more neat). What do reviewers think?
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.
The current logic isn't super nice, but isn't wrong either.
Maybe directly logging all destruction errors and setting a generic error state at the end is a better idea.
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.
The current logic isn't super nice, but isn't wrong either.
No, it's not incorrect, but it's... messy.
Maybe directly logging all destruction errors and setting a generic error state at the end is a better idea.
We could do that, but that doesn't cover errors during cleanup. Besides, it's important to know what the actual error was to do something about it (or debug it), nevermind leaks. At any rate, I don't mind doing this. I just figured it'd much easier if rcutils
took care of redirecting all RCUTILS_SET_ERROR_MSG()
for a given scope. @clalancette @wjwwood @jacobperron for feedback too.
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.
We could do that, but that doesn't cover errors during cleanup
Do you mean the cleanup that a function does when it fails?
In that case it would be good to set an error message about what failed, and log all cleanup failures.
So logging is fine in that case too,
I just figured it'd much easier if rcutils took care of redirecting all RCUTILS_SET_ERROR_MSG() for a given scope
How?
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.
For instance, having a flag in TLS that client code can toggle. For C++ implementations, we may be able to use RAII for easier control of the error handling scope. If done right it can reduce clutter.
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.
Ok, that's fair. As I said elsewhere, I wonder about the usefulness of a return code if we log everything.
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.
The return code would still be useful, as the caller can know that sth failed (it doesn't matter if we return the first error code or the last one).
The error string won't be useful if we log everything, yes.
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.
I wonder about the usefulness of a return code if we log everything
Isn't the purpose of the return code so that the calling function knows something went wrong, and optionally if there is enough information in the return code to then make an intelligent decision about what to do about it? The logging is more for after-the-fact debugging so having everything logged doesn't seem bad to me.
Having an error string would also still be useful for when logging is turned down, I think.
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.
Why not simply pass an RMW error state object around inside the implementation, with a setter that implements the behaviour of returning the first error and logging the rest? That's basically the pattern you have here with ret
and inner_ret
, but it'd remove the messiness from the code.
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.
and optionally if there is enough information in the return code to then make an intelligent decision about what to do about it?
IMHO that's the whole point of having different, documented return codes, vs. a bool.
Why not simply pass an RMW error state object around inside the implementation, with a setter that implements the behaviour of returning the first error and logging the rest?
Yeah, I was trying not to (re)build this behavior for each RMW implementation, but to make it widely available. I'll probably push this as-is until we've reached consensus on how to do this nicely.
@@ -1954,9 +1987,16 @@ extern "C" rmw_publisher_t * rmw_create_publisher( | |||
static_cast<void *>(&msg), | |||
nullptr)) | |||
{ | |||
rmw_error_state_t error_state = *rmw_get_error_state(); |
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.
nit: Inverting the logic in L1978, setting an error message and returning NULL will make the logic a bit clearer.
return destroy_publisher(publisher); | ||
|
||
rmw_ret_t inner_ret = destroy_publisher(publisher); | ||
if (RMW_RET_OK != inner_ret) { |
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.
The current logic isn't super nice, but isn't wrong either.
Maybe directly logging all destruction errors and setting a generic error state at the end is a better idea.
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.
It looks correct to me.
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
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
Ok, CI's green and reviewers are happy. Going in! |
Confirmed locally that this patch introduces no new leaks. |
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Precisely what the title says. Connected to ros2/rmw#252.