-
Notifications
You must be signed in to change notification settings - Fork 224
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
check for exceptions before returning from C extension #95
Conversation
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
As discussed offline, I think there is still a race condition in this scenario:
- This code is run:
if (PyErr_Occurred()) {
return NULL;
}
- continues because no error set
- keyboardinterrupt set from signal (SIGINT / ctrl-c)
- return non-NULL from C extension because no error was set when checked
And in that case we're still in the same boat as now.
This patch reduces the chance of that happening, but it seems like a conceptual problem. Maybe there is a better solution, but +1 for this today as an incremental improvement. I think it's worth looking into in more detail later.
This shouldn't be merged for beta 2 since it has too much potential for side effects. |
Actually, after doing some reading I think we should be ok. Apparently the KeyboardInterrupt can only be set when So my conclusion is that:
|
a34ac4c
to
458cf85
Compare
Given @wjwwood 's research, it seems like we may be able to merge this now. I've fired off a CI job for it (which doesn't guarantee this is correct, but at least ensures that there are no obvious regressions): |
as discussed in the waffle triage meetings of the last two weeks we decided to hold this until we look into the root of the problem rather than fixing the symptom
This is still adressing only that function and is still labeled as in progress |
e06ec72
to
0fbf30c
Compare
ros2/rosidl#240 addresses the actual problem. During the |
Some background on Python C extensions: a C function being called from Python can only do either of the two:
NULL
value orPyErr_
) or exception.If both is done the call will trigger a
SystemError: <built-in function your-name-here> returned a result with an error set
.Now consider the following case: a user presses Ctrl-C which sets the
KeyboardInterrupt
exception while a C function is running. If the function tries to return a non-NULL
value aSystemError
is the consequence. Instead before returning from the C function the code should check if an error is set (usingPyErr_Occurred
) and if that is the case returnNULL
(the standard rule applies to avoid leaking memory in that case).The benefit of the current patch can be reproduced with the following example which has a high chance of hitting Ctrl-C while this C function is running:
ros2 run image_tools cam2image
in one terminalros2 topic echo /image
in a second terminal and while it is printing messages hit Ctrl-CWithout the patch you have a high chance of seeing the
SystemError
. With the patch the program should gracefully exit without a visible exception.This PR currently only patches the function
rclpy_take
. The same would need to be done in all C function exposed in Python for each non-NULL
return (which is in quite a few places). Before replicating the change for all other cases I would like to have feedback if this is viable or if there is a different way (or we don't care about the way this "crashes").