-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[tracking] fixing stdio #20361
Comments
|
ContextIt seems that #20067 was only the tip of the iceberg. Even after stdio initialization done, there can still be races in newlib that can corrupt memory and, therefore, cause "interesting surprises" at runtime (e.g. the hardfault I observed in #19926 (comment)). The Issue
Possible SolutionsImplement Reentrancy in NewlibThe most straight forward implementation would be to just implement the locking interface newlib requires for reentrancy. This has some downsides, though:
Use a Non-Blocking and Thread-Safe
|
As I understood, that was always the guidance, accompanied by "if you know very precisely what your building blocks are, it may still work", which is a caveat people chose to ignore. |
I am aware. I would be in favour to forbid use of stdio from IRQ outright. Maybe we now have a critical mass of people to push for that again, though. |
So far there was always someone who said that "yeah but it works in my cases"; IIRC from the semantics and fixes PR, last time that was @benpicco. As I understand this issue, here it's not even about RIOT's stdio (stdio_write etc) having weird properties, but on top of that, the C library functions have non-reentrancy that makes things worse even if the individual stdio impl is good. So maybe we should clarify whether we talk about libc provided functions (printf etc) or RIOT provided functions (stdio_write) in this issue here. Then we're in a better situation to decide whether those cases are relevant for this issue. |
Also @kaspar030 was "over my dead body" regarding no stdio from IRQ context. But I think he may no longer care.
We should, but we also need to keep both in mind. E.g. newlib can provide reentrancy (and will work fine with that - at the cost of higher latency and higher memory consumption). But without reentrancy, newlib's stdio is racy and will occasionally crash. On the other hand I think it would absolute be possible to write C lib stdio ( |
I still think we don't need to worry about stdio too much. |
I agree that stdio is mostly a debug tool. Still, random crashes due to stdio is a pita. (Admittedly, the chance of a crash due to a race is low, but it is still something we need to fix. And there are firmwares that get the timing just right for a reliable crash on startup.) |
It may be a debug tool, but it's also one of the earliest things people are introduced to with RIOT; judging from the various telnet-ish and Bluetooth-ish transports that are around, apparently the shell is pretty widely used. (And race conditions are not something we should have in our code base) |
It is also not only newlib's stdio that is not thread-safe, but also avrlibc's. E.g. int
printf_P(const char *fmt, ...)
{
va_list ap;
int i;
va_start(ap, fmt);
stdout->flags |= __SPGM;
i = vfprintf(stdout, fmt, ap);
stdout->flags &= ~__SPGM;
va_end(ap);
return i;
} So when thread A is doing I now imagine in thousand of years archeologists debating the reasoning behind the design choice to set a flag in a |
From the matrix: "stdio in RIOT is a hot mess". So let's fix this. This lists the tasks needed for sane stdio
CONFIG_SKIP_BOOT_MSG
makes newlib stdio races more likely #20067stdio_uart
stdio_semihosting
stdio_rtt
stdio_cdc_acm
stdio_nimble
stdio_udp
stdio_telnet
stdio_usb_serial_jtag
stdio_native
stdio_ethos
slipdev_stdio
The text was updated successfully, but these errors were encountered: