Repository navigation
Conversation
|
I decided to include a patch to resolve #3843 as well. Open to ideas on ways to improve this, possibly with less code? |
|
Also kind of related is #3478. |
One option is to refactor parsing and loading of .mpy files so they don't raise exceptions, but instead return error codes. But this is difficult because this code relies on some object constructors (eg makeing new strings, ints, floats, complex's) and all these constructors would need an alternative version that didn't raise an exception. |
|
We are somehow going to need to add tests that test the invalid-mpy parts of the code. |
Added in 6d8816f |
|
There's a well-known pattern of handling exceptions - at the "top level" (instead of many intermediate levels), and that's what MicroPython follows pretty much. For example, all calls mp_parse() are already wrapped in nlr_push(), and if something needs to be done about its |
|
Also note that object deallocation in MicroPython is "best effort", not everything is freed/deallocated explicitly, because there's GC, which will take care of that. For handling non-memory resources, like open file descriptors, there's GC finalization support. |
|
I think it's safer to wrap the function with an exception handler, as I've done, but I'm wondering about some other idiom for that code. For example, what if we replace this: with this: I'm not sure what to substitute for the |
|
And for reference, here's the test sequence I was using to validate my fix: And a version for the |
|
@dpgeorge Any thoughts on merging this code? I've held off on it in our MicroPython fork but may need to merge it so we're not leaving files open on a failed import. |
|
@dpgeorge We're planning to ship these changes in an upcoming firmware release. Wondering if it can get some consideration for upstream merge. The Travis failure is just an (expected) increase in code size: |
Well, not just the code size. As was explained above, this also increases the stack usage noticeably, and possibly recursively (explicit analysis of that should be persistent part of this change, i.e. be in the commit messages). And I don't even mention coverage decrease (love "we can do it later" excuse myselef). |
Yes, there's another idiom: #4131 |
…main Merge ble-fixes from 6.0.x to main
|
This is still a problem. Apart from the solution here (which uses a lot of stack), one way to tackle it is to make sure finalisers are used for all streams used by the parser/raw-code-loader, and then do a GC collect after importing (to make sure any non-freed streams are freed by the GC). Alternatively, #4131 would be the best way to go. |
|
I'll close this in favour of #12369, which uses much less C stack space to implement the same thing. Also, the test here doesn't work on Linux (it passes even without the fix provided in this PR). |
Fixes issue micropython#3874. Signed-off-by: Damien George <[email protected]>
Fixes issue micropython#3874. Signed-off-by: Damien George <[email protected]>
Fixes issue micropython#3874. Signed-off-by: Damien George <[email protected]>
The PicoMite tree ran its TinyUSB 0.21 host work on this same hardware - two keyboards (one marginal), a touch panel and a flash drive behind one hub - across software, hardware and power-on resets, and wrote up what actually held (docs/usb-host-hardening). Root cause: the RP2 SIE keeps ONE handshake-result latch shared between EPX and the interrupt-endpoint poller (upstream micropython#3533), so an interrupt poll can overwrite a control transfer's ACK before the IRQ handler reads it, and the transfer is misread as RX_TIMEOUT. The validated answer is to tolerate the race above the silicon, not to adopt the strict micropython#3533 driver rewrite - which enumerated FEWER devices on the marginal rig. Applied here: hcd_rp2040.patch Grace period for EP0 RX timeouts: within a 1 s window the transfer is left armed and the clobbered result outlasted; the window closes on any EP0 completion. Expiry (a genuinely dead device) takes the original fail path, which keeps our buffer clear (micropython#3874). Bulk/interrupt keep the fast-fail: their flow control is NAK, which never raises RX_TIMEOUT. usbh.patch Enumeration-exclusive control dispatch: while a device enumerates, only address 0, the enumerating address and the hub in use may claim the control slot; LED writes and touch handshakes wait in the pending FIFO (gated at the claim, the two drain checks and the dispatcher, by peeking the head). And a failed enumeration now disables its hub port (CLEAR_FEATURE(PORT_ENABLE), async no-op callback) - 0.21 left the abandoned device enabled at address 0, where it answers in parallel with the next device's bring-up. The 100 ms reset recovery (micropython#3876) stays. mp_usbh.c Mount-callback prints deferred: the callbacks now usb_msc.c format into a small static ring and mp_usbh_task() prints it after tuh_task() returns. A print in the callback runs the VM via dupterm mid-enumeration - the measured cost of "one connect chime" on the PicoMite rig was the marginal device. The existing reentrancy guard treated the symptom; this removes the stall itself. tusb_config.h CFG_TUH_CONTROL_PENDING_QUEUE_SZ 4 -> 8: the gate parks more traffic in the FIFO during enumeration. Not adopted, by the doc's own measurement: the micropython#3533 reference hcd (fewer devices on marginal hardware; revisit when merged upstream). Already carried, now cross-validated: MULTI_HUB_FIX and the 64-entry event queue. Builds clean; the board leg - all reset kinds, hot attach, MSC beside HID, pulling the marginal device - is owed before this is believed. Co-Authored-By: Claude Fable 5 <[email protected]>
Fixes issue micropython#3874. Signed-off-by: Damien George <[email protected]>
Somewhat related to #3843. If we run into an error trying to
importa module stored as a.mpyfile, we never callreader->close()to release the open file handle.This PR adds exception handling to
mp_raw_code_load()and has it close the reader before re-throwing the exception.