Skip to content

Adding the ability to post an error on any object - #4843

Merged
mattkae merged 3 commits into
wayland-rs-error-handlingfrom
wayland-rs-error-handling-across-objects
Apr 17, 2026
Merged

Adding the ability to post an error on any object#4843
mattkae merged 3 commits into
wayland-rs-error-handlingfrom
wayland-rs-error-handling-across-objects

Conversation

@mattkae

@mattkae mattkae commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

What's new?

  • C++ classes are now initialized with their protocol ID during the associate step
  • We keep a map from protocol_id -> Resource in a thread-local storage
  • The ProtocolError now includes this protocol ID when it sends exceptions
  • The ID gets parsed, looked up in the map, and then used to post an error if it is available

Checklist

  • Tests added and pass
  • Adequate documentation added
  • (optional) Added Screenshots or videos

@RAOF RAOF left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wheeee! What a mess. I've suggested what I think is an improvement; please check if that works!

Comment on lines +582 to +585
thread_local! {
static OBJECT_REGISTRY: RefCell<HashMap<u32, ObjectId>> = RefCell::new(HashMap::new());
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not wild about making this a thread-local; this makes our C++ side no longer threadsafe.

A grungy, but possible, alternative would be to use handle.object_for_protocol_id()? This would require stashing the &'static protocol::Interface in addition to the object id in the C++ side, but because it's 'static that would be safe (although it's marshalling pointer -> string -> pointer, so looks groody)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My push back is that:

  1. It adds a lot of complication from what I've seen so far
  2. When else would you be throwing a protocol error outside of the Wayland thread? Errors are thrown in response to some request typically, not out of the blue AFAIK

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we went the easy route and put the map behind a lock. That way we can avoid unnecessary thread safe code, and the lookup table will always be thread safe. And therefore we can post errors from any thread 😄 This seems like the best route in my opinion as it avoid a lot of unsafety and complication (e.g. serializing pointers)

@mattkae
mattkae requested a review from RAOF April 15, 2026 13:20

@RAOF RAOF left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that works, but...

One of the things that passing the &'static Interface would have handled (that I didn't explicitly mention) is removing things from the map; as it is now, IDs are never removed for dead objects.

Can we also remove from the map when the object dies? Otherwise clients will be able to cause us to consume unbounded memory ðŸ˜Ū‍ðŸ’Ļ

@mattkae

mattkae commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

Yeah, that works, but...

One of the things that passing the &'static Interface would have handled (that I didn't explicitly mention) is removing things from the map; as it is now, IDs are never removed for dead objects.

Can we also remove from the map when the object dies? Otherwise clients will be able to cause us to consume unbounded memory ðŸ˜Ū‍ðŸ’Ļ

Oof of course!

Luckily, our Dispatch provides a destroyed call, so we can just remove ourselves from the map there :)

@mattkae
mattkae requested a review from RAOF April 16, 2026 12:30

@RAOF RAOF left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to make one last request; feel free to ignore it or to apply that set of changes and merge.


fn register_resource(resource: &impl Resource) {
let id = resource.id();
OBJECT_REGISTRY.write().unwrap_or_else(|e| e.into_inner()).insert(id.protocol_id(), id);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OBJECT_REGISTRY.write().unwrap_or_else(|e| e.into_inner()).insert(id.protocol_id(), id);
OBJECT_REGISTRY.write().expect("lock poisoned").insert(id.protocol_id(), id);

I don't know if we can witness it, but if the Mutex is poisoned then we probably want to bail rather than continue with weirdness.

@mattkae
mattkae merged commit d3824d2 into wayland-rs-error-handling Apr 17, 2026
21 of 37 checks passed
@mattkae
mattkae deleted the wayland-rs-error-handling-across-objects branch April 17, 2026 12:13
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

Successfully merging this pull request may close these issues.

2 participants