bpo-27144: concurrent.futures as_complete and map iterators do not keep reference to returned object#1560
Conversation
|
@grzgrzgrz3, thanks for your PR! By analyzing the history of the files in this pull request, we identified @brianquinlan, @asvetlov and @ezio-melotti to be potential reviewers. |
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
Can you give this function a more descriptive name?
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
Can you explain why you need to do this?
There was a problem hiding this comment.
If your question is about line 176. Based on issue20319, changes on future waiters list should be locked.
There was a problem hiding this comment.
I guess I don't understand why you need to remove the waiter. Previous code didn't do this.
There was a problem hiding this comment.
If we do not remove waiter, second result set on future will trigger waiter and cause KeyError, future is already returned and reference cleared.
For example:
>>> from concurrent.futures import Future, as_completed
>>> fs_finished = Future()
>>> fs = Future()
>>> fs_finished.set_result("")
>>> for x in as_completed([fs_finished, fs, Future()]):
... fs.set_result(None)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/grzegorz/cpython/Lib/concurrent/futures/_base.py", line 235, in as_completed
pending.remove(future)
KeyError: <Future at 0x7f566ff6fc20 state=finished returned NoneType>
This error occurs in both version.
However docstring for Future.set_result and Future.set_exception says:
Should only be used by Executor implementations and unit tests.
So maybe we should ignore this case?
There was a problem hiding this comment.
If I'm understanding correctly then, yes, I would certainly consider it an error to call set_result twice.
There was a problem hiding this comment.
Anyway, this part is not relate to origin issue, so i ll remove discussed code.
Maybe in future someone encounters it and create new issue, so it can be discussed there.
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
If future_list is a list, then this is O(n)...
There was a problem hiding this comment.
In this use case future_list will be always a set.
set().remove is O(1).
I will rename future_list to futures_collection
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
If fs is a list, then this is O(n).
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
In this case fs is always a list, however I can modify this function to yield last element. I think order here does not matter. If order matter, reversing list is the option. What do you think?
There was a problem hiding this comment.
Either reverse the list or make it a deque, as you prefer.
Lib/concurrent/futures/process.py
Outdated
There was a problem hiding this comment.
Why do you need this? Please add a comment and/or docstring.
Lib/test/test_concurrent_futures.py
Outdated
There was a problem hiding this comment.
Please give this function a more descriptive name, new_object perhaps?
|
Thanks for caring about this issue. I think the proposed fix needs improvements, see comments. |
67e22b6 to
f24c9d4
Compare
|
Thank you for review 👍. To be honest when i was writing it i do not think about complexity at all. Please review new version. I have pushed with force, delete branch before pulling. |
Lib/concurrent/futures/_base.py
Outdated
There was a problem hiding this comment.
This is my best, i could not came up with anything better. Maybe you can suggest name more descriptive.
There was a problem hiding this comment.
Perhaps add a comment explaining why this function exists, then?
Lib/test/test_concurrent_futures.py
Outdated
There was a problem hiding this comment.
Out of curiosity, why does your PR affect this?
There was a problem hiding this comment.
My mistake, when rebasing.
Lib/test/test_concurrent_futures.py
Outdated
There was a problem hiding this comment.
Isn't this already tested by test_map? Or perhaps you just want to augment test_map with a chunksize-using test.
f24c9d4 to
12dc30f
Compare
|
Any update on review. Please have a look at last revision. |
|
Sorry for the delay @grzgrzgrz3. The PR now has conflicts, could you please resolve them? |
reference to returned object
12dc30f to
d581bba
Compare
|
Done. |
|
I'm trying to push some small changes to your branch. Crossing fingers. |
…ying on sys.getrefcount() in tests.
ae0262c to
d67b22c
Compare
|
I'm merging this. Thank you very much! |
…not keep reference to returned object (pythonGH-1560) * bpo-27144: concurrent.futures as_complie and map iterators do not keep reference to returned object * Some nits. Improve wordings in docstrings and comments, and avoid relying on sys.getrefcount() in tests. (cherry picked from commit 97e1b1c)
* 'master' of https://github.com/python/cpython: (601 commits) remove check for bug last seem in Solaris 9 (python#3285) Change code owners for hashlib and ssl to the crypto team (python#3284) bpo-31281: Fix pathlib.Path incompatibility in fileinput (pythongh-3208) remove autoconf check for select() (python#3283) remove configure check for 'volatile' (python#3281) Add missing _sha3 module to Setup.dist (python#2395) bpo-12383: Also ignore __PYVENV_LAUNCHER__ (python#3278) bpo-9146: add the missing NEWS entry. (python#3275) Fix a c.f.as_completed() refleak previously introduced in bpo-27144 (python#3270) bpo-31185: Fixed miscellaneous errors in asyncio speedup module. (python#3076) remove a redundant lower in urllib.parse.urlsplit (python#3008) bpo-31323: Fix reference leak in test_ssl (python#3263) bpo-31250, test_asyncio: fix EventLoopTestsMixin.tearDown() (python#3264) bpo-31326: ProcessPoolExecutor waits for the call queue thread (python#3265) bpo-27144: concurrent.futures as_complete and map iterators do not keep reference to returned object (python#1560) bpo-31250, test_asyncio: fix dangling threads (python#3252) bpo-31217: Fix regrtest -R for small integer (python#3260) bpo-30096: Use ABC in abc reference examples (python#1220) bpo-30737: Update DevGuide links to new URL (pythonGH-3228) [Trivial] Remove now redundant assert (python#3245) ...
…ep reference to returned object (python#1560) * bpo-27144: concurrent.futures as_complie and map iterators do not keep reference to returned object * Some nits. Improve wordings in docstrings and comments, and avoid relying on sys.getrefcount() in tests.
|
|
||
| total_futures = len(fs) | ||
|
|
||
| fs = set(fs) |
There was a problem hiding this comment.
This is a regression. The ordering of instructions here is wrong. Now fs must be a sequence to support the len(fs).
…ted()` This was possible before. pythonGH-1560 introduced a regression after 3.6.2 got released where only sequences were accepted now. This commit addresses this problem.
…completed()` (pythonGH-3830) This was possible before. pythonGH-1560 introduced a regression after 3.6.2 got released where only sequences were accepted now. This commit addresses this problem. (cherry picked from commit 574562c)
…completed()` (pythonGH-3830) (python#3831) This was possible before. pythonGH-1560 introduced a regression after 3.6.2 got released where only sequences were accepted now. This commit addresses this problem. (cherry picked from commit 574562c)
https://bugs.python.org/issue27144