-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
panic-in-panic-hook: formatting a message that's just a string is risk-free #122984
Conversation
None, // no message | ||
location, // but we want to show the location! | ||
message.as_ref(), | ||
location, | ||
can_unwind, | ||
force_no_backtrace, | ||
); | ||
rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n"); | ||
} | ||
panic_count::MustAbort::AlwaysAbort => { |
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 could use the same logic as above in this branch as well, which would fix #122940 but degrade panic printing for post-fork panics that do need formatting. Let me know what 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.
@Amanieu any thoughts on this?
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 think #122940 is better fixed with an additional flag on the global count.
This comment has been minimized.
This comment has been minimized.
@bors r+ |
panic-in-panic-hook: formatting a message that's just a string is risk-free This slightly improves the output in the 'panic while processing panic' case if the panic message does not involve any formatting. Follow-up to rust-lang#122930. r? `@Amanieu`
…iaskrgr Rollup of 10 pull requests Successful merges: - rust-lang#122737 (conditionally ignore fatal diagnostic in the SilentEmitter) - rust-lang#122757 (Fixed the `private-dependency` bug) - rust-lang#122886 (add test for rust-lang#90192) - rust-lang#122937 (Unbox and unwrap the contents of `StatementKind::Coverage`) - rust-lang#122949 (Add a regression test for rust-lang#117310) - rust-lang#122962 (Track run-make-support lib in common inputs stamp) - rust-lang#122977 (Rename `Arguments::as_const_str` to `as_statically_known_str`) - rust-lang#122983 (Fix build failure on ARM/AArch64/PowerPC/RISC-V FreeBSD/NetBSD) - rust-lang#122984 (panic-in-panic-hook: formatting a message that's just a string is risk-free) - rust-lang#122992 (std::thread: refine available_parallelism for solaris/illumos.) r? `@ghost` `@rustbot` modify labels: rollup
…iaskrgr Rollup of 10 pull requests Successful merges: - rust-lang#122737 (conditionally ignore fatal diagnostic in the SilentEmitter) - rust-lang#122757 (Fixed the `private-dependency` bug) - rust-lang#122886 (add test for rust-lang#90192) - rust-lang#122937 (Unbox and unwrap the contents of `StatementKind::Coverage`) - rust-lang#122949 (Add a regression test for rust-lang#117310) - rust-lang#122962 (Track run-make-support lib in common inputs stamp) - rust-lang#122977 (Rename `Arguments::as_const_str` to `as_statically_known_str`) - rust-lang#122983 (Fix build failure on ARM/AArch64/PowerPC/RISC-V FreeBSD/NetBSD) - rust-lang#122984 (panic-in-panic-hook: formatting a message that's just a string is risk-free) - rust-lang#122992 (std::thread: refine available_parallelism for solaris/illumos.) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#122984 - RalfJung:panic-in-hook, r=Amanieu panic-in-panic-hook: formatting a message that's just a string is risk-free This slightly improves the output in the 'panic while processing panic' case if the panic message does not involve any formatting. Follow-up to rust-lang#122930. r? ``@Amanieu``
// Don't try to format the message in this case, perhaps that is causing the | ||
// recursive panics. However if the message is just a string, no user-defined | ||
// code is involved in printing it, so that is risk-free. | ||
let msg_str = message.and_then(|m| m.as_str()).map(|m| [m]); | ||
let message = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m)); | ||
let panicinfo = PanicInfo::internal_constructor( | ||
None, // no message | ||
location, // but we want to show the location! | ||
message.as_ref(), | ||
location, | ||
can_unwind, | ||
force_no_backtrace, | ||
); | ||
rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n"); |
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.
For some reason I thought that this would show the message as unformatted, not just when it contains no formatting args.
ie. I thought it shows both cases:
panic!("some unformatted string")
; would show assome unformatted string
panic!("some formatted string i={} j={}", i, j);
would show assome formatted string i={} j={}
(literally)
but the latter doesn't show at all(which is indeed intended to be so by this PR, no problem),
therefore for my local rust copy that I'm gonna use, I had to change it and make it do that second case too(well, almost that: the {}
won't be visible, it's acceptable compromise - I don't really need to see those, given that it would only complicate the code used to show them) by replacing lines 751 and 752 from above with:
let message=message.map(|m| m.unformat_it());
Index: /var/tmp/portage/dev-lang/rust-1.75.0-r1/work/rustc-1.75.0-src/library/core/src/fmt/mod.rs
===================================================================
--- .orig/var/tmp/portage/dev-lang/rust-1.75.0-r1/work/rustc-1.75.0-src/library/core/src/fmt/mod.rs
+++ /var/tmp/portage/dev-lang/rust-1.75.0-r1/work/rustc-1.75.0-src/library/core/src/fmt/mod.rs
@@ -352,6 +352,20 @@ impl<'a> Arguments<'a> {
Arguments { pieces, fmt: Some(fmt), args }
}
+ /// just return the unformatted string
+ /// so this:
+ /// "some formatted string i={} j={}"
+ /// would be seen as:
+ /// "some formatted string i= j="
+ /// because the {}s get removed and transformed into the args array.
+ /// this assumes `pub fn write` was already patched to handle the extra pieces,
+ /// else you only see the first piece like:
+ /// "some formatted string i="
+ #[inline]
+ pub fn unformat_it(&self) -> Arguments<'a> {
+ Arguments { pieces:self.pieces, fmt: None, args: &[] }
+ }
+
/// Estimates the length of the formatted text.
///
/// This is intended to be used for setting initial `String` capacity
@@ -1140,10 +1154,23 @@ pub fn write(output: &mut dyn Write, arg
}
// There can be only one trailing string piece left.
- if let Some(piece) = args.pieces.get(idx) {
- formatter.buf.write_str(*piece)?;
+ //if let Some(piece) = args.pieces.get(idx) {
+ // formatter.buf.write_str(*piece)?;
+ //}
+ //Maybe there's a ton of pieces*, that had fmt: None and args: &[]
+ //and we wanna print them all, yes they'll be unformatted like due to .unformat_it() function
+ //from Arguments struct.
+ // * not just the one trailing string piece left.
+ if idx < args.pieces.len() {
+ // Iterate over the remaining string pieces starting from idx
+ for piece in &args.pieces[idx..] {
+ // Write each piece to the formatter buffer
+ formatter.buf.write_str(piece)?;
+ }
}
+
+
Ok(())
}
I'm just saying this in case it may be useful to anyone for any reason. Certainly I don't expect any such change(s) to be incorporated into rust as it seems hacky or unnecessary.
Doing this however has uncovered an issue(playground link) whereby the following message from within .expect
isn't shown (even before this PR, ie. rust stable):
use std::fmt::{Display, self};
struct MyStruct;
impl Display for MyStruct {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
None::<i32>.expect("oh snap");
todo!();//ignore this, it's for return
}
}
fn main() {
let instance = MyStruct;
assert!(false, "oh no, '{}' was unexpected", instance);
}
Compiling playground v0.0.1 (/playground)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.66s
Running `target/debug/playground`
panicked at src/main.rs:7:21:
thread panicked while processing panic. aborting.
feel free(anyone) to make an issue out of it, I'm just "busy" exploring how to fix it locally. Note that in this PR, message
is seen as being None
after the two lines that transform it, this is why it's not shown, however as to why it's None
after when it's clearly shown initially to be there when displayed (as {:?}
(Debug is same as Display) shows as Some(oh snap)
) I'm uncertain yet (in progress, might update this later)
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.
Doing this however has uncovered an issue(playground link) whereby the following message from within .expect isn't shown (even before this PR, ie. rust stable):
That's expected, the panic here uses formatting. It goes via this code path.
My PR is only expected to show the panic message for literal panic!("text here")
, not for anything that involves {}
in any way.
It will show in some extra cases due to this optimization, but that's not guaranteed.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
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.
you mean that None::.expect("oh snap"); uses formatting internally?
Yes, it does.
Thanks to RalfJung rust-lang/rust#122984 (comment)
This slightly improves the output in the 'panic while processing panic' case if the panic message does not involve any formatting. Follow-up to #122930.
r? @Amanieu