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

panic-in-panic-hook: formatting a message that's just a string is risk-free #122984

Merged
merged 1 commit into from
Mar 24, 2024

Conversation

RalfJung
Copy link
Member

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

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 24, 2024
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 => {
Copy link
Member Author

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.

Copy link
Member Author

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?

Copy link
Member

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.

@rust-log-analyzer

This comment has been minimized.

@Amanieu
Copy link
Member

Amanieu commented Mar 24, 2024

@bors r+

@bors
Copy link
Contributor

bors commented Mar 24, 2024

📌 Commit 0727b6a has been approved by Amanieu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 24, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 24, 2024
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`
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
…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
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
…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
@bors bors merged commit f67fb08 into rust-lang:master Mar 24, 2024
11 checks passed
@rustbot rustbot added this to the 1.79.0 milestone Mar 24, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
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``
@RalfJung RalfJung deleted the panic-in-hook branch March 24, 2024 18:28
Comment on lines +748 to 759
// 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");

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 as some unformatted string
  • panic!("some formatted string i={} j={}", i, j); would show as some 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)

Copy link
Member Author

@RalfJung RalfJung Mar 25, 2024

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.

Copy link
Member Author

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.

correabuscar added a commit to correabuscar/sandbox that referenced this pull request Mar 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants