Repository navigation
Runtime: reference counts from callback reads and __cast_instance__; buffers stay exported for the LVGL call - #35
Merged
Conversation
…ffers stay exported for the LVGL call - Reading a callback back from a struct field (drv.open_cb) returned the callback dict's borrowed reference as a new one, so every read dropped the callback's reference count by one until it was freed. - A buffer passed as a void * (obj.send_event(code, buf)) was released before LVGL used the pointer, so Python code run during the call could resize it under LVGL. The export now lasts until the outermost LVGL call returns. - __cast_instance__ returned self without a reference, and a struct that owned its memory freed it twice once cast onto another struct's.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three reference bugs in
src/lvpy_runtime.c, on every Python build.Reading a callback back from a struct (
drv.open_cb,font.get_glyph_dsc, any callback field) returned the callback dict's borrowed reference as if it were new. Each read dropped the callback's reference count by one, so a few reads freed a callback that LVGL still calls.mp_lv_funcptrnow returns a reference of its own, andNonewhen the dict has no entry (it returned NULL with no exception set).A buffer passed where LVGL takes a
void *(obj.send_event(code, buf), auser_data, adst) was released before LVGL used the pointer. Python code run during the call, such as an event callback, could then resize abytearrayand leave LVGL reading freed memory. The buffer now stays exported until the outermost LVGL call returns, so resizing it during the call raisesBufferErrorand works again afterwards. A non-contiguous buffer is refused withBufferErrorrather than passed through.__cast_instance__returnedselfwithout a reference, and a struct that owned its memory freed it twice after being cast onto another struct's. It now lets go of its own memory and returns a new reference.tests/test_runtime_references.pychecks all three in a subprocess underMALLOC_PERTURB_. On the code before this change it fails three ways: the callback's count drops by 4 over 4 reads, the bytearray resizes mid-call, and__cast_instance__aborts with a double free. With the fix reverted by hand on this branch (a planted fault, since undone), the same three tests fail; with the fix, the full suite passes (28 tests).