How can I proxy a panic message from a thread pool to the test endpoint?

I have some thread pool. It creates some async runner and executes a provided future. It also uses catch_unwind to catch panics. If a panic occurs, a thread from the pool shuts down and sends via a sync channel the caught data. The main test endpoint periodically checks all spawned (by this endpoint) handles and resume_unwind if it gets a panic. Like

pub(crate) type JobResult = thread::Result<()>;

pub(crate) struct ExecutorPoolJoinHandle {
    was_joined: bool,
    sync_receiver: SyncReceiver<JobResult>,
}


pub(crate) fn join_timeout_maybe_resume_panic(
        &mut self,
        timeout: Option<Duration>,
    ) -> Result<(), RecvTimeoutError>
    {
        assert!(!self.was_joined);

        let res = if let Some(timeout) = timeout {
            match self.sync_receiver.recv_timeout(timeout) {
                Ok(res) => res,
                Err(RecvTimeoutError::Timeout) => return Err(RecvTimeoutError::Timeout),
                _ => panic!("{BUG_MESSAGE}"),
            }
        } else {
            self.sync_receiver.recv().expect(BUG_MESSAGE)
        };

        self.was_joined = true;

        if let Err(err) = res {
            panic::resume_unwind(err);
        }

        Ok(())
    }

And it sees panics. It also fails tests. But in the RustRover test's window, I don't see the panic message. If I run it with the console, I can see something like it:

---- runtime::epoch_gc::test::test_epoch_gc_concurrent stdout ----
Test test_epoch_gc_concurrent started!

thread 'orengine-test-executor' panicked at src/runtime/epoch_gc/test.rs:116:9:
assertion left == right failed
left: 4
right: 24

Looks like all messages are forwarded to the stdout. How to forward them to the stderr?

This is not the first place to look. Often, Rust is set up to capture test output and only show it if the test fails. I would start by investigating whether test capturing is set up correctly.

With cargo, the relevant flag is --no-capture.

I don't think you can. The test running takes control of the global panic hook so you should not change it and the Err from catch_unwind can't be extracted into anything meaningful. Best you possibly can do it panic at that point and say the thread panicked so look at std out for its message.

But the test fails, and I can't see the output. I would panic one more time with the message, but it is Box<dyn Any + Send> and can't be downcast to String or &str.

Yes, it works and shows the panic message, but I want to repair the output for IDEs. I write my own async runtime, and it is bad if users can't debug their programs because of this issue. I can rewrite the test module to show panics from the main test endpoints, but I want to show all panics (even in other threads but spawned by one endpoint).

Honestly, it sounds like an IDE bug.

Before choosing a "hacky" solution, I decided to test all the theories I had. It turned out that panics are displayed correctly if threads are not reused. Moreover, you need to avoid reusing even those threads that did not catch any panics. I don't know why this happens. If you know how to actually fix this bug while still reusing threads, please supplement my answer.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.