-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
gh-71936: Fix race condition in multiprocessing.Pool #124973
Conversation
Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection would be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task, and a new object is allocated that shares the id() of a previously deleted one. Instead of using the id() of the token (or the proxy), use a unique, non-reusable number. Co-Authored-By: Akinori Hattori <hattya@gmail.com>
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.
A couple possible things to improve, but good regardless.
I'm not worried about a regression test for this. Hard, and clearly better than what came before.
As I confirmed in #71936 (comment), this solves the problem for me. Will this be back ported? |
I see no issues in our post-merge testing, so, yes :) |
Thanks @encukou for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Thanks @encukou for the PR 🌮🎉.. I'm working now to backport this PR to: 3.12. |
…124973) * pythongh-71936: Fix race condition in multiprocessing.Pool Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection would be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task, and a new object is allocated that shares the id() of a previously deleted one. Instead of using the id() of the token (or the proxy), use a unique, non-reusable number. (cherry picked from commit ba088c8) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-Authored-By: Akinori Hattori <hattya@gmail.com>
GH-126869 is a backport of this pull request to the 3.13 branch. |
…124973) * pythongh-71936: Fix race condition in multiprocessing.Pool Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection would be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task, and a new object is allocated that shares the id() of a previously deleted one. Instead of using the id() of the token (or the proxy), use a unique, non-reusable number. (cherry picked from commit ba088c8) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-Authored-By: Akinori Hattori <hattya@gmail.com>
GH-126870 is a backport of this pull request to the 3.12 branch. |
… (GH-126870) Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection would be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task, and a new object is allocated that shares the id() of a previously deleted one. Instead of using the id() of the token (or the proxy), use a unique, non-reusable number. (cherry picked from commit ba088c8) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Akinori Hattori <hattya@gmail.com>
… (GH-126869) Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection would be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task, and a new object is allocated that shares the id() of a previously deleted one. Instead of using the id() of the token (or the proxy), use a unique, non-reusable number. (cherry picked from commit ba088c8) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Akinori Hattori <hattya@gmail.com>
This is based on @hattya's gh-98274.
As far as I can tell, the race condition is caused by using
id()
as a unique identifier, assuming that it can't be reused.@hattya's PR supplements the remote object's id with the id of the proxy. But since
_decref
is called after the proxy is deleted, that id could be reused as well. Note that this is a theoretical concern, I wasn't able to reproduce it.This PR uses a counter (with locked store&increment) to get unique values for
_idset
.Unfortunately, I have no idea how to test this :/