← index #10898PR #15991
Related · medium · value 1.558
QUERY · ISSUE

Interrupting soft reset (Ctrl-D) with Ctrl-C erases filesystem on Raspberry Pi Pico

openby connorclopened 2023-03-01updated 2023-03-01
bug

Sending a Ctrl-D to the MicroPython REPL to initiate a soft reset and then immediately issuing a Ctrl-C causes the entire filesystem to be erased on the Raspberry Pi Pico board. This issue was observed on 2 separate Pico boards across the following nightly builds (the 4 latest as of 01 March 2023):

However, the bug was not observed in the latest stable version 1.19.1.

Steps to reproduce

These steps were tested on a Linux host (Ubuntu 22.04).

First, load one of the above nightly versions of MicroPython onto a Raspberry Pi Pico board.

Next, using mpremote, install a library on the Pico’s filesystem, for example hashlib:

mpremote mip install hashlib

Then check that the library exists on the Pico’s filesystem:

mpremote fs ls /lib

This should show the hashlib folder:

ls :/lib
           0 hashlib/

Then, to send the required keystrokes (Ctrl-D followed by Ctrl-C), execute the following lines of Python on the Linux host machine to which the Pico is connected, replacing /dev/ttyACM0 with the serial port of the MicroPython REPL. This script requires pyserial.

import serial
s = serial.Serial('/dev/ttyACM0')
s.write(b'\x04') # Ctrl-D
s.write(b'\x03') # Ctrl-C
s.close()

Less precisely, the issue can also be reproduced by entering a REPL with mpremote and pressing Ctrl-D and Ctrl-C in rapid succession.

Then check the Pico’s filesystem once again:

mpremote fs ls

This should show that the lib folder and all files it contains have been removed:

ls :

This issue became evident because the visual studio code extension Pico-W-Go exhibits this behaviour when running a MicroPython file, issuing a Ctrl-D and Ctrl-C in rapid succession before running the given code. This issue has been reported on that project’s GitHub page here, suggesting it affects other nightly versions older than the 4 listed above.

CANDIDATE · PULL REQUEST

tools: Only issue a single Ctrl-C when entering raw REPL.

mergedby dpgeorgeopened 2024-10-10updated 2024-10-15
tools

Summary

A long time ago when there was only the stm port, Ctrl-C would trigger a preemptive NLR jump to break out of running code. Then in commit 124df6f8d07b53542b6960dbeea9b63bff469a67 a more general approach to asynchronous KeyboardInterrupt exceptions was implemented, and stmhal supported both approaches, with the general (soft) interrupt taking priority.

Then in commit bc1488a05f509cd5be8bfab9574babfcb993806f pyboard.py was updated with a corresponding change to make it issue a double Ctrl-C to break out of any existing code when entering the raw REPL (two Ctrl-C characters were sent in order to more reliably trigger the preemptive NLR jump).

No other port has preemptive NLR jumps and so a double Ctrl-C doesn't really behave any differently to a single Ctrl-C: with USB CDC the double Ctrl-C would most likely be in the same USB packet and so processed in the same low-level USB callback, so it's just setting the keyboard interrupt flag twice in a row. The VM/runtime then just sees one keyboard interrupt and acts as though only one Ctrl-C was sent.

This commit changes the double Ctrl-C to a single Ctrl-C in pyboard.py and mpremote. That keeps things as simple as they need to be.

Testing

Ran the test suite on a PYBD-SF2 and ESP32_GENERIC board. It passes.

Also ran the mpremote tests on the same hardware. They also pass.

Trade-offs and Alternatives

There's a slight risk this may change behaviour of some code which expects two Ctrl-C's, but that's unlikely because in the vast majority of cases two back-to-back Ctrl-C's will just end up being one KeyboardInterrupt, ie equivalent to a single Ctrl-C (especially due to #15988 that preemptive NLR jump is removed).

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied