Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpp: Exception handling undefined #17523

Open
jenswet opened this issue Jan 17, 2022 · 3 comments
Open

cpp: Exception handling undefined #17523

jenswet opened this issue Jan 17, 2022 · 3 comments
Labels
Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Comments

@jenswet
Copy link
Contributor

jenswet commented Jan 17, 2022

Description

The exception handling is undefined in RIOT.

Some modules and unit tests use exceptions, e.g. the riot::thread implementation from the cpp11_compat module and the according unit test.

Steps to reproduce the issue

I've created a unit test to demonstrate the current undefined behavior: jenswet@7940cbe

Expected results

All boards should give the following result:

************ C++ exception test ***********
Exceptions enabled
Exception catched
******************************************

Actual results

The native board does as expected:

RIOT native board initialized.
RIOT native hardware initialization complete.

Help: Press s to start test, r to print it is ready
READY
s
START
main(): This is RIOT! (Version: 2022.04-devel-20-g95b50-cpp-exception)

************ C++ exception test ***********
Exceptions enabled
Exception catched
******************************************

The nucleo-f767zi does the following (with both gnu and llvm toolchain):

main(): This is RIOT! (Version: 2022.04-devel-20-g95b50-cpp-exception)

************ C++ exception test ***********
Exceptions enabled
#! exit 1: powering off

With the default compiler flags there is no -fno-exceotions.

When adding -fno-exceotions manually and therefore disabling exceptions the test wouldn't even compile:

tests/cpp_exception/main.cpp:26:6: error: '__EXCEPTIONS' was not declared in this scope
   26 |   if(__EXCEPTIONS) {
      |      ^~~~~~~~~~~~
tests/cpp_exception/main.cpp:38:43: error: exception handling disabled, use '-fexceptions' to enable
   38 |       throw std::runtime_error("Exception");
      |                                           ^
tests/cpp_exception/main.cpp:41:30: error: 'e' was not declared in this scope
   41 |       printf("%s catched\n", e.what());
      |                              ^

Exact the same behavior can be verified on esp32-wroom-32:

************ C++ exception test ***********
Exceptions enabled
#! exit 1: powering off

The devices are powered off instead of catching the exception.

Arduino has defined behabior, when trying to compile code that uses exceptions an error occurs error: exception handling disabled, use -fexceptions to enable.

I didn't try the other platforms because of missing hardware.

I don't want to discuss whether exceptions are useful for embedded development or not. But the behavior should be consistent. Either they should work or they should be disabled. When they do not work, they should not be used in any module imho.

Versions

It doesn't matter whether I build locally:

Operating System Environment
----------------------------
         Operating System: macOS 11.6.2
                   Kernel: Darwin 20.6.0 x86_64 i386
./dist/tools/ci/print_toolchain_versions.sh: line 78: realpath: command not found
             System shell:  (probably dash)
             make's shell: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)

Installed compiler toolchains
-----------------------------
               native gcc: gcc (Homebrew GCC 10.2.0_4) 10.2.0
        arm-none-eabi-gcc: arm-none-eabi-gcc (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)
                  avr-gcc: avr-gcc (Homebrew AVR GCC 9.3.0_3) 9.3.0
         mips-mti-elf-gcc: missing
           msp430-elf-gcc: missing
       riscv-none-elf-gcc: missing
  riscv64-unknown-elf-gcc: missing
     riscv-none-embed-gcc: missing
     xtensa-esp32-elf-gcc: xtensa-esp32-elf-gcc (crosstool-NG crosstool-ng-1.22.0-61-gab8375a) 5.2.0
   xtensa-esp8266-elf-gcc: missing
                    clang: Apple clang version 13.0.0 (clang-1300.0.29.30)

Installed compiler libs
-----------------------
     arm-none-eabi-newlib: "3.3.0"
      mips-mti-elf-newlib: missing
        msp430-elf-newlib: missing
    riscv-none-elf-newlib: missing
riscv64-unknown-elf-newlib: missing
  riscv-none-embed-newlib: missing
  xtensa-esp32-elf-newlib: "2.2.0"
xtensa-esp8266-elf-newlib: missing
                 avr-libc: "2.0.0" ("20150208")

Installed development tools
---------------------------
                   ccache: missing
                    cmake: cmake version 3.21.0
                 cppcheck: missing
                  doxygen: 1.9.1
                      git: git version 2.32.0 (Apple Git-132)
                     make: GNU Make 4.3
                  openocd: Open On-Chip Debugger 0.10.0+dev-01514-ga8edbd020-dirty (2020-11-30-10:23)
                   python: Python 2.7.16
                  python2: Python 2.7.16
                  python3: Python 3.9.7
                   flake8: error: /usr/local/opt/python@3.9/bin/python3.9: No module named flake8
               coccinelle: missing

or with the latest riot/riotbuild.

@jenswet
Copy link
Contributor Author

jenswet commented Jan 17, 2022

@maribu As we discussed I tried to build with the llvm toolchain, but it didn't change anything.

@maribu
Copy link
Member

maribu commented Jan 17, 2022

At least for Alpine, linking against the nano variant of libstdc++ results in no exceptions being supported:

https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/community/gcc-cross-embedded/APKBUILD#L114-120

And indeed,

$ DISABLE_MODULE=newlib_nano BOARD=nucleo-f767zi make -C tests/cpp_exception flash test
[...]
  text	   data	    bss	    dec	    hex	filename
  70312	   2512	   2488	  75312	  12630	/home/maribu/Repos/software/RIOT/tests/cpp_exception/bin/nucleo-f767zi/tests_cpp_exception.elf
[...]
Help: Press s to start test, r to print it is ready
START
main(): This is RIOT! (Version: 2022.01-devel-1612-gf7dd0-tests/cpp11_exceptions)

************ C++ exception test ***********
Exceptions enabled
Exception catched
******************************************

I'm pulling the current version of riot/riotbuild to confirm this behavior for non-Alpine systems. But it looks like -fno-exceptions has to be added when using newlib_nano.

It would also be sensible to prominently document that adding DISABLE_MODULE += newlib_nano would enable exceptions. It is also worth pointing out that the non-nano variant buys in a lot of unrelated bloat (such as even more insanely bloated stdio than for newlib_nano) that likely nobody wants. I think most C++ developers would profit from a nano but with exceptions version of newlib.

@maribu
Copy link
Member

maribu commented Jan 17, 2022

OK, with riot/riotbuild there are no exceptions even with DISABLE_MODULE=newlib_nano. Would be nice to know if the Arch Linux toolchain is similar to Alpine in this regard.

I was also trying to give picolibc a try, but that doesn't seem to work at all with C++. (Generally speaking, picolibc is the better and more active C lib and RIOT is very likely to switch there, when the remaining issues are solved. That might also be chance to get C++ support right even without buying in bloat.)

@maribu maribu added the Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) label May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

No branches or pull requests

2 participants