doctest crashes on ESP32 at startup (with workaround) #861
Description
Description
TL;DR: When using doctest with ESP32, either
#define DOCTEST_THREAD_LOCAL
to disable thread local storage,
or, alternatively#define DOCTEST_CONFIG_NO_MULTITHREADING
, which is safer and more efficient if you don't use assertions across multiple threads.
Background
- I'm using doctest with PlatformIO for both native and ESP32 builds. The ESP32 build uses an Arduino-style main, with setup() and empty loop()
- ESP32 has an IPC task for each CPU which is created during startup.
- Before running any code that I can see in the debugger, the ESP32 crashes with this error:
Guru Meditation Error: Core 0 panic'ed (Unhandled debug exception).
Debug exception reason: Stack canary watchpoint triggered (ipc0)
Core 0 register dump:
PC : 0x403799ea PS : 0x00060036 A0 : 0x8037a0e4 A1 : 0x3fcf0aa0
A2 : 0x3fc8e2c4 A3 : 0xffffffff A4 : 0x00060023 A5 : 0xb33fffff
A6 : 0x00000000 A7 : 0x00060023 A8 : 0x80379add A9 : 0x3fc8f320
While the ESP-IDF supports thread-local storage, using the C++11 thread_local
, they come at the cost of increasing the stack usage of all tasks in the system, regardless of whether they use the thread-local variable nor not.
In this case, the thread-locals used by doctest are enough to blow up the stack of the ipc tasks, which have a 4K stack by default.
One possible solution would be to increase the stack size of all tasks to accommodate the thread locals. If you are targeting IDF directly, this could be a workable solution. However, I'm using PlatformIO, and presently it's not possible to reconfigure ESP-IDF at that level, since the IDF is a pre-compiled, and hence a pre-configured library wherein stack sizes for the system tasks are fixed.
Disabling thread local storage, or disabling multithreading in doctest, using the #define
s above are the workarounds I found.
This wasn't an easy find :-). I hope this is of use to anyone else using doctest on an architecture that allocates thread locals on the stack of each thread.