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

Free memory when things don't go as planned #138

Merged
merged 1 commit into from
Nov 8, 2017
Merged

Conversation

sloretz
Copy link
Contributor

@sloretz sloretz commented Nov 1, 2017

Follow up to comments on #137

  • Reverted moving of the PyCapsule creation to eliminate some Py_DECREF()
  • Added PyMem_Free calls to failure cases (sometimes moving code down to reduce the number of places where this is called)

CI

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@sloretz sloretz added the in review Waiting for review (Kanban column) label Nov 1, 2017
@sloretz sloretz self-assigned this Nov 1, 2017
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));
Copy link
Member

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.

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 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);
Copy link
Contributor

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.

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'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

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tracking bug #139

Copy link
Contributor

@clalancette clalancette left a 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.

Copy link
Member

@mikaelarguedas mikaelarguedas left a comment

Choose a reason for hiding this comment

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

lgtm

@sloretz sloretz merged commit c8d3c54 into master Nov 8, 2017
@sloretz sloretz deleted the rclpy_free_on_failure branch November 8, 2017 22:09
@sloretz sloretz removed the in review Waiting for review (Kanban column) label Nov 8, 2017
sloretz added a commit that referenced this pull request Nov 9, 2017
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)
sloretz added a commit that referenced this pull request Nov 9, 2017
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)
sloretz added a commit that referenced this pull request Nov 14, 2017
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)
sloretz added a commit that referenced this pull request Nov 15, 2017
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)
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