From 0b75e180a3b9fe72681fb942873102cdf2f4cae1 Mon Sep 17 00:00:00 2001 From: Alessandro Gatti Date: Sat, 10 Aug 2024 16:37:03 +0200 Subject: [PATCH] esp32/mphalport: Print debug strings even before the GIL is ready. If verbose debugging is enabled there is some stdout output happening before the GIL is ready (for example, GC initialisation), and the code assumed that no string printing occurred before the interpreter was fully initialised. Printing long strings would operate without holding the GIL, which would crash if string output would happen too early in the startup process. This commit addresses that issue, making sure verbose debugging output will work even before the interpreter is fully initialised (as if it is not yet ready there's no GIL to take care of). Also, the threshold that would indicate whether a string is "long" (and thus requiring a GIL release/lock operation) or not was hardcoded to 20 bytes. This commit makes that configurable, maintaining 20 bytes as a default. Fixes issue #15408. Signed-off-by: Alessandro Gatti --- ports/esp32/mpconfigport.h | 5 +++++ ports/esp32/mphalport.c | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 40b3f11b4..866b1bc25 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -314,3 +314,8 @@ void boardctrl_startup(void); #endif #endif #endif + +// The minimum string length threshold for string printing to stdout operations to be GIL-aware. +#ifndef MICROPY_PY_STRING_TX_GIL_THRESHOLD +#define MICROPY_PY_STRING_TX_GIL_THRESHOLD (20) +#endif diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index df966b3a2..cc0e2ee7b 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -47,6 +47,10 @@ #include "usb_serial_jtag.h" #include "uart.h" +#if MICROPY_PY_STRING_TX_GIL_THRESHOLD < 0 +#error "MICROPY_PY_STRING_TX_GIL_THRESHOLD must be positive" +#endif + TaskHandle_t mp_main_task_handle; static uint8_t stdin_ringbuf_array[260]; @@ -129,7 +133,13 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { // Only release the GIL if many characters are being sent mp_uint_t ret = len; bool did_write = false; - bool release_gil = len > 20; + bool release_gil = len > MICROPY_PY_STRING_TX_GIL_THRESHOLD; + #if MICROPY_DEBUG_PRINTERS && MICROPY_DEBUG_VERBOSE && MICROPY_PY_THREAD_GIL + // If verbose debug output is enabled some strings are printed before the + // GIL mutex is set up. When that happens, no Python code is running and + // therefore the interpreter doesn't care about the GIL not being ready. + release_gil = release_gil && (MP_STATE_VM(gil_mutex).handle != NULL); + #endif if (release_gil) { MP_THREAD_GIL_EXIT(); }