-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Implement RealtimeSanitizer (RTSan) support, add #[realtime(nonblocking)]
, #[realtime(blocking)]
attributes
#3766
base: master
Are you sure you want to change the base?
Conversation
`#[blocking]` attributes
one objection to naming the attributes |
I also agree that the naming is confusing, since while it is very similar to the goals of what async people want, I think that it's not quite the same. Perhaps simply having a |
I think that seems reasonable. We are open to changing the attribute names. I like the sound of "realtime(required)" and "realtime(forbidden)" Some other possibilities (spitballing): For nonblocking:
For blocking:
Any of these jump out to folks? Not sure if we want to do "rtsan" or "realtime" as the main attribute name, I like "realtime" better but it is less specific, for better or worse. |
text/0000-rtsan-and-attributes.md
Outdated
```rust | ||
#[nonblocking] | ||
fn process() { | ||
rtsan_scoped_disabler!({ |
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'm not familiar with the implementation of RealtimeSanitizer, but would it be possible to implement this kind of thing / sanitizer/rtsan_interface.h
in a crate instead? I recall that something like that is possible with Callgrind.
If that's the case, you could perhaps downscope this to just "add RealtimeSanitizer and std
support", and let users figure it out for themselves to do something else on cfg!(sanitize = "realtime")
if they have some API themselves that they want to mark as realtime.
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'm not sure I understand, could you elaborate more?
As for internal details, let me give you some more info to help understand the inner workings of rtsan.
The main component is the sanitizer runtime library. This is a simple dynamic library, similar to the runtime components of tsan, asan etc. Like any shared library, if you have the header and the compiled library you can include it in your binary.
So, it would be possible to include the header, and link against the shared library. In fact, we made a standalone proof of concept crate to work out many of the kinks of rtsan in rust and write this proposal, that can be seen here:
https://github.com/realtime-sanitizer/rtsan-standalone-rs
With an article from @steckes on his blog on how he implemented and lessons he learned (not necessary to read for this RFC, but may provide additional info): https://steck.tech/posts/rtsan-in-rust/
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.
So, assuming that std
can get special treatment and thus we don't need to worry about that for the design of the feature / the public API, the main part is that rustc
is going to link in this shared libclang_rt.rtsan*
library when you enable -Zsantizer=realtime
(or -Csantizer=realtime
), right?
If that is done, could the rtsan-standalone-rs
crate be updated such that e.g. realtime_enter
would be defined as the following?
pub fn realtime_enter() {
#[cfg(all(sanitize = "realtime", any(target_os = "macos", target_os = "linux")))]
unsafe { rtsan_standalone_sys::__rtsan_realtime_enter() };
}
Along with rtsan-standalone-sys
being updated to not do anything in build.rs
(because rustc
already does it for it)?
(Remember that the sanitize = "..."
cfg is already provided for the other sanitizers).
If so, then I don't see the reason why these attributes has to be exposed by rustc
as a language feature?
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.
My argument here is not so much against a built-in #[blocking]
etc., it's just that, if we can avoid having this in the language, and restrict it to just adding a rustc
flag, then there's a much higher probability that the feature will be accepted (actually, then I don't even think you'd need an RFC, at most an MCP. But I'm not a compiler team member, so I can't say that for sure).
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.
So, assuming that
std
can get special treatment and thus we don't need to worry about that for the design of the feature / the public API, the main part is thatrustc
is going to link in this sharedlibclang_rt.rtsan*
library when you enable-Zsantizer=realtime
(or-Csantizer=realtime
), right?
Yes, you're correct in your understanding here!
If that is done, could the
rtsan-standalone-rs
crate be updated such that e.g.realtime_enter
would be defined as the following?pub fn realtime_enter() { #[cfg(all(sanitize = "realtime", any(target_os = "macos", target_os = "linux")))] unsafe { rtsan_standalone_sys::__rtsan_realtime_enter() }; }Along with
rtsan-standalone-sys
being updated to not do anything inbuild.rs
(becauserustc
already does it for it)?(Remember that the
sanitize = "..."
cfg is already provided for the other sanitizers).If so, then I don't see the reason why these attributes has to be exposed by
rustc
as a language feature?
I see what you're saying, I think! I agree this would make it easier to accept/deny this RFC, the most controversial part is definitely the addition of the attributes (and changes to assert
, panic
etc).
However, as an end user, I think it would be strange for the compiler to expose the flag, link the library and do nothing until I downloaded and used another third party crate (rtsan-standalone-rs
). I think a good proposal from the end users perspective would allow them to do everything with only rustc, not relying on a third party crate.
I think the addition of the attributes into the standard would also encourage libraries to document their expectations - far in the future you could imagine just looking at the signature of functions and reasoning about if they are real-time safe because they have the attribute.
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.
the most controversial part is definitely the addition of the attributes
Again, I'm not the one that's gonna make a decision here, but personally, I would like to evaluate the merits of such attributes separately from the actual sanitizer being added.
However, as an end user, I think it would be strange for the compiler to expose the flag
the addition of the attributes into the standard would also encourage libraries to document their expectations
That's fair, and I agree that having this in the language/std could have ecosystem effects, but then I think the RFC should be written around that; or at least have a section that says "why does this belong in the language/std".
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.
Again, I'm not the one that's gonna make a decision here, but personally, I would like to evaluate the merits of such attributes separately from the actual sanitizer being added.
In our initial zulip thread, one of the compiler team members said we did not need an RFC for adding the sanitizer, only the attributes (see the thread). However, to piece together the RFC we thought it made most sense to provide all of the context in which the attributes will be used.
Definitely we expect most of the conversation here to be around the attributes!
I'll wait a bit to see what some others say about this. Thanks for the feedback so far, it's appreciated.
text/0000-rtsan-and-attributes.md
Outdated
An example of an improper allocation being detected in a `nonblocking` function: | ||
```rust | ||
> cat example/src/main.rs | ||
#[nonblocking] |
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.
Attribute naming thread
Existing comments: #3766 (comment) , #3766 (comment) , #3766 (comment)
I'll toss my hat in for realtime(constrained)
to mark a "please validate this function" root, and realtime(blocking)
to mark a function as forbidden underneath a validation root. Further naming work is needed to have separate validation classes for "blocking event loop" (target 20Hz 50ms) versus "blocking the frame timer" (target 120Hz 8ms - you cannot call Windows Thread sleep) versus "hard realtime" (no allocations)
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.
Reading further, I see rtsan_scoped_disabler!
. I already had text typed to propose realtime(unconstrained)
for that usecase, but deleted it after I realized that wasn't the two primary attributes.
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 like realtime(constrained)
and realtime(blocking)
. I would be OK with that being the two.
Any thoughts other co-authors @steckes @davidtrevelyan?
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 can get on board with this style, for sure! If we're happy with realtime(blocking)
, would we also be happy with realtime(nonblocking)
? I suggest this in an effort to maintain the blocking/nonblocking symmetry and consistency with clang, while at the same time being explicit about it being realtime blocking/nonblocking (and thereby reducing confusion with other definitions of blocking and nonblocking). What do you think?
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 would also like to keep it closer to the original documentation, so it is less confusing.
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 would also support realtime(nonblocking/blocking)
. This may be the best of both worlds as it keeps the documentation green, and doesn't collide with any async work. Any thoughts @riking @clarfonthey @programmerjake?
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.
seems good to me!
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 have updated the doc to use realtime(nonblocking/blocking)
because of the support of all original authors and no objections (thusfar). Of course this can be changed again if more feedback comes in :)
I think we shouldn't name stuff after the verification mechanism, since that could be changed/extended to use something other than rtsan. maybe name it |
Seems reasonable to me! Thanks for the feedback, I agree.
Differentiating between harder and softer realtime is out of the scope of rtsan as it exists today, it only has one level which is "disallow all non-deterministic time calls", which is just generally "realtime", encompassing all levels from hard-soft. I think this would also open up a lot of debate as to what is allowed at each level of hardness. The solution we have gone with is to disallow everything, and let users opt-out via the scoped_disabler or suppression lists if they want to allow allocations or similar. |
in that case |
maybe something that is more similar to the no_sanitize which is already existing in Rust, like Just to be clear, I understand the ambiguity with async, but renaming those things means that the official RealtimeSanitizer documentation does not apply for Rust anymore. It removes confusion in async but introduces confusion for people reading the LLVM docs. |
text/0000-rtsan-and-attributes.md
Outdated
|
||
``` | ||
|
||
### The addition of the `rtsan_scoped_disabler!` macro |
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.
@steckes @programmerjake starting a thread to discuss changing or not changing this macro name (so it's not in the main thread)
text/0000-rtsan-and-attributes.md
Outdated
|
||
2. User defined functions marked `blocking` | ||
|
||
The new `blocking` attribute allows users to mark a function as unsafe for real-time contexts. |
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.
This description elicits potential confusion with unsafe
(memory safety). Does such a function become unsafe
to call if I compile with RTSan enabled? I do not think it will?
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.
No this just means real-time unsafe and has nothing to do with the unsafe keyword in Rust. Thanks for pointing this out.
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'll tweak the wording here to make it more obvious what we are talking about! unsafe definitely an overloaded term in general.
To be clear (and echo @steckes): real-time unsafe != memory unsafe/the unsafe
rust uses.
text/0000-rtsan-and-attributes.md
Outdated
If users rely on `panic!` or `assert!` while running under RealtimeSanitizer, they will hit an intercepted call before the message is printed. | ||
|
||
For example: | ||
|
||
```rust | ||
#[nonblocking] | ||
fn processor(buffer: &[f32]) { | ||
buffer[512]; // Oops, out of bounds!! should panic! | ||
} | ||
|
||
processor(&[0.0; 512]); | ||
``` | ||
|
||
Running under RTSan the user gets this message. This is due to some memory being allocated to prepare to print the panic message. | ||
``` | ||
==31969==ERROR: RealtimeSanitizer: unsafe-library-call | ||
Intercepted call to real-time unsafe function `malloc` in real-time context! | ||
``` | ||
|
||
A user should expect this out of bounds access to print: | ||
``` | ||
index out of bounds: the len is 512 but the index is 512 | ||
``` | ||
|
||
To adhere to this expected behavior, RTSan should be disabled for `panic!` and each of the assertion macros: `assert`, `assert_eq`, `assert_ne`, `debug_assert`, `debug_assert_eq`, `debug_assert_ne`. |
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.
Note that it would be possible to make panic!
and the following backtrace process not allocate, but obviously it currently does.
#[nonblocking]
, #[blocking]
attributes#[realtime(nonblocking)]
, #[realtime(blocking)]
attributes
Seeing as it has been a week, I'm going to post a little ping/recap comment to encourage more conversation on this RFC. What happened in the initial week:
Any more thoughts/ideas/input greatly appreciated. Thanks for the discussion so far. |
RealtimeSanitizer is an approach to detecting real-time safety violations in timing critical code. It has been added to LLVM 20, adn this RFC aims to leverage that work and add it to Rust.
See the document for more.
Thanks for considering,
Chris (@cjappl), David (@davidtrevelyan), and Stephen (@steckes)
Rendered