| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Protect dict iterations by wrapping them with _IterationGuard in the following methods: - WeakValueDictionary.copy() - WeakValueDictionary.__deepcopy__() - WeakKeyDictionary.copy() - WeakKeyDictionary.__deepcopy__()
|
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA). Unfortunately we couldn't find an account corresponding to your GitHub username on bugs.python.org (b.p.o) to verify you have signed the CLA (this might be simply due to a missing "GitHub Name" entry in your b.p.o account settings). This is necessary for legal reasons before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. You can check yourself to see if the CLA has been received. Thanks again for your contribution, we look forward to reviewing it! |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM. We might want to add a test (see check_weak_destroy_and_mutate_while_iterating in test_weakref.py).
Sorry, something went wrong.
There was a problem hiding this comment.
Is it possible to write a test reproducing the bug? (to then make sure that the fix works as expected)
Sorry, something went wrong.
As much as I want, I couldn't write a reliable test case in a standalone Python file to trigger this bug. I could, however, reliably trigger it when debugging my multithreaded PySide2 application. We also happened to trigger it once on our CI after hundreds of runs. I'm open to ideas of how to write a reliable test case to trigger this bug! |
Sorry, something went wrong.
|
I explained above where to look for and how to add a test. Please take a look. Edit: ok, the challenge here is to execute arbitrary code during the copy method since the iterator doesn't survive the method call. Other methods using IterationGuard are easier to test since they are generators, so you can easily execute code in-between loop iterations. |
Sorry, something went wrong.
|
@pitrou I took a look at check_weak_destroy_and_mutate_while_iterating(). It seems to me that this test case is ensuring keys/values of weakref dictionary can be destroyed during iterations. However, without monkeypatch, I cannot inject code to delete an object during the execution copy() or __deepcopy__() -- unless I'm missing something. Any suggestions? |
Sorry, something went wrong.
|
@ltfish You're right, I was too optimistic. I think we're left to using two threads: one that heavily copies a very large weakdict, another that loses references to the weakdict keys' or values', one at a time, in more or less random order. |
Sorry, something went wrong.
|
@pitrou Thanks. Lemme give it a try! |
Sorry, something went wrong.
|
On master branch: $ ../python -m unittest -v test.test_weakref.MappingTestCase
test_make_weak_keyed_dict_from_dict (test.test_weakref.MappingTestCase) ... ok
test_make_weak_keyed_dict_from_weak_keyed_dict (test.test_weakref.MappingTestCase) ... ok
test_make_weak_keyed_dict_repr (test.test_weakref.MappingTestCase) ... ok
test_make_weak_valued_dict_from_dict (test.test_weakref.MappingTestCase) ... ok
test_make_weak_valued_dict_from_weak_valued_dict (test.test_weakref.MappingTestCase) ... ok
test_make_weak_valued_dict_misc (test.test_weakref.MappingTestCase) ... ok
test_make_weak_valued_dict_repr (test.test_weakref.MappingTestCase) ... ok
test_threaded_weak_key_dict_copy (test.test_weakref.MappingTestCase) ... FAIL
test_threaded_weak_key_dict_deepcopy (test.test_weakref.MappingTestCase) ... FAIL
test_threaded_weak_value_dict_copy (test.test_weakref.MappingTestCase) ... FAIL
test_threaded_weak_value_dict_deepcopy (test.test_weakref.MappingTestCase) ... FAIL
test_threaded_weak_valued_consistency (test.test_weakref.MappingTestCase) ... ok
test_threaded_weak_valued_pop (test.test_weakref.MappingTestCase) ... ok
test_threaded_weak_valued_setdefault (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_bad_delitem (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_cascading_deletes (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_delitem (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_dict_popitem (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_dict_setdefault (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_dict_update (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_iters (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_len_cycles (test.test_weakref.MappingTestCase) ... ok
test_weak_keyed_len_race (test.test_weakref.MappingTestCase) ... ok
test_weak_keys (test.test_weakref.MappingTestCase) ... ok
test_weak_keys_destroy_while_iterating (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_delitem (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_dict_popitem (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_dict_setdefault (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_dict_update (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_iters (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_len_cycles (test.test_weakref.MappingTestCase) ... ok
test_weak_valued_len_race (test.test_weakref.MappingTestCase) ... ok
test_weak_values (test.test_weakref.MappingTestCase) ... ok
test_weak_values_destroy_while_iterating (test.test_weakref.MappingTestCase) ... ok
======================================================================
FAIL: test_threaded_weak_key_dict_copy (test.test_weakref.MappingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1760, in test_threaded_weak_key_dict_copy
self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, False)
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1753, in check_threaded_weak_dict_copy
self.fail("Caught a RuntimeError: \"%s\". WeakRef dictionary copying failed." % exc[0])
AssertionError: Caught a RuntimeError: "dictionary changed size during iteration". WeakRef dictionary copying failed.
======================================================================
FAIL: test_threaded_weak_key_dict_deepcopy (test.test_weakref.MappingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1765, in test_threaded_weak_key_dict_deepcopy
self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, True)
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1753, in check_threaded_weak_dict_copy
self.fail("Caught a RuntimeError: \"%s\". WeakRef dictionary copying failed." % exc[0])
AssertionError: Caught a RuntimeError: "dictionary changed size during iteration". WeakRef dictionary copying failed.
======================================================================
FAIL: test_threaded_weak_value_dict_copy (test.test_weakref.MappingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1770, in test_threaded_weak_value_dict_copy
self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, False)
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1753, in check_threaded_weak_dict_copy
self.fail("Caught a RuntimeError: \"%s\". WeakRef dictionary copying failed." % exc[0])
AssertionError: Caught a RuntimeError: "dictionary changed size during iteration". WeakRef dictionary copying failed.
======================================================================
FAIL: test_threaded_weak_value_dict_deepcopy (test.test_weakref.MappingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1775, in test_threaded_weak_value_dict_deepcopy
self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, True)
File "/home/fish/projects/cpython/Lib/test/test_weakref.py", line 1753, in check_threaded_weak_dict_copy
self.fail("Caught a RuntimeError: \"%s\". WeakRef dictionary copying failed." % exc[0])
AssertionError: Caught a RuntimeError: "dictionary changed size during iteration". WeakRef dictionary copying failed.
----------------------------------------------------------------------
Ran 34 tests in 4.820s
FAILED (failures=4)
With this PR: $ ../python -m unittest -v test.test_weakref.MappingTestCase test_make_weak_keyed_dict_from_dict (test.test_weakref.MappingTestCase) ... ok test_make_weak_keyed_dict_from_weak_keyed_dict (test.test_weakref.MappingTestCase) ... ok test_make_weak_keyed_dict_repr (test.test_weakref.MappingTestCase) ... ok test_make_weak_valued_dict_from_dict (test.test_weakref.MappingTestCase) ... ok test_make_weak_valued_dict_from_weak_valued_dict (test.test_weakref.MappingTestCase) ... ok test_make_weak_valued_dict_misc (test.test_weakref.MappingTestCase) ... ok test_make_weak_valued_dict_repr (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_key_dict_copy (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_key_dict_deepcopy (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_value_dict_copy (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_value_dict_deepcopy (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_valued_consistency (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_valued_pop (test.test_weakref.MappingTestCase) ... ok test_threaded_weak_valued_setdefault (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_bad_delitem (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_cascading_deletes (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_delitem (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_dict_popitem (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_dict_setdefault (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_dict_update (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_iters (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_len_cycles (test.test_weakref.MappingTestCase) ... ok test_weak_keyed_len_race (test.test_weakref.MappingTestCase) ... ok test_weak_keys (test.test_weakref.MappingTestCase) ... ok test_weak_keys_destroy_while_iterating (test.test_weakref.MappingTestCase) ... ok test_weak_valued_delitem (test.test_weakref.MappingTestCase) ... ok test_weak_valued_dict_popitem (test.test_weakref.MappingTestCase) ... ok test_weak_valued_dict_setdefault (test.test_weakref.MappingTestCase) ... ok test_weak_valued_dict_update (test.test_weakref.MappingTestCase) ... ok test_weak_valued_iters (test.test_weakref.MappingTestCase) ... ok test_weak_valued_len_cycles (test.test_weakref.MappingTestCase) ... ok test_weak_valued_len_race (test.test_weakref.MappingTestCase) ... ok test_weak_values (test.test_weakref.MappingTestCase) ... ok test_weak_values_destroy_while_iterating (test.test_weakref.MappingTestCase) ... ok ---------------------------------------------------------------------- Ran 34 tests in 6.228s OK |
Sorry, something went wrong.
|
Hi there, is there any update on this PR? |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM, but I would prefer to have a second core dev like @pitrou to review this change.
As soon as the change has a test, it looks good to me :-)
Does the tests fail without the fix?
Sorry, something went wrong.
Please see my previous reply. Without the fix, my newly added test case fails reliably on my machine. I can also open a PR without my fix if needed (to make sure the test case works as expected on the CI). |
Sorry, something went wrong.
…honGH-11384) Protect dict iterations by wrapping them with _IterationGuard in the following methods: - WeakValueDictionary.copy() - WeakValueDictionary.__deepcopy__() - WeakKeyDictionary.copy() - WeakKeyDictionary.__deepcopy__() (cherry picked from commit 96d37db) Co-authored-by: Fish <ltfish@users.noreply.github.com>
|
GH-11785 is a backport of this pull request to the 3.7 branch. |
Sorry, something went wrong.
…11384) (GH-11785) Protect dict iterations by wrapping them with _IterationGuard in the following methods: - WeakValueDictionary.copy() - WeakValueDictionary.__deepcopy__() - WeakKeyDictionary.copy() - WeakKeyDictionary.__deepcopy__() (cherry picked from commit 96d37db) Co-authored-by: Fish <ltfish@users.noreply.github.com>
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Protect dict iterations by wrapping them with _IterationGuard in the
following methods:
https://bugs.python.org/issue35615