Change to `mp_handle_pending' includes possible MICROPY_EVENT_POLL_HOOK and downstream code breakage
Port, board and/or hardware
all
MicroPython version
1.27+
Reproduction
For long-running processes handled by user C modules (eg: busy wait on e-ink update) I've been using the pattern:
extern void mp_handle_pending_internal(bool);
mp_handle_pending(true);
I tried to build against 1.27 today, and ran into this build error:
modules/c/ssd1680/ssd1680.cpp.o: in function `pimoroni::SSD1680::busy_wait()':
modules/c/ssd1680/ssd1680.cpp:54:(.text._ZN8pimoroni7SSD16809busy_waitEv+0x10): undefined reference to `mp_handle_pending'
This looks like it was introduced by https://github.com/micropython/micropython/commit/c57aebf790c40125b663231ec4307d2a3f3cf193
This PR seems to make the assumption that mp_handle_pending is only ever called inline in runtime.h, or in code that uses:
#include "runtime.h"
mp_handle_pending(true);
This assumption doesn't seem to hold true, for example the same "undefined reference" error should occur if an attempt is made to call "MICROPY_EVENT_POLL_HOOK" from Zephyr code:
https://github.com/micropython/micropython/blob/26c16969ab954db4d8d79bed154e3d45c12c087f/ports/zephyr/mpconfigport.h#L171-L172
But I guess runtime.h is implicitly available here? In any case making the "extern" line redundant and this pattern should probably be updated where it occurs.
Either way the inline wrapper to preserve the old mp_handle_pending behaviour does not cover all possible cases, causing a break in my code from 1.26 to 1.27.
I expect breakage, though, so I'd propose the implicit "example" uses in the MicroPython codebase (there are a few things like "MICROPY_EVENT_POLL_HOOK") are updated and this issue should, with any luck, steer any future encounters (I'll probably forget and run into this again) toward the correct usage.
Expected behaviour
Observed behaviour
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree
py: clean up definition and use of `mp_handle_pending()`
Summary
Commit c57aebf790c40125b663231ec4307d2a3f3cf193 added more functionality to mp_handle_pending(), passing in an enum instead of a bool to select whether exceptions are ignored, cleared or raised.
That commit attempted to keep the original behaviour of mp_handle_pending(bool) with a bool argument by making it static-inline, but that doesn't work in all cases (see #18663).
This PR cleans up the definition and use of this function:
- remove incorrect and unnecessary declarations of
extern void mp_handle_pending(bool);inmpconfigport.h - reorder enum so their numerical values match the original bool argument, namely that
truemaps toMP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONSandfalsemaps toMP_HANDLE_PENDING_CALLBACKS_AND_CLEAR_EXCEPTIONS - remove the static-inline definition
- rename
mp_handle_pending_internal()tomp_handle_pending()
Functionality should be unchanged, and backwards compatibility with mp_handle_pending() should be retained.
Fixes issue #18663.
Testing
Tested locally on PYBV10.
CI will also test the change (the unix port already has special coverage testing for mp_handle_pending()).
Trade-offs and Alternatives
This touches all code that calls mp_handle_pending() but that's necessary to fully clean it up.
The enum for mp_handle_pending_behaviour_t now defines the first and second values as false and true, which is a bit awkward but will explicitly retain backwards compatibility.