-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py/map.c: Clear value when re-using slot with ordered dictionaries #6128
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
Conversation
This issue occurred with the #5323 PR enabled to use ordered dict/map by default everywhere, hence the ordered implementation was being used in asyncio/uselect |
Thanks for the PR. Are you able to provide a pure Python test that shows the issue with map and ordered dicts? Regarding the second commit that changes uasyncio: I'm not sure that's good to merge at this point, probably it needs it's own PR to discuss (it allocates memory...). And I think that issue would anyway be fixed by #6125 (replacing |
@dpgeorge yep! Happy to do that. Is it worth me re-raising, or are you pretty confident that the |
I'm pretty confident |
I've dropped the uasyncio changes. I haven't found a way to put together a python-level test case, unfortunately. All other consumers of The visual inspection with relation to unordered maps make it reasonably trivial to verify that the fix is correct. Is there an accepted way to write a lower-level C test against the map interface for this? |
On its own I don't think the patch here fixes anything. Using always-ordered dicts with uasyncio is just not going to work, and this patch alone will not fix it (but correct me if I'm wrong). This test code:
it doesn't use the map API correctly: after calling In summary: I don't think there is any bug to fix here (although the fix itself doesn't hurt). |
Sounds like my C example as slightly off. You are correct that you'd need to deref and store My key point is: There is an obvious inconsistency within the
Regarding the compatibility with uasyncio, you'll obviously know better than me. Are you saying that uasyncio is relying on undefined behaviour by checking if the returned element value is micropython/extmod/moduselect.c Lines 54 to 57 in 29e2586
You are correct that there is one other issue remaining with uasyncio with regards to modifying the map while iterating over it. However, I believe that is orthogonal to the inconsistency within the (The iteration issue in |
On a side note, it looks like basically each map consumer throughout the codebase already has this output value (re-)nulling in place (except uselect), which if this PR is applied means it's duplicate code sprinkled throughout the codebase that could be cleaned up to save a few bytes of flash. |
Fix SAMD51 builds on GCC11.2
To adhere to the contract of mp_map_lookup, namely: MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour: - returns slot, with key non-null and value=MP_OBJ_NULL if it was added
e35595c
to
edc92d1
Compare
Revisiting this (with fresh eyes!) I see that it is indeed needed, because the comment for // MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour:
// - returns slot, with key non-null and value=MP_OBJ_NULL if it was added |
Code size report:
|
Discovered this issue due to an intermittent crash when using
moduselect.c
with a series of serial ports that are continually connecting to send short bursts of data and then disconnecting.This change brings the new ordered dictionary implementation in line with other places that re-use slots in maps or dictionaries, including:
micropython/py/map.c
Lines 240 to 241 in 51fd6c9
micropython/py/objdict.c
Lines 339 to 340 in 51fd6c9
micropython/py/map.c
Lines 280 to 281 in 51fd6c9
The specific bug arises when a new item is added using
mp_map_lookup
that is able to occupy an available slot without causing the dictionary to re-allocate.Roughly, the code that causes this issue could be like: