-
Notifications
You must be signed in to change notification settings - Fork 225
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
Free memory when things don't go as planned #138
Conversation
return NULL; | ||
} | ||
g_sigint_gc_handle = sigint_gc; | ||
PyObject * pylist = PyList_New(2); | ||
PyList_SET_ITEM(pylist, 0, pygc); | ||
PyList_SET_ITEM(pylist, 0, PyCapsule_New(sigint_gc, "rcl_guard_condition_t", NULL)); |
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 value of PyCapsule_New
needs to be checked.
Same below.
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 added this to #139. If it is alright with you I would like to tackle this in a separate PR.
rcl_reset_error(); | ||
PyMem_Free(sigint_gc); | ||
return NULL; | ||
} | ||
g_sigint_gc_handle = sigint_gc; | ||
PyObject * pylist = PyList_New(2); |
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.
FWIW, the Python documentation for PyList_New
says:
Return a new list of length len on success, or NULL on failure.
Which means we should check the return value of PyList_New
as well (throughout this file). I'm not sure if we want to do that as part of this PR or a different one, though.
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'd rather do this in a few smaller PRs. I double checked all the functions in _rclpy.c
; these are being used and can fail but are not being checked.
PyList_New
PyCapsule_New
FYI @dirk-thomas
PyLong_FromUnsignedLongLong
PyMem_Malloc
PyUnicode_FromString
(not in web documentation but source code says otherwise)
PyLong_FromSize_t
PyObject_GetAtterString
PyLong_FromLongLong
PyCapsule_GetName
PyList_Append
PyObject_CallObject
PyTuple_New
PyTuple_SetItem
PyList_SetItem
PyImport_ImportModule
PyObject_SetAttrString
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.
Ah, good, you were a lot more comprehensive than I was. It's fine by me to do it in separate PRs; I'd suggest a tracking bug since there are so many of them. I'll leave it up to you, though.
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.
Tracking bug #139
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.
These changes look good to me, and should leak less memory.
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
Moved wait set code to its own class for code reuse Added timeout_sec_to_nsec() wait_for_service() implemented with timers Added unit tests for timeout_sec_to_nsec() Added test for WaitSet class Use negative timeouts to mean block forever Double quotes to single quotes Added wait_for_service() tests and fixed bugs it caught Eliminate blind exception warning Reduce flakiness of test by increasing time to 0.1s Comment says negative timeouts block forever Use :returns: Move add_subscriptions() arugments -> arguments Daemon as keyword arg Remove unnecessary namespace argument Use S_TO_NS in test More tests using S_TO_NS Use monotonic clock for testing timer time Increased test timeout by 30 seconds CheckExact -> IsValid Fixed wait_set not clearing ready_pointers Remove unnecessary namespace keyword arg Non-blocking wait remove expression that always evaluates to True Raise ValueError on invalid capsule Simplified timeout_sec_to_nsec Added 'WaitSet.destroy()' and made executor use it GraphListener periodically checks if rclpy is shutdown Misc fixes after pycapsule names Wait set class always clears entities before waiting Remove underscore on import Reformat timeout line Use () when raising exceptions Removed _ on imports Executor optimizations ~5% less overhead in wait_for_ready_callbacks() Fixed executor yielding entities to wrong node Also refactored some code to a sub-generator Use list() only where necessary Docstring in imperitive mood Executors reuse iterator moved some wait_set code into C Avoid another list comprehension Replaced WaitSet with C code in executor Remove test code Use lists instead of set Use locally defined function instead of member function Shorten code using macro Move everything to new wait_set code protect against ImportError.path being None (#134) Free memory when things don't go as planned (#138)
Moved wait set code to its own class for code reuse Added timeout_sec_to_nsec() wait_for_service() implemented with timers Added unit tests for timeout_sec_to_nsec() Added test for WaitSet class Use negative timeouts to mean block forever Double quotes to single quotes Added wait_for_service() tests and fixed bugs it caught Eliminate blind exception warning Reduce flakiness of test by increasing time to 0.1s Comment says negative timeouts block forever Use :returns: Move add_subscriptions() arugments -> arguments Daemon as keyword arg Remove unnecessary namespace argument Use S_TO_NS in test More tests using S_TO_NS Use monotonic clock for testing timer time Increased test timeout by 30 seconds CheckExact -> IsValid Fixed wait_set not clearing ready_pointers Remove unnecessary namespace keyword arg Non-blocking wait remove expression that always evaluates to True Raise ValueError on invalid capsule Simplified timeout_sec_to_nsec Added 'WaitSet.destroy()' and made executor use it GraphListener periodically checks if rclpy is shutdown Misc fixes after pycapsule names Wait set class always clears entities before waiting Remove underscore on import Reformat timeout line Use () when raising exceptions Removed _ on imports Executor optimizations ~5% less overhead in wait_for_ready_callbacks() Fixed executor yielding entities to wrong node Also refactored some code to a sub-generator Use list() only where necessary Docstring in imperitive mood Executors reuse iterator moved some wait_set code into C Avoid another list comprehension Replaced WaitSet with C code in executor Remove test code Use lists instead of set Use locally defined function instead of member function Shorten code using macro Move everything to new wait_set code protect against ImportError.path being None (#134) Free memory when things don't go as planned (#138)
Moved wait set code to its own class for code reuse Added timeout_sec_to_nsec() wait_for_service() implemented with timers Added unit tests for timeout_sec_to_nsec() Added test for WaitSet class Use negative timeouts to mean block forever Double quotes to single quotes Added wait_for_service() tests and fixed bugs it caught Eliminate blind exception warning Reduce flakiness of test by increasing time to 0.1s Comment says negative timeouts block forever Use :returns: Move add_subscriptions() arugments -> arguments Daemon as keyword arg Remove unnecessary namespace argument Use S_TO_NS in test More tests using S_TO_NS Use monotonic clock for testing timer time Increased test timeout by 30 seconds CheckExact -> IsValid Fixed wait_set not clearing ready_pointers Remove unnecessary namespace keyword arg Non-blocking wait remove expression that always evaluates to True Raise ValueError on invalid capsule Simplified timeout_sec_to_nsec Added 'WaitSet.destroy()' and made executor use it GraphListener periodically checks if rclpy is shutdown Misc fixes after pycapsule names Wait set class always clears entities before waiting Remove underscore on import Reformat timeout line Use () when raising exceptions Removed _ on imports Executor optimizations ~5% less overhead in wait_for_ready_callbacks() Fixed executor yielding entities to wrong node Also refactored some code to a sub-generator Use list() only where necessary Docstring in imperitive mood Executors reuse iterator moved some wait_set code into C Avoid another list comprehension Replaced WaitSet with C code in executor Remove test code Use lists instead of set Use locally defined function instead of member function Shorten code using macro Move everything to new wait_set code protect against ImportError.path being None (#134) Free memory when things don't go as planned (#138)
Moved wait set code to its own class for code reuse Added timeout_sec_to_nsec() wait_for_service() implemented with timers Added unit tests for timeout_sec_to_nsec() Added test for WaitSet class Use negative timeouts to mean block forever Double quotes to single quotes Added wait_for_service() tests and fixed bugs it caught Eliminate blind exception warning Reduce flakiness of test by increasing time to 0.1s Comment says negative timeouts block forever Use :returns: Move add_subscriptions() arugments -> arguments Daemon as keyword arg Remove unnecessary namespace argument Use S_TO_NS in test More tests using S_TO_NS Use monotonic clock for testing timer time Increased test timeout by 30 seconds CheckExact -> IsValid Fixed wait_set not clearing ready_pointers Remove unnecessary namespace keyword arg Non-blocking wait remove expression that always evaluates to True Raise ValueError on invalid capsule Simplified timeout_sec_to_nsec Added 'WaitSet.destroy()' and made executor use it GraphListener periodically checks if rclpy is shutdown Misc fixes after pycapsule names Wait set class always clears entities before waiting Remove underscore on import Reformat timeout line Use () when raising exceptions Removed _ on imports Executor optimizations ~5% less overhead in wait_for_ready_callbacks() Fixed executor yielding entities to wrong node Also refactored some code to a sub-generator Use list() only where necessary Docstring in imperitive mood Executors reuse iterator moved some wait_set code into C Avoid another list comprehension Replaced WaitSet with C code in executor Remove test code Use lists instead of set Use locally defined function instead of member function Shorten code using macro Move everything to new wait_set code protect against ImportError.path being None (#134) Free memory when things don't go as planned (#138)
Follow up to comments on #137
Py_DECREF()
PyMem_Free
calls to failure cases (sometimes moving code down to reduce the number of places where this is called)CI