Skip to content

Commit 1f2ec45

Browse files
committed
extmod/os_dupterm: Prevent recursive execution of mp_os_dupterm_rx_chr.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 395886c commit 1f2ec45

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

extmod/os_dupterm.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags) {
9494
}
9595

9696
int mp_os_dupterm_rx_chr(void) {
97+
#if MICROPY_PY_OS_DUPTERM_NOTIFY
98+
// When os.dupterm_notify() is enabled it is usually called from a scheduled
99+
// function, via mp_os_dupterm_notify(). That can lead to recursive calls of
100+
// this function when this function is called from mp_hal_stdin_rx_chr():
101+
// - mp_hal_stdin_rx_chr()
102+
// - mp_os_dupterm_rx_chr()
103+
// - <Python code>
104+
// - os.dupterm_notify() is scheduled via interrupt/event
105+
// - <Python code> runs scheduled code (eg WebREPL -> rp2.Flash().writeblocks())
106+
// - mp_os_dupterm_notify()
107+
// - mp_os_dupterm_rx_chr()
108+
// Break that cycle by locking the scheduler during this function's duration.
109+
mp_sched_lock();
110+
#endif
111+
112+
int ret = -1; // no chars available
97113
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
98114
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
99115
continue;
@@ -106,7 +122,8 @@ int mp_os_dupterm_rx_chr(void) {
106122
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
107123
mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
108124
if (errcode == 0 && out_sz != 0) {
109-
return buf[0];
125+
ret = buf[0];
126+
break;
110127
} else {
111128
continue;
112129
}
@@ -132,20 +149,24 @@ int mp_os_dupterm_rx_chr(void) {
132149
} else {
133150
// read 1 byte
134151
nlr_pop();
135-
if (buf[0] == mp_interrupt_char) {
152+
ret = buf[0];
153+
if (ret == mp_interrupt_char) {
136154
// Signal keyboard interrupt to be raised as soon as the VM resumes
137155
mp_sched_keyboard_interrupt();
138-
return -2;
156+
ret = -2;
139157
}
140-
return buf[0];
158+
break;
141159
}
142160
} else {
143161
mp_os_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
144162
}
145163
}
146164

147-
// No chars available
148-
return -1;
165+
#if MICROPY_PY_OS_DUPTERM_NOTIFY
166+
mp_sched_unlock();
167+
#endif
168+
169+
return ret;
149170
}
150171

151172
void mp_os_dupterm_tx_strn(const char *str, size_t len) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy