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

Fix spin_once_until_future_complete to quit when the future finishes. #1143

Merged
merged 3 commits into from
Aug 1, 2023

Conversation

clalancette
Copy link
Contributor

This makes it match the function name much more closely. While we are in here, also fix a bug where the multi-threaded version would not quit immediately after the future completes. And also add tests for both of these situations.

This should fix #989

This makes it match the function name much more closely.
While we are in here, also fix a bug where the multi-threaded
version would not quit immediately after the future completes.
And also add tests for both of these situations.

Signed-off-by: Chris Lalancette <clalancette@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.

lgtm, I had one question, but I don't think it's necessarily blocking.

future.result() # re-raise any exceptions

def spin_once(self, timeout_sec: Optional[float] = None) -> None:
self._spin_once_impl(timeout_sec)
Copy link
Member

Choose a reason for hiding this comment

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

What, if anything, should be done with self._futures here? Is it intended that the futures are held until the next call?

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'm not sure I totally understand the question, but let me explain what I understand happens to the futures in both spin_once and spin_once_until_future_complete.

When you are calling spin_once, then what happens is that our wait_condition for _spin_once_impl is the default lambda: False. That means that that condition will never cause the work loop (in _wait_for_ready_callbacks) to return early, and so that function will always find one piece of work (assuming it doesn't time out or shutdown). When it does find that piece of work, it executes it immediately in _spin_once_impl. After that we add it to the _futures list to check on whether it is done. We then also look at any other futures that were pending, and if those are done we execute the done handlers for those and remove them from the list.

When you are calling spin_once_until_future_complete, the logic is largely the same except that our wait_condition is the done callback on the future. So if the future finishes before we find other work to do, that can cause wait_for_ready_callbacks to return early. If that is the case, then it actually raises ConditionReachedException, because we have already called the done callback. And thus it is never added to _futures.

Does that make sense to you? And does that answer your question at all?

Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

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

@clalancette thanks for the PR. I just have a question before lgtm.

rclpy/rclpy/executors.py Show resolved Hide resolved
rclpy/rclpy/executors.py Outdated Show resolved Hide resolved
Signed-off-by: Chris Lalancette <clalancette@gmail.com>
Because we are executing the handler directly, we don't
need to store it and check for futures later.  We can just
check the result immediately.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

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

lgtm

@clalancette
Copy link
Contributor Author

clalancette commented Aug 1, 2023

CI:

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

@clalancette clalancette merged commit 5367703 into rolling Aug 1, 2023
3 checks passed
@delete-merged-branch delete-merged-branch bot deleted the clalancette/spin-once-until-future-complete branch August 1, 2023 16:44
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.

SingleThreadedExecutor::spin_once_until_future_complete continues to spin even if future is completed
4 participants