-
Notifications
You must be signed in to change notification settings - Fork 2.1k
sys/newlib_syscalls_default: fix race condition in __sinit() #20392
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
Conversation
@mchesser: Could you give this a try? I'm aware that it still is a pain in the ass that RIOT doesn't support (at least optional) reentrancy for platforms other than ESP. That is in issue that stills needs to be addressed. However, even people desperate for saving RAM don't like crashes, and this hopefully makes the concurrent use of stdio crash-free. |
This eagerly calls `__sinit()` instead of lazy initialization upon the first call to stdio (e.g. `puts()`, `printf()`). The issue is that without locking (as is currently the case for all RIOT platforms but ESP) two concurrent "first calls" may result in concurrent initialization of the same structure and data corruption. Fixes RIOT-OS#20067
ea98597
to
375aed1
Compare
/* Also, make an exception for riotboot, which does not use stdio | ||
* at all. This would pull in stdio and increase .text size | ||
* significantly there */ | ||
if (!IS_USED(MODULE_RIOTBOOT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was under the impression that riotboot would already do
DISBALE_MODULE += core_thread
but apparently not. That would save us some special casing in other places too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you open a PR to just do that? I could wait and rebase on top of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
riotboot_dfu
uses a thread (and thread flags), so might not be so easy.
But how about
if (!IS_USED(MODULE_RIOTBOOT)) { | |
if (!IS_USED(MODULE_STDIO_NULL)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly that would not work: stdio_null
just throws away the output after it has gone the whole way through newlib. So there is no way for newlib to know whether the output is actually printed or just thrown away.
It would be possible to implement stdio_null
to wrap all calls to printf()
and friends to a mockup implementation. (And if we assume that callers of printf()
don't care about the return value, those could be lean.) But as of know, we still need to init that with stdio_null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like hard-coding riotboot
, but let's get this in since we don't have a better solution.
OK, full CI run with tests passed. I guess this is OK to merge. Note: The CI run failed twice before due to:
|
Thx :) |
Contribution description
This eagerly calls
__sinit()
instead of lazy initialization upon the first call to stdio (e.g.puts()
,printf()
). The issue is that without locking (as is currently the case for all RIOT platforms but ESP) two concurrent "first calls" may result in concurrent initialization of the same structure and data corruption.Testing procedure
Have two threads concurrently use stdio and the boot message disabled. This may result in data corruptions and crashes.
See #20067 for details on a reproducible crashing app.
Issues/PRs references
Fixes #20067