-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
CircuitPython version and board name
Adafruit CircuitPython 10.0.3 on 2025-10-17; FeatherS3 with ESP32S3Code/REPL
import time
import supervisor
i=0
while True:
i += 1
print(f"[{time.monotonic_ns()}] [{supervisor.runtime.serial_connected}] {i}...")
time.sleep(0.1)Behavior
This code will run just fine on a fresh start. However, once a serial console has been connected (supervisor.runtime.serial_connected becomes True), even after that console disconnects, print() will become blocking any time the output buffer is full. This will be evidenced by, upon reconnection of the console, multiple older messages filling the screen, and then a large jump in the outputted time.monotonic_ns() as the program execution resumes. You will also note that the outputs that occurred while the console was disconnected still indicate that supervisor.runtime.serial_connected is True.
Description
I suspect this is the true root cause of #9150, and possibly #10500. I've been able to reproduce it with minicom, screen, and even cat as serial consoles.
My workaround is to create a ring buffer, but that's a lot of heavy lifting to paper over the fact that serial_connected apparently never changes back to False.
Additional information
In case anyone wants my ring buffer code; it's not the prettiest, but it works, and allows easy toggling in and out of ring mode; press CTRL-C once to toggle, and optionally quickly press CTRL-C again to fully exit.
_ring_drops: int = 0
_ring: list[tuple] = []
def ring_print(fmt: str, *args) -> None:
global _ring
global _ring_drops
if len(_ring) > RING_SIZE:
_ring.pop(0)
_ring_drops += 1
_ring.append((fmt, args))
# Monkeypatch print()
print("Patching print(); use ^C to see output.")
_orig_print = print
print = ring_print
while True: # Core kernel
try:
# <... do stuff...>
except KeyboardInterrupt as e:
_out = ""
_orig_print(f"\033[2m[{time.time()}] Got keyboard interrupt at:")
traceback.print_exception(e) # So we know what our CTRL-C interrupted
_orig_print("\033[0;0m", end="")
if print is ring_print:
if _ring_drops:
_orig_print(f"<... dropped {_ring_drops} messages ...>")
for fmt, args in _ring:
_orig_print(fmt, *args)
_ring = []
_ring_drops = 0
_out = f"\033[2m[{time.time()}] Switching to live output; press CTRL-C to toggle back to ring.\033[0;0m"
print = _orig_print
else:
_out = f"\033[2m[{time.time()}] Switching to ring-buffered output; press CTRL-C to toggle back to live.\033[0;0m"
print = ring_print
time.sleep(0.5) # hit CTRL-C again and you'll exit the loop.
_orig_print(_out)