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

concurrent.futures.as_completed() fails when given duplicate Futures #64566

Closed
glangford mannequin opened this issue Jan 23, 2014 · 19 comments
Closed

concurrent.futures.as_completed() fails when given duplicate Futures #64566

glangford mannequin opened this issue Jan 23, 2014 · 19 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@glangford
Copy link
Mannequin

glangford mannequin commented Jan 23, 2014

BPO 20367
Nosy @gvanrossum, @tim-one, @mdickinson, @vstinner, @1st1
Files
  • test_dupfuture.py
  • issue20367.patch
  • issue20367.patch
  • issue20367.patch
  • issue20367.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2014-01-27.08:14:07.882>
    created_at = <Date 2014-01-23.15:00:48.109>
    labels = ['type-bug', 'library']
    title = 'concurrent.futures.as_completed() fails when given duplicate Futures'
    updated_at = <Date 2014-02-06.00:07:36.755>
    user = 'https://bugs.python.org/glangford'

    bugs.python.org fields:

    activity = <Date 2014-02-06.00:07:36.755>
    actor = 'gvanrossum'
    assignee = 'none'
    closed = True
    closed_date = <Date 2014-01-27.08:14:07.882>
    closer = 'vstinner'
    components = ['Library (Lib)']
    creation = <Date 2014-01-23.15:00:48.109>
    creator = 'glangford'
    dependencies = []
    files = ['33658', '33684', '33685', '33686', '33728']
    hgrepos = []
    issue_num = 20367
    keywords = ['patch']
    message_count = 19.0
    messages = ['208952', '208956', '208957', '208961', '209081', '209084', '209091', '209093', '209102', '209267', '209321', '209338', '209359', '209360', '209361', '209367', '209413', '210352', '210353']
    nosy_count = 7.0
    nosy_names = ['gvanrossum', 'tim.peters', 'mark.dickinson', 'vstinner', 'python-dev', 'yselivanov', 'glangford']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue20367'
    versions = ['Python 3.3', 'Python 3.4']

    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 23, 2014

    concurrent.futures.as_completed([f,f]) will yield f twice, then fail with a KeyError for a Future f which is not completed.

    If the Future has already completed, as_completed([f,f]) will yield f once and does not trigger an exception.

    What is the correct behaviour?
    as_completed( [f,f] ) -> yield f twice ?
    wait( [f,f], return_when=ALL_COMPLETED ) -> yield f twice ?

    @glangford glangford mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Jan 23, 2014
    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 23, 2014

    There is a subtlety in the as_completed() code which explains a lot - note that "finished" starts off as a set in the _AcquireFutures block. So if a Future f has already completed,
    as_completed( [f,f] )
    will only yield f once, because f appears once in the finished set.

    Later on when waiter events are processed, "finished" turns into a list because of the line:

    finished = waiter.finished_futures

    So any duplicates in that list will cause problems in pending.remove(Future).

    @vstinner
    Copy link
    Member

    Since the new asyncio module has also a Future class and functions like as_completed(), this issue concerns also asyncio. concurrent.futures and asyncio should have the same behaviour.

    @gvanrossum
    Copy link
    Member

    I think you the caller was wrong to pass in [f, f] in the first place.

    In asyncio, the argument is converted into a set before using it, but there's still a bug if you pass it a list containing two references to the same coroutine -- it gets wrapped in two separate Futures. I think the better behavior is to convert to a set first and then map coroutines to Futures.

    So concurrent.futures should also convert to a set first.

    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 24, 2014

    Proposed patch for as_completed(). bpo-20369 fixes wait(), and behaviour is consistent between the two.

    @vstinner
    Copy link
    Member

    Proposed patch for as_completed().

    Could you please try to write a unit test. The unit test should fail without the patch, and fail with the patch. Then create a new patch including the patch.

    If it's tricky to write a reliable test reproducing the race condition, you can use unittest.mock to mock some objects.

    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 24, 2014

    Could you please try to write a unit test.

    Revised patch with unit test for as_completed().

    @vstinner
    Copy link
    Member

    Hum, you should also modify the documentation to explicit the
    behaviour. Example: "Duplicates futures are only yielded once".

    You may add the same sentence in the asyncio.as_completed()
    documentation. It looks like asyncio tests doesn't test as_completed()
    with duplicated future. You may write a new patch to modify asyncio
    doc and tests. It should be very similar.

    + completed = [f for f in futures.as_completed( [f1,f1] ) ]

    You can just use list(futures.as_completed([f1,f1])). Please no space
    around parenthesis (see the PEP-8).

    + self.assertEqual( len(completed), 1 )

    No space around parenthesis (see the PEP-8):
    self.assertEqual(len(completed), 1).

    You may check the list value instead: self.assertEqual(completed, [f1])

    (Why "f1" name? There is no f2, maybe rename to f?)

    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 24, 2014

    Thanks for the feedback. The new patch is modified for PEP-8 with naming consistent with other concurrent tests. assertEqual I think is clearer by checking list length, so it is not changed. The docstring is updated.

    I suggest asyncio be handled separately.

    @gvanrossum
    Copy link
    Member

    LGTM. But you also need to update Doc/library/concurrent.futures.rst

    I see this as a bugfix so it's not necessary to get this in before the beta 3 release tonight.

    I will work on an asyncio patch and test.

    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 26, 2014

    Ah...ok, here is a patch that includes an update to Doc/library/concurrent.futures.rst as well.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jan 26, 2014

    New changeset 58b0f3e1ddf8 by Guido van Rossum in branch 'default':
    Fix issue bpo-20367: concurrent.futures.as_completed() for duplicate arguments.
    http://hg.python.org/cpython/rev/58b0f3e1ddf8

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jan 26, 2014

    New changeset 1dac8c954488 by Victor Stinner in branch 'default':
    Issue bpo-20367: Add Glenn Langford to Misc/ACKS
    http://hg.python.org/cpython/rev/1dac8c954488

    @vstinner
    Copy link
    Member

    @guido: Why not fixing the issue in Python 3.3? You forgot to add Gleen Langford to Misc/ACKS!

    @gleen: Congrats for your first commit :)

    @gvanrossum
    Copy link
    Member

    Sorry, I suppose it needs to be backported to 3.3.

    If someone wants to do that, please do (I'm afraid I'd mess up the merge).

    @gvanrossum gvanrossum reopened this Jan 26, 2014
    @glangford
    Copy link
    Mannequin Author

    glangford mannequin commented Jan 26, 2014

    @victor: Thank you, and I appreciate all your advice! I am still learning the dev environment but hope to be helpful. :)

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jan 27, 2014

    New changeset 791b69f9f96d by Victor Stinner in branch '3.3':
    Issue bpo-20367: Fix behavior of concurrent.futures.as_completed() for duplicate
    http://hg.python.org/cpython/rev/791b69f9f96d

    @1st1
    Copy link
    Member

    1st1 commented Feb 5, 2014

    This one is still not merged in Tulip, right?

    @gvanrossum
    Copy link
    Member

    Correct, if you want to work on it, see http://code.google.com/p/tulip/issues/detail?id=114

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants