thread_local not supported; unsafe to use c++ exceptions in multi-core setting
@kilograham is already working on this.
Since Mar 31, 2021.
Assessment
This issue has not been assessed yet.
Description
pico-sdk doesn't support thread-local storage (thread_local keyword), which is required for c++ exceptions to function properly in a multi-core environment. Internally libstdc++ stores some global exception state in a thread_local variable (static __thread abi::__cxa_eh_globals global; in eh_globals.cc).
If now both RP2040 cores throw or catch exceptions at the same time they are "mixed", because the thread_local state variable is the exact same variable on both cores. There are also no synchronization locks, so both cores can write to the same variable at the same time.
The code below shows how core0's std::current_exception() is overwritten by core1. The expected output is:
[core0] core0 exception
[core1] core1 exception
[core0] core0 exception
[core1] core1 exception
The actual output is:
[core0] core0 exception
[core1] core1 exception
[core0] core1 exception
[core1] core1 exception
#include <cstdio>
#include <stdexcept>
#include <pico/multicore.h>
#include <pico/stdio_usb.h>
void continue_with_other_core(semaphore_t& acquire, semaphore_t& release)
{
sem_release(&release);
sem_acquire_blocking(&acquire);
}
void print_current_exception()
{
try {
std::rethrow_exception(std::current_exception());
}
catch (const std::exception& e) {
std::printf("[core%d] %s\n", get_core_num(), e.what());
}
}
void run_test(semaphore_t& acquire, semaphore_t& release)
{
try {
sem_acquire_blocking(&acquire);
throw std::runtime_error("core" + std::to_string(get_core_num()) + " exception");
}
catch (...) {
print_current_exception();
continue_with_other_core(acquire, release);
print_current_exception();
continue_with_other_core(acquire, release);
}
}
int main()
{
stdio_usb_init();
std::getchar();
std::puts("[start]");
static semaphore_t sem0, sem1;
sem_init(&sem0, 1, 1); // unlocked: start with core0
sem_init(&sem1, 0, 1);
multicore_launch_core1([] { run_test(sem1, sem0); });
run_test(sem0, sem1);
for (;;);
}
- Dominant language
- C
- Stars
- 5k
- Forks
- 1.3k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 17
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from raspberrypi/pico-sdk
-
hardware_pio
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
raspberrypi/pico-sdk#3193 ·
-
pioasm
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
raspberrypi/pico-sdk#3189 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
raspberrypi/pico-sdk#3183 ·
-
c++
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
raspberrypi/pico-sdk#3181 · 3 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
raspberrypi/pico-sdk#3167 ·
All issues in raspberrypi/pico-sdk
Similar issues
-
[adam] AdamNet network read doesn't cap to MAX_ADAM_PACKET_LEN, overflows client receive buffers Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
FujiNetWIFI/fujinet-firmware#1649 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
HarbourMasters/Shipwright#7229 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
riscv-software-src/riscv-isa-sim#2435 · 1 comment ·
-
bug Self Built Image SNAPSHOT Supported Device target/ramips
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100