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

bpo-31249: Fix ref cycle in ThreadPoolExecutor #3178

Merged
merged 4 commits into from
Aug 22, 2017
Merged

bpo-31249: Fix ref cycle in ThreadPoolExecutor #3178

merged 4 commits into from
Aug 22, 2017

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Aug 22, 2017

WorkItem.run() of concurrent.futures used by ThreadPoolExecutor now
breaks a reference cycle between an exception object and the WorkItem
object.

ThreadPoolExecutor.shutdown(wait=True) now also clears the set of
threads.

https://bugs.python.org/issue31249

@@ -148,4 +150,5 @@ def shutdown(self, wait=True):
if wait:
for t in self._threads:
t.join()
self._threads.clear()
Copy link
Member Author

Choose a reason for hiding this comment

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

This change is not strictly needed to fix the initial bug:
https://bugs.python.org/issue31249#msg300634

But it should help to prevent leaking dangling threads if the executor object lives longer than expected.

Copy link
Member

Choose a reason for hiding this comment

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

I have the feeling you're getting obsessed about "dangling threads".

Copy link
Member Author

Choose a reason for hiding this comment

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

@pitrou: I have the feeling you're getting obsessed about "dangling threads".

That's true. In my experience, sometimes, it shows a larger issue. For example, https://bugs.python.org/issue31249 pointed a reference cycle which wasn't seen before.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm working on race conditions since 3-6 months, and I saw so many non deterministic behaviours. I would like to make Python test suite more reliable, more reproductible.

Copy link
Member

Choose a reason for hiding this comment

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

At least, this part should be under the if wait clause IMO.

Copy link
Member

Choose a reason for hiding this comment

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

Also, there is no race condition here. Besides the Thread object doesn't seem to hold onto any important data, so it shouldn't be a problem if isn't collected immediately.

Copy link
Member Author

Choose a reason for hiding this comment

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

At least, this part should be under the if wait clause IMO.

I hesitated to not clear threads on shutdown(wait=False), but I don't see how clearing _theads can introduce any issue.

Anyway, I made the change ;-)

Copy link
Member Author

Choose a reason for hiding this comment

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

Also, there is no race condition here. Besides the Thread object doesn't seem to hold onto any important data, so it shouldn't be a problem if isn't collected immediately.

Hum, you know what? I reverted my changes on shutdown() to only break the reference cycle in _WorkItem ;-) Let's keep the change as small as possible.

concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now
breaks a reference cycle between an exception object and the WorkItem
object. ThreadPoolExecutor.shutdown() now also clears its threads
set.
@vstinner
Copy link
Member Author

@gpshead, @pitrou: What do you think of the added "self._threads.clear()" statement?

@vstinner vstinner merged commit bc61315 into python:master Aug 22, 2017
@vstinner vstinner deleted the futures_cycle branch August 22, 2017 14:50
@gpshead
Copy link
Member

gpshead commented Aug 29, 2017

given I didn't respond earlier and I see no more self._threads.clear() in the accepted change, this change looks good to me. 👍

@Mariatta
Copy link
Member

Mariatta commented Sep 6, 2017

Already backported in #3253 so I'm removing the label.

GadgetSteve pushed a commit to GadgetSteve/cpython that referenced this pull request Sep 10, 2017
* bpo-31249: Fix ref cycle in ThreadPoolExecutor

concurrent.futures: WorkItem.run() used by ThreadPoolExecutor now
breaks a reference cycle between an exception object and the WorkItem
object. ThreadPoolExecutor.shutdown() now also clears its threads
set.

* shutdown() now only clears threads if wait is true.

* Revert changes on shutdown()
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.

6 participants