Hone logo
Hone
Problems

Customizing Panic Behavior in Rust

Rust's panic! macro provides a simple way to signal unrecoverable errors. By default, when a panic occurs, Rust aborts the current thread and prints a backtrace to the console. This challenge asks you to implement a custom panic handler to gain more control over how panics are processed.

Problem Description

Your task is to implement a custom panic handler in Rust. This involves replacing the default panic hook with your own function that will be executed whenever a panic! occurs. Your custom handler should log specific information about the panic and then decide whether to continue execution (if possible and safe) or terminate the program.

Key Requirements:

  1. Define a custom panic hook function: This function should accept a &PanicInfo object, which contains details about the panic.
  2. Log panic information: Inside your custom hook, extract and log at least the following information from PanicInfo:
    • The location of the panic (file, line, column).
    • The payload of the panic (the value passed to panic!).
  3. Conditional termination: Your handler should have a mechanism to decide whether to call std::process::exit to terminate the program. For this challenge, we'll define a simple condition: if the panic payload is the string "abort", the program should exit with a specific error code. Otherwise, if the panic payload is anything else, the program should attempt to continue execution (though in a real-world scenario, this might be unsafe and require careful consideration).
  4. Register the custom hook: Use std::panic::set_hook to register your custom function as the global panic handler.

Expected Behavior:

  • When panic!("some message") is called, your custom handler will execute, log "some message" and its location, and the program will continue (as the payload is not "abort").
  • When panic!("abort") is called, your custom handler will execute, log "abort" and its location, and the program will terminate with an exit code of 1.

Edge Cases:

  • Panics with non-string payloads: The PanicInfo payload can be of any type that implements Debug. Ensure your logging mechanism handles this gracefully.
  • Multiple panics: If a panic occurs within another panic handler, the behavior might be complex. For this challenge, focus on the primary panic.

Examples

Example 1:

  • Code:
    use std::panic;
    use std::process;
    
    fn main() {
        panic::set_hook(Box::new(|info| {
            // Custom panic logic here
            println!("Panic occurred!");
            // ... log info and conditionally exit ...
        }));
    
        println!("Starting...");
        panic!("This is a normal panic.");
        println!("This line will not be reached.");
    }
    
  • Output:
    Starting...
    Panic occurred!
    panic payload: "This is a normal panic."
    Location: src/main.rs:10:5 (or similar)
    // Program continues execution (though in this example, it won't due to the panic)
    // If there were no panic, the program would complete normally after the hook returns.
    
  • Explanation: The program starts, registers the hook, and then triggers a panic. The custom hook intercepts the panic, logs the information, and since the payload is not "abort", it returns, allowing the program to conceptually continue (though the subsequent println! is never reached due to the panic's nature).

Example 2:

  • Code:
    use std::panic;
    use std::process;
    
    fn main() {
        panic::set_hook(Box::new(|info| {
            // Custom panic logic here
            println!("Panic occurred!");
            // ... log info and conditionally exit ...
        }));
    
        println!("Starting...");
        panic!("abort");
        println!("This line will not be reached.");
    }
    
  • Output:
    Starting...
    Panic occurred!
    panic payload: "abort"
    Location: src/main.rs:10:5 (or similar)
    // Program terminates with exit code 1.
    
  • Explanation: Similar to Example 1, but the panic payload is "abort". The custom hook logs the information and then calls process::exit(1), terminating the program immediately.

Constraints

  • The program must compile successfully with rustc.
  • The custom panic handler must be registered using std::panic::set_hook.
  • The program must correctly identify and act upon the "abort" payload.
  • The logging of panic information should be clear and readable.

Notes

  • The PanicInfo struct provides access to the payload() and location(). The payload is a trait object (&dyn Any) which you'll likely want to downcast to a specific type (e.g., &str or a type implementing Debug) for logging.
  • Consider how you will handle the case where the panic payload is not a string. The as_ref() method on &dyn Any can be useful here.
  • In a real-world application, calling std::process::exit directly from a panic handler might have implications for cleanup. For this challenge, it's the required behavior for the "abort" case.
  • To see the exit code, you might need to run the program in a shell that allows inspecting exit codes (e.g., Linux/macOS shell: your_program; echo $?).
Loading editor...
rust