8000 "FATAL: uncaught exception" on KeyboardInterrupt during large printout at normal REPL · Issue #4921 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

"FATAL: uncaught exception" on KeyboardInterrupt during large printout at normal REPL #4921

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

Closed
mikewadsten opened this issue Jul 12, 2019 · 4 comments
Labels

Comments

@mikewadsten
Copy link
Contributor
mikewadsten commented Jul 12, 2019

This is a bug that I originally found in our own commercial product running a fork of MicroPython, but I have since reproduced on the mainline STM32 port as well.

At the friendly REPL, if you enter an expression such as "a" * 10000 and then very quickly hit Ctrl-C, MicroPython will crash with "FATAL: uncaught exception <pointer>", where <pointer> corresponds to mp_state_ctx.vm.mp_kbd_exception.

I am able to reproduce this with both the v1.10 and v1.11 branches, including the current master (154062d). For v1.11 reproduction, I am using an STM32F415ZG based dev board internal to our company (compiled on a branch whose only changes are board-specific, no core tweaks). My other reproduction is on our Silicon Labs EFM32 based product. The fact that I can reproduce on STM32 tells me the bug is not specific to our product.

I am not able to reproduce on v1.9, at least where I've tested (including a microbit).

From my own analysis of the "uncaught exception" message, I believe the cause of the crash is that the REPL runs parse_compile_execute to execute the given expression, which sees the KeyboardInterrupt being raised, restores context, and re-raises -- but there's no surrounding nlr_push at the REPL, so nlr_jump_fail ends up being called.

@dpgeorge
Copy link
Member

Thanks for the report.

there's no surrounding nlr_push at the REPL, so nlr_jump_fail ends up being called.

Yes that's pretty much it. In detail it looks like the following is happening:

  1. In lib/utils/pyexec.c:parse_compile_execute, the call to mp_call_function_0() executes the code and it takes a while to execute (print the large string), and ctrl-C comes in during this execution.
  2. The VM does not check for the pending ctrl-C because the print of the string was the last thing it needed to do and it returns with an exception still pending.
  3. Back in parse_compile_execute, mp_hal_set_interrupt_char(-1) is called to disable interrupts but there's still the KeyboardInterrupt pending.
  4. When the REPL resumes and calls mp_hal_stdin_rx_chr() this function checks for pending exceptions and raises it.
  5. There is no surrounding NLR handler so the exception is uncaught.

The problem exists for all ports that use pyexec.c (bug confirmed also on esp32).

Note that it's not enough to fix point (2) and make the VM always check for pending exceptions on return, because there's always the chance an exception comes in betwee the VM returning and execution of mp_hal_set_interrupt_char(-1).

One option to fix it is to make mp_hal_set_interrupt_char(-1) also cancel/clear any pending exceptions. That would mean such exceptions are lost. The other option is to make the REPL loop check explicitly for pending exceptions and have code to deal with them (for a KeyboardInterrupt basically just do nothing).

@dpgeorge
Copy link
Member

See related #1667, #1722, #1738

@dpgeorge
Copy link
Member

One option to fix it is to make mp_hal_set_interrupt_char(-1) also cancel/clear any pending exceptions.

A variation on this would be for this function to first set the interrupt char to -1 (to stop any more incoming events), then if there is a pending exception raise it.

@dpgeorge dpgeorge added the bug label Jul 15, 2019
dpgeorge added a commit to dpgeorge/micropython that referenced this issue Jan 30, 2020
Pending exceptions would otherwise be handled later on where there may not
be an NLR handler in place.

Fixes issues micropython#4921 and micropython#5488.
dpgeorge added a commit to dpgeorge/micropython that referenced this issue Feb 5, 2020
Pending exceptions would otherwise be handled later on where there may not
be an NLR handler in place.

A similar fix is also made to the unix port's REPL handler.

Fixes issues micropython#4921 and micropython#5488.
dpgeorge added a commit to dpgeorge/micropython that referenced this issue Feb 7, 2020
Pending exceptions would otherwise be handled later on where there may not
be an NLR handler in place.

A similar fix is also made to the unix port's REPL handler.

Fixes issues micropython#4921 and micropython#5488.
@dpgeorge
Copy link
Member
dpgeorge commented Feb 7, 2020

Fixed by 5a91cd9

@dpgeorge dpgeorge closed this as completed Feb 7, 2020
alu96 pushed a commit to alu96/micropython that referenced this issue Mar 23, 2020
Pending exceptions would otherwise be handled later on where there may not
be an NLR handler in place.

A similar fix is also made to the unix port's REPL handler.

Fixes issues micropython#4921 and micropython#5488.
c0d3z3r0 pushed a commit to c0d3z3r0/micropython that referenced this issue Apr 5, 2020
Pending exceptions would otherwise be handled later on where there may not
be an NLR handler in place.

A similar fix is also made to the unix port's REPL handler.

Fixes issues micropython#4921 and micropython#5488.

Change-Id: I258443be7c6b7368bf7fb50b507d5e18b9d9bd5a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
38E8
None yet
Development

No branches or pull requests

2 participants
0