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

Assert in pending_errors #947

Open
ilmai opened this issue Nov 8, 2024 · 3 comments
Open

Assert in pending_errors #947

ilmai opened this issue Nov 8, 2024 · 3 comments

Comments

@ilmai
Copy link

ilmai commented Nov 8, 2024

This assert is triggering in pending_errors, line 56:
assert_eq!(Some(Reverse(seqno)), seqno2);

This results from calling poll_for_event().

I'm a bit stumped as to how to debug what's going wrong, and my knowledge of X11 is quite limited so that doesn't help.

@notgull
Copy link
Collaborator

notgull commented Nov 8, 2024

What version of XOrg are you using?

@psychon
Copy link
Owner

psychon commented Nov 9, 2024

Could you tell a bit more about the situation / program / anything where this happens?

TL;DR: The error that you are seeing is a failure of something like this:

fn foo(heap: &mut BinaryHeap<u32>) {
  if let Some(num) = heap.peek() {
      // Do something else; this might do a "return" so that a later call tries the same thing again.
      assert_eq!(Some(num), heap.pop());
  }
}

As far as I can tell... it should be impossible for this assertion to fail. And not because of any X11-related reason. That's just Rust. The usual reaction to that is to call "memory corruption!"

and my knowledge of X11 is quite limited so that doesn't help.

Okay, so...

You can send requests to the X11 server. Like conn.get_input_focus() and conn.create_window(). Every request has a sequence number. That's just a counter. The first request is number 1, the second one is number 2, etc.

Sequence numbers are used to match requests to their replies. A reply for request number 5 will contain the number 5. If request number 5 caused an error, there will be an error packet containing the number 5.

I guess you know about https://docs.rs/x11rb/latest/x11rb/cookie/index.html#handling-x11-errors : There are options to just ignore errors, to return them on the cookie, or to have them returned as an event to the main loop (poll_for_event() in your case).

With that out of the way... The code in pending_errors.rs deals with receiving errors. Line 56 is in the function get(), which is called by poll_for_event() to check "did we already receive an error that can be returned as an event?". This code knows about requests which were sent for which we did not yet receive an error or an indication that no error will be returned. This list is in_flight: BinaryHeap<Reverse<SequenceNumber>>.

Now, what does get() do exactly?

        // Check if any of the still in-flight responses got a reply/error
        while let Some(&Reverse(seqno)) = inner.in_flight.peek() {
            let result = match conn.poll_for_reply(seqno) {
                Err(()) => {
                    // This request was not answered/errored yet, so later request will not
                    // have answers as well.
                    return None;
                }
                Ok(reply) => reply,
            };

            let seqno2 = inner.in_flight.pop();
            assert_eq!(Some(Reverse(seqno)), seqno2);

It looks at the first entry of BinaryHeap via peek(). It then asks conn.poll_for_reply() whether a reply was already received for this request. If no reply was received yet, but there can still be one, this code gets an Err(()) and does nothing. Because it only used peek(), no state was actually changed and the next call to get() will do the same check again.

If it got a reply, it now has to change the state and remove the dealt-with entry, so it calls pop(). It then asserts that the entry it removed is the actual entry that it checked for. That's the assertion that is failing for you.

@ilmai
Copy link
Author

ilmai commented Nov 9, 2024

Thanks for the info!

My computer has version 1:7.7+23ubuntu2 of the xserver-xorg package.

The situation where this occurs is a bit complex as I'm building a CLAP audio plugin and this happens when I open the user interface for the plugin.

pthread_kill (@pthread_kill:81)
raise (@raise:10)
abort (@abort:46)
std::sys::pal::unix::abort_internal (@7cfeb7ba15da..7cfeb7ba1621:3)
std::panicking::rust_panic_with_hook (@std::panicking::rust_panic_with_hook:128)
std::panicking::begin_panic_handler::{{closure}} (@std::panicking::begin_panic_handler::{{closure}}:33)
std::sys::backtrace::__rust_end_short_backtrace (@7cfeb7b9aec9..7cfeb7b9af16:3)
rust_begin_unwind (@7cfeb7b9bcdc..7cfeb7b9bd4c:3)
core::panicking::panic_nounwind_fmt::runtime (@core::panicking::panic_nounwind_fmt:19)
core::panicking::panic_nounwind_fmt (@core::panicking::panic_nounwind_fmt:13)
core::panicking::panic_nounwind (@7cfeb7bc4c62..7cfeb7bc4cb8:3)
core::panicking::panic_cannot_unwind (@core::panicking::panic_in_cleanup:3)
plinth_plugin::formats::clap::extensions::timer_support::TimerSupport<P>::on_timer (.../timer_support.rs:30)
___lldb_unnamed_symbol7871 (@___lldb_unnamed_symbol7871:25)
___lldb_unnamed_symbol8591 (@___lldb_unnamed_symbol8591:110)
___lldb_unnamed_symbol6227 (@___lldb_unnamed_symbol6227:91)
___lldb_unnamed_symbol6131 (@___lldb_unnamed_symbol6131:836)
___lldb_unnamed_symbol3139 (@___lldb_unnamed_symbol3139:29)
__libc_start_main (@__libc_start_main:43)
_start (@_start:15)

For some reason it's not showing the full call stack, and the only reason I realized it's the assert mentioned above is that I have Sentry integration which was able to return information for the assert. plinth-plugin is my code which through a couple of function ends up calling poll_for_event(). I'm not getting any error from the function, it just crashes with the call stack above. I also verified that all the x11rb functions are being called from the same thread.

I'll continue digging but this is the information I have at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants