wl_client/proxy/low_level/owned.rs
1use {
2 crate::{
3 ffi::{
4 WL_MARSHAL_FLAG_DESTROY, interface_compatible, wl_argument, wl_dispatcher_func_t,
5 wl_interface, wl_message, wl_proxy,
6 },
7 proxy::low_level::{
8 borrowed::UntypedBorrowedProxy,
9 check_dispatching_proxy, check_new_proxy,
10 owned::scope::{Scope, ScopeData},
11 },
12 queue::Queue,
13 utils::sync_ptr::{SyncNonNull, SyncPtr},
14 },
15 destruction::ProxyDataDestruction,
16 parking_lot::Mutex,
17 run_on_drop::on_drop,
18 std::{
19 any::{Any, TypeId},
20 cell::Cell,
21 collections::HashSet,
22 ffi::{c_int, c_void},
23 mem::{self},
24 ops::Deref,
25 panic::{AssertUnwindSafe, catch_unwind},
26 ptr::{self, NonNull},
27 sync::{
28 Arc,
29 atomic::{
30 AtomicBool, AtomicPtr, AtomicUsize,
31 Ordering::{Acquire, Relaxed, Release},
32 fence,
33 },
34 },
35 },
36};
37
38pub(crate) mod destruction;
39pub(crate) mod scope;
40#[cfg(test)]
41mod tests;
42
43/// A owned `wl_proxy` pointer.
44///
45/// Most of the time you will not work with this type directly and instead use one of
46/// the types generated by `wl-client-builder`.
47#[derive(Eq, PartialEq)]
48pub struct UntypedOwnedProxy {
49 data: SyncNonNull<UntypedOwnedProxyData>,
50}
51
52struct UntypedOwnedProxyData {
53 /// This object is owned by a number of [`UntypedOwnedProxy`] objects. This field
54 /// contains the number of these objects. Additionally, if ever_had_event_handler is
55 /// true, then libwayland might be holding a pointer to this object and this object
56 /// must not be destroyed until we know that libwayland has ceased accessing the
57 /// pointer.
58 ref_count: AtomicUsize,
59 /// The queue that this proxy is attached to.
60 queue: Queue,
61 /// This field holds the wl_proxy. We're storing it in a [`UntypedBorrowedProxy`] so
62 /// that we can deref to [`UntypedBorrowedProxy`]. This [`UntypedBorrowedProxy`] is
63 /// mutable. The proxy is a wrapper if and only if `interface` is None.
64 proxy: UntypedBorrowedProxy,
65 /// This is Some if and only if the proxy is not a wrapper. In this case, this is the
66 /// interface of the proxy.
67 interface: Option<&'static wl_interface>,
68 /// This is true if a event handler has been attached to the proxy. We only allow
69 /// attaching a event handler once.
70 ever_had_event_handler: AtomicBool,
71 /// A pointer to event handler data. This is set once while holding the proxy pointer
72 /// read lock. It is accessed by event_handler_func and when destroying the event
73 /// handler. Visibility is ensured just like for the scope_data field below.
74 ///
75 /// The pointer gets invalidated when the event handler is destroyed which can happen
76 /// long before this object is dropped. In these cases, access to the event handler
77 /// is prevented in two ways: If the proxy has been destroyed, then event_handler_func
78 /// is no longer invoked and the code ensures that the event handler is not destroyed
79 /// before the last such invocation has completed. If the proxy has not been destroyed,
80 /// then the event dispatcher is event_handler_func_scoped and that function will
81 /// never again call into event_handler_func.
82 event_handler: AtomicPtr<u8>,
83 /// If this is not null, it is a function pointer to a function that can be used to
84 /// drop the event handler. This field is written at the same time as the
85 /// event_handler field is written. Visibility is ensured just like for event_handler.
86 /// It is set back to null while holding the proxy pointer write lock when creating
87 /// the [`ProxyDataDestruction`] for the event handler.
88 drop_event_handler: AtomicPtr<u8>,
89 /// This field is true if and only if this proxy is attached to a registry.
90 stored_in_registry: AtomicBool,
91 /// The scope that this proxy is attached to, if any. This ensures that the scope_data
92 /// field remains valid until this object is dropped.
93 scope_data_arc: Mutex<Option<Arc<ScopeData>>>,
94 /// A pointer to the data in the Arc stored in scope_data_arc, or null if the proxy is
95 /// not attached to a scope. This field is written at most once while holding the proxy
96 /// pointer read lock. It is accessed by event_handler_func_scoped and by code in this
97 /// file.
98 ///
99 /// The event handler is attached to this proxy while holding the dispatch lock which
100 /// is also held when the event handler is invoked. This ensures visibility in the
101 /// event handler.
102 ///
103 /// All code in this file that accesses this field does so while having exclusive
104 /// access to the proxy pointer, either by holding the proxy pointer write lock or in
105 /// the drop impl. This ensures visibility in those places.
106 ///
107 /// If it is not null, then this pointer remains valid until this object is dropped.
108 scope_data: AtomicPtr<ScopeData>,
109}
110
111/// A registry used for owned proxies that might have to be destroyed at some point.
112///
113/// This is used for proxies that have event handlers with a drop impl. Such event handlers can
114/// form a reference cycle with the proxy that has to be explicitly broken. All proxies
115/// in this registry will be explicitly destroyed when the connection object is dropped.
116/// Destroying the proxy drops the event handler which breaks the reference cycle.
117#[derive(Default)]
118pub(crate) struct OwnedProxyRegistry {
119 /// This set contains proxies that have a event handler with a drop impl attached. The
120 /// pointers in this set are always valid, but they are not strong references. You can
121 /// dereference them while holding this lock. To be able to use them outside of
122 /// holding the lock, you must increment the reference count from n>0 to n+1. Note
123 /// that the reference count can be n=0. Such pointers must be ignored.
124 proxies: Mutex<HashSet<SyncNonNull<UntypedOwnedProxyData>>>,
125}
126
127/// A transparent wrapper around [`UntypedOwnedProxy`].
128///
129/// # Safety
130///
131/// This type must be a transparent wrapper around [`UntypedOwnedProxy`].
132pub unsafe trait UntypedOwnedProxyWrapper: Clone {}
133
134// SAFETY: Self is literally UntypedOwnedProxy.
135unsafe impl UntypedOwnedProxyWrapper for UntypedOwnedProxy {}
136
137impl Deref for UntypedOwnedProxy {
138 type Target = UntypedBorrowedProxy;
139
140 fn deref(&self) -> &Self::Target {
141 &self.data().proxy
142 }
143}
144
145impl UntypedOwnedProxy {
146 /// Creates a new [`UntypedOwnedProxy`] from a plain `wl_proxy`.
147 ///
148 /// # Safety
149 ///
150 /// - `proxy` must be a valid pointer to a plain `wl_proxy`.
151 /// - `proxy` must remain valid for the lifetime of this object and its clones.
152 /// - `proxy` must not have an event handler or dispatcher assigned.
153 /// - `queue` must be the queue of the proxy.
154 /// - `interface` must be the interface of the proxy.
155 pub unsafe fn from_plain_wl_proxy(
156 queue: &Queue,
157 proxy: NonNull<wl_proxy>,
158 interface: &'static wl_interface,
159 ) -> Self {
160 // SAFETY: - proxy is a plain proxy and interface is its interface
161 // - proxy does not have an event handler assigned
162 // - queue is the queue of the queue
163 unsafe { Self::new(queue, proxy, Some(interface)) }
164 }
165
166 /// Creates a new [`UntypedOwnedProxy`] from a wrapper `wl_proxy`.
167 ///
168 /// # Safety
169 ///
170 /// - `proxy` must be a valid pointer to a wrapper `wl_proxy`.
171 /// - `proxy` must remain valid for the lifetime of this object and its clones.
172 /// - `queue` must be the queue of the proxy.
173 pub unsafe fn from_wrapper_wl_proxy(queue: &Queue, proxy: NonNull<wl_proxy>) -> Self {
174 // SAFETY: - proxy is a valid wrapper and as such does not have an event handler
175 // - queue is the queue of the proxy
176 unsafe { Self::new(queue, proxy, None) }
177 }
178
179 /// # Safety
180 ///
181 /// - proxy must be a valid pointer
182 /// - proxy must not have an event handler assigned
183 /// - this function takes ownership of the proxy
184 /// - the proxy's event handler must not be modified except through this object
185 /// - queue must be the queue of the proxy
186 /// - if interface is not None, it must be the interface of the wl_proxy
187 /// - if this is a wrapper, then interface must be None
188 /// - if this is not a wrapper, then interface must not be None
189 unsafe fn new(
190 queue: &Queue,
191 proxy: NonNull<wl_proxy>,
192 interface: Option<&'static wl_interface>,
193 ) -> Self {
194 let data = Box::new(UntypedOwnedProxyData {
195 ref_count: AtomicUsize::new(1),
196 queue: queue.clone(),
197 proxy: {
198 // SAFETY: - By the safety requirements of this function, proxy is a valid
199 // pointer.
200 // - Whenever we destroy the proxy we first set it to a null
201 // pointer.
202 unsafe { UntypedBorrowedProxy::new_internal(queue.libwayland(), proxy) }
203 },
204 interface,
205 ever_had_event_handler: Default::default(),
206 event_handler: Default::default(),
207 drop_event_handler: Default::default(),
208 stored_in_registry: Default::default(),
209 scope_data: Default::default(),
210 scope_data_arc: Default::default(),
211 });
212 Self {
213 data: SyncNonNull(NonNull::from(Box::leak(data))),
214 }
215 }
216
217 fn data(&self) -> &UntypedOwnedProxyData {
218 // SAFETY: self.data is always a valid pointer except during `drop`.
219 unsafe { self.data.as_ref() }
220 }
221
222 /// Destroys this object by sending a request on this proxy.
223 ///
224 /// After this function returns, the underlying `wl_proxy` has been destroyed.
225 ///
226 /// This function cannot be used if the request creates a new object. Use
227 /// [`UntypedOwnedProxy::send_constructor`] for that purpose.
228 ///
229 /// This function cannot be used if this is a wrapper.
230 ///
231 /// # Panic
232 ///
233 /// - This function panics if this proxy has already been destroyed.
234 /// - This function might panic if the proxy is attached to a local queue and the
235 /// current thread is not the thread in which the queue was created.
236 /// - This function panics if this proxy is a wrapper.
237 ///
238 /// # Safety
239 ///
240 /// - `opcode` must be a valid request opcode for the interface of the proxy.
241 /// - `args` must conform to the interface + opcode of the proxy.
242 /// - `args` must not contain any `new_id` element.
243 #[inline]
244 pub unsafe fn send_destructor(&self, opcode: u32, args: &mut [wl_argument]) {
245 let slf = self.data();
246 if slf.interface.is_none() {
247 panic!("Proxy is a wrapper");
248 }
249 let _write_lock = slf.proxy.lock.write();
250 // SAFETY: We're holding the write lock.
251 let proxy = slf.proxy.proxy.load(Relaxed);
252 let proxy = check_dispatching_proxy(NonNull::new(proxy));
253 // SAFETY: We're holding the write lock.
254 slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
255 // SAFETY: - We've just checked that proxy is not null. By the invariants, the
256 // proxy is valid.
257 // - The opcode/args requirements are forwarded to the caller.
258 // - Flags are WL_MARSHAL_FLAG_DESTROY.
259 // - We've checked above that the proxy is not a wrapper.
260 // - We've set the proxy pointer to null.
261 unsafe {
262 slf.proxy.libwayland.wl_proxy_marshal_array_flags(
263 proxy.as_ptr(),
264 opcode,
265 ptr::null(),
266 0,
267 WL_MARSHAL_FLAG_DESTROY,
268 args.as_mut_ptr(),
269 );
270 }
271 // SAFETY: - We're holding the write lock of the proxy.
272 // - The proxy has been destroyed.
273 unsafe {
274 self.destroy_event_handler();
275 }
276 }
277
278 /// Creates a new object by sending a request on this proxy.
279 ///
280 /// If `DESTROY=true`, then the underlying `wl_proxy` has been destroyed after this
281 /// function returns.
282 ///
283 /// This function can only be used if the request creates a new object. Use
284 /// [`UntypedOwnedProxy::send_destructor`] or [`UntypedBorrowedProxy::send_request`]
285 /// otherwise.
286 ///
287 /// The new object will be attached to the queue of this proxy.
288 ///
289 /// # Panic
290 ///
291 /// - This function panics if this proxy has already been destroyed.
292 /// - If `DESTROY=true`, then this function might panic if the proxy is attached to a
293 /// local queue and the current thread is not the thread in which the queue was
294 /// created.
295 /// - If `DESTROY=true`, then this function panics if this proxy is a wrapper.
296 ///
297 /// # Safety
298 ///
299 /// - `opcode` must be a valid request opcode for the interface of the proxy.
300 /// - `args` must conform to the interface + opcode of the proxy.
301 /// - `args` must contain exactly one `new_id` element.
302 /// - `interface` must be a valid `wl_interface`.
303 pub unsafe fn send_constructor<const DESTROY: bool>(
304 &self,
305 opcode: u32,
306 args: &mut [wl_argument],
307 interface: &'static wl_interface,
308 version: Option<u32>,
309 ) -> Self {
310 let slf = self.data();
311 let (_read_lock, _write_lock);
312 if DESTROY {
313 if slf.interface.is_none() {
314 panic!("Proxy is a wrapper");
315 }
316 _write_lock = slf.proxy.lock.write();
317 } else {
318 _read_lock = slf.proxy.lock.read_recursive();
319 }
320 // SAFETY: We're holding at least a read lock.
321 let proxy = slf.proxy.proxy.load(Relaxed);
322 let proxy = check_dispatching_proxy(NonNull::new(proxy));
323 let version = version.unwrap_or_else(|| {
324 // SAFETY: - We're holding at least a read lock which ensures that the pointer
325 // stays valid.
326 // - We've just checked that the pointer is valid.
327 unsafe { slf.proxy.libwayland.wl_proxy_get_version(proxy.as_ptr()) }
328 });
329 let mut flags = 0;
330 if DESTROY {
331 flags |= WL_MARSHAL_FLAG_DESTROY;
332 // SAFETY: We're holding the write lock.
333 slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
334 }
335 // SAFETY: - We've just checked that proxy is not null. By the invariants, the
336 // proxy is valid.
337 // - The opcode/args requirements are forwarded to the caller.
338 // - Flags are 0 or WL_MARSHAL_FLAG_DESTROY.
339 // - If flags contains WL_MARSHAL_FLAG_DESTROY then we've checked above
340 // that the proxy is not a wrapper and we've set the proxy pointer to
341 // null.
342 let new_proxy = unsafe {
343 slf.proxy.libwayland.wl_proxy_marshal_array_flags(
344 proxy.as_ptr(),
345 opcode,
346 interface,
347 version,
348 flags,
349 args.as_mut_ptr(),
350 )
351 };
352 if DESTROY {
353 // SAFETY: - We're holding the write lock of the proxy.
354 // - The proxy has been destroyed.
355 unsafe {
356 self.destroy_event_handler();
357 }
358 }
359 let new_proxy = check_new_proxy(new_proxy);
360 // SAFETY: - new_proxy was returned by libwayland and we've just checked that it
361 // is not null
362 // - we're passing ownership
363 // - proxy was just created so it doesn't have a dispatcher
364 // - wl_proxy_marshal_array_flags attaches new proxy to the same queue as
365 // the input proxy
366 // - wl_proxy_marshal_array_flags sets the interface of the proxy to the
367 // interface passed into the function
368 unsafe { UntypedOwnedProxy::from_plain_wl_proxy(&slf.queue, new_proxy, interface) }
369 }
370
371 pub(crate) fn set_event_handler<T>(&self, handler: T)
372 where
373 T: EventHandler + Send + 'static,
374 {
375 // SAFETY: T implements Send.
376 unsafe {
377 self.set_event_handler2(handler);
378 }
379 }
380
381 pub(crate) fn set_event_handler_local<T>(&self, handler: T)
382 where
383 T: EventHandler + 'static,
384 {
385 if self.data().queue.is_non_local() {
386 panic!("Queue is not a local queue");
387 }
388 // SAFETY: We've just checked that the queue is thread local.
389 unsafe {
390 self.set_event_handler2(handler);
391 }
392 }
393
394 /// # Safety
395 ///
396 /// If T does not implement Send, then the queue must be a local queue.
397 unsafe fn set_event_handler2<T>(&self, event_handler: T)
398 where
399 T: EventHandler + 'static,
400 {
401 // SAFETY: - all requirements except the callability of event_handler_func as part
402 // of a libwayland dispatch are trivially satisfied
403 // - libwayland only ever calls event handlers while preserving a
404 // valid pointer to the proxy and all pointers in args
405 // - set_event_handler4 checks that the interface of the proxy is
406 // T::WL_INTERFACE
407 // - libwayland ensures that opcode and args conform to the
408 // interface before calling the event handler
409 // - set_event_handler4 sets event_handler to a pointer to T
410 // - we only ever invalidate the self.event_handler or self.data
411 // pointers while the queue is idle and after having destroyed
412 // the proxy.
413 // - if T is not Send, then this function requires that this is a
414 // local queue which will panic when trying to call this function
415 // or any dispatching function on a thread other than the thread
416 // on which the queue was created
417 // - we always hold the queue lock while dispatching
418 unsafe {
419 self.set_event_handler3(event_handler, event_handler_func::<T>, None);
420 }
421 }
422
423 /// # Safety
424 ///
425 /// - if T does not implement Send, then the queue must be a local queue
426 /// - the safety requirements of event_handler_func must be satisfied whenever it is
427 /// called
428 /// - if scope is Some, then either
429 /// - the event handler must be destroyed before the end of 'scope, OR
430 /// - ScopeData::handle_destruction must never run the destructions
431 unsafe fn set_event_handler3<'scope, T>(
432 &self,
433 event_handler: T,
434 event_handler_func: wl_dispatcher_func_t,
435 scope: Option<&'scope Scope<'scope, '_>>,
436 ) where
437 T: EventHandler,
438 {
439 unsafe fn drop<T>(event_handler: *mut u8) {
440 // SAFETY: This function is called only to drop the boxed event_handler.
441 unsafe {
442 let _ = Box::from_raw(event_handler.cast::<T>());
443 }
444 }
445
446 let event_handler = Box::into_raw(Box::new(event_handler)).cast();
447 let dealloc = on_drop(move || {
448 // SAFETY: - This is only called if set_event_handler4 panics, otherwise the
449 // on_drop is forgotten.
450 // - If set_event_handler4 panics, then it has not assumed ownership
451 // of the event handler.
452 unsafe { drop::<T>(event_handler) }
453 });
454 // SAFETY: - interface is T::WL_INTERFACE
455 // - event_handler is a pointer to T
456 // - we've called Box::into_raw on the event handler so it stays valid
457 // valid pointer to the proxy and all pointers in args
458 // - drop_event_handler is a pointer to the deallocator
459 // - the other requirements are forwarded to the caller of this function
460 unsafe {
461 self.set_event_handler4(
462 T::WL_INTERFACE,
463 T::mutable_type(),
464 event_handler,
465 drop::<T> as *mut u8,
466 mem::needs_drop::<T>(),
467 event_handler_func,
468 scope,
469 )
470 }
471 dealloc.forget();
472 }
473
474 /// This function verifies the following:
475 ///
476 /// - `event_handler_func` is only called as part of a libwayland dispatch
477 /// - this proxy has the interface `interface`.
478 /// - if `mutable_data_type` is Some, then it is the type of `()` or the type returned
479 /// by [Queue::mut_data_type] of [Self::queue].
480 ///
481 /// # Safety
482 ///
483 /// There must be a type `T: EventHandler` such that
484 ///
485 /// - interface is T::WL_INTERFACE
486 /// - mutable_data_type is T::mutable_type()
487 /// - event_handler is a pointer to a T
488 /// - if T does not implement Send, then the queue must be a local queue
489 /// - event_handler must stay valid until drop_event handler is called
490 /// - drop_event_handler is a pointer to a unsafe fn(*mut u8)
491 /// that can be called once with event_handler
492 /// - the safety requirements of event_handler_func must be satisfied whenever it is
493 /// called by libwayland as part of a dispatch
494 /// - if scope is Some, then either
495 /// - the event handler must be destroyed before the end of 'scope, OR
496 /// - ScopeData::handle_destruction must never run the destructions
497 #[expect(clippy::too_many_arguments)]
498 unsafe fn set_event_handler4<'scope>(
499 &self,
500 interface: &'static wl_interface,
501 mutable_data_type: Option<(TypeId, &'static str)>,
502 event_handler: *mut u8,
503 drop_event_handler: *mut u8,
504 needs_drop: bool,
505 event_handler_func: wl_dispatcher_func_t,
506 scope: Option<&'scope Scope<'scope, '_>>,
507 ) {
508 let slf = self.data();
509 match slf.interface {
510 None => panic!("Proxy is a wrapper"),
511 Some(i) => {
512 // SAFETY: EventHandler::WL_INTERFACE and slf.interface are always valid
513 // interfaces.
514 let compatible = unsafe { interface_compatible(i, interface) };
515 if !compatible {
516 panic!("Proxy has an incompatible interface");
517 }
518 }
519 }
520 'check_mutable_data: {
521 let Some((mutable_data_type, mutable_data_type_name)) = mutable_data_type else {
522 break 'check_mutable_data;
523 };
524 if mutable_data_type == TypeId::of::<()>() {
525 break 'check_mutable_data;
526 }
527 let (mut_data_type, mut_data_type_name) = slf.queue.mut_data_type();
528 if Some(mutable_data_type) == mut_data_type {
529 break 'check_mutable_data;
530 }
531 if let Some(name) = mut_data_type_name {
532 panic!(
533 "This queue only supports mutable data of type `{name}` but the \
534 event handler requires type `{mutable_data_type_name}`",
535 );
536 } else {
537 panic!(
538 "This queue does not support mutable data but the event handler \
539 requires type `{mutable_data_type_name}`",
540 );
541 }
542 };
543 let lock = slf.proxy.lock();
544 let proxy = check_dispatching_proxy(lock.wl_proxy());
545 if slf.ever_had_event_handler.swap(true, Relaxed) {
546 panic!("Proxy already has an event handler");
547 }
548 if let Some(scope) = scope {
549 *slf.scope_data_arc.lock() = Some(scope.data.clone());
550 slf.scope_data
551 .store(ptr::from_ref(&*scope.data).cast_mut(), Relaxed);
552 }
553 if needs_drop {
554 slf.stored_in_registry.store(true, Relaxed);
555 // SAFETY: - self.data is only ever invalidated via self.create_destruction which
556 // will remove self.data from the registry.
557 // - we just wrote to the scope_data field in this thread.
558 unsafe {
559 self.modify_owned_registry(|r| {
560 r.insert(self.data);
561 });
562 }
563 }
564 let _queue_lock = slf.queue.lock_dispatch();
565 slf.event_handler.store(event_handler, Relaxed);
566 slf.drop_event_handler.store(drop_event_handler, Relaxed);
567 // SAFETY: - we're holding the proxy lock so the proxy is valid
568 // - we're holding the queue lock which is always held when
569 // accessing/modifying the unprotected fields of the wl_proxy
570 // - by the safety requirements of this function, the safety
571 // requirements of event_handler_func are satisfied whenever it is
572 // called by libwayland as part of a dispatch; and the function set
573 // through this call is only ever called as part of a dispatch.
574 unsafe {
575 slf.proxy.libwayland.wl_proxy_add_dispatcher(
576 proxy.as_ptr(),
577 Some(event_handler_func),
578 self.data.as_ptr() as *mut c_void,
579 ptr::null_mut(),
580 );
581 }
582 }
583
584 /// Returns the queue of this proxy.
585 ///
586 /// This is the same queue that was passed into the constructor of this object.
587 #[inline]
588 pub fn queue(&self) -> &Queue {
589 &self.data().queue
590 }
591
592 /// Destroys a proxy without sending a wayland message.
593 ///
594 /// This function only destroys the proxy in libwayland without sending a message to the
595 /// compositor.
596 ///
597 /// # Panic
598 ///
599 /// This function might panic if the proxy is attached to a local queue and the current
600 /// thread is not the thread in which the queue was created.
601 #[inline]
602 pub fn destroy(&self) {
603 let slf = self.data();
604 let _lock = slf.proxy.lock.write();
605 if slf.proxy.proxy.load(Relaxed).is_null() {
606 return;
607 }
608 // SAFETY: We're holding the write lock.
609 unsafe {
610 self.destroy_proxy();
611 }
612 // SAFETY: - We're holding the write lock of the proxy.
613 // - The proxy has been destroyed.
614 unsafe {
615 self.destroy_event_handler();
616 }
617 }
618
619 /// Destroys the proxy if it is not already destroyed.
620 ///
621 /// # Safety
622 ///
623 /// - The caller must have exclusive access to the proxy pointer.
624 unsafe fn destroy_proxy(&self) {
625 let slf = self.data();
626 // SAFETY: By the requirements of this function we have exclusive access to the
627 // pointer.
628 let proxy = slf.proxy.proxy.load(Relaxed);
629 if proxy.is_null() {
630 return;
631 }
632 // SAFETY: By the requirements of this function we have exclusive access to the
633 // pointer.
634 slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
635 if slf.interface.is_none() {
636 // SAFETY: - By the requirements of the function, we have exclusive write
637 // access to the pointer.
638 // - We've just checked that the pointer is not null. By the
639 // invariants of UntypedBorrowedProxy, this means that the pointer
640 // is valid.
641 // - By the invariants of this type, since the interface is None,
642 // the proxy is a wrapper.
643 unsafe {
644 slf.proxy.libwayland.wl_proxy_wrapper_destroy(proxy.cast());
645 }
646 } else {
647 // SAFETY: - By the requirements of the function, we have exclusive write
648 // access to the pointer.
649 // - We've just checked that the pointer is not null. By the
650 // invariants of UntypedBorrowedProxy, this means that the pointer
651 // is valid.
652 // - By the invariants of this type, since the interface is Some,
653 // the proxy is not a wrapper.
654 unsafe {
655 slf.proxy.libwayland.wl_proxy_destroy(proxy);
656 }
657 }
658 }
659
660 /// Creates a [`ProxyDataDestruction`] destroying parts of this object.
661 ///
662 /// If the proxy has an event handler with a Drop impl attached, the destruction will
663 /// drop that event handler.
664 ///
665 /// If `destroy_proxy_data` is true, then the destruction will destroy the
666 /// [`UntypedOwnedProxyData`].
667 ///
668 /// # Safety
669 ///
670 /// - The caller must have exclusive access to the proxy pointer.
671 unsafe fn create_destruction(&self, destroy_proxy_data: bool) -> ProxyDataDestruction {
672 let slf = self.data();
673 let data = destroy_proxy_data.then_some(self.data);
674 let drop_event_handler = {
675 // SAFETY: - By the safety requirements of this function, the caller has
676 // exclusive access to the proxy pointer which ensures visibility
677 // of the drop_event_handler and event_handler fields.
678 let drop_event_handler = slf.drop_event_handler.load(Relaxed);
679 if drop_event_handler.is_null() {
680 None
681 } else {
682 slf.drop_event_handler.store(ptr::null_mut(), Relaxed);
683 Some((
684 SyncPtr(slf.event_handler.load(Relaxed)),
685 SyncPtr(drop_event_handler),
686 ))
687 }
688 };
689 let destruction = ProxyDataDestruction::new(data, drop_event_handler);
690 if slf.stored_in_registry.load(Relaxed) {
691 // SAFETY: - We've just created a destruction fo the event handler if it exists.
692 // - By the safety requirements of this function, the caller has
693 // exclusive access to the proxy pointer.
694 unsafe {
695 self.modify_owned_registry(|r| {
696 r.remove(&self.data);
697 });
698 }
699 slf.stored_in_registry.store(false, Relaxed);
700 }
701 destruction
702 }
703
704 /// # Safety
705 ///
706 /// - All pointers in the registry must be valid.
707 /// - If a proxy has an event handler, it must not be removed from the registry before
708 /// a destruction has been created for the event handler.
709 /// - The caller must have exclusive access to the proxy pointer or must ensure that
710 /// writes to the scope_data field happen before this call.
711 unsafe fn modify_owned_registry(
712 &self,
713 f: impl FnOnce(&mut HashSet<SyncNonNull<UntypedOwnedProxyData>>),
714 ) {
715 // SAFETY: The requirement is forwarded to the caller.
716 let scope = unsafe { self.scope() };
717 let mut registry = if let Some(scope) = scope {
718 scope.registry.proxies.lock()
719 } else {
720 self.data().queue.owned_proxy_registry().proxies.lock()
721 };
722 f(&mut registry)
723 }
724
725 /// # Safety
726 ///
727 /// - This must only be called from `drop` once the ref count reaches 0.
728 /// - The effects of other threads must have been made visible.
729 #[inline(never)]
730 unsafe fn drop_slow(&self) {
731 // SAFETY: Since the ref count has reached 0, there are no longer any accessible
732 // UntypedOwnedProxy referring to the UntypedOwnedProxyData. Since the
733 // UntypedOwnedProxyData contains the UntypedBorrowedProxy by value, there can
734 // be no other references to the proxy pointer.
735 unsafe {
736 self.destroy_proxy();
737 }
738 // SAFETY: We have exclusive access to the proxy pointer.
739 let destruction = unsafe { self.create_destruction(true) };
740 let slf = self.data();
741 // SAFETY: We have exclusive access to the proxy pointer.
742 let scope = unsafe { self.scope() };
743 if let Some(scope) = scope {
744 let _scope = slf.scope_data_arc.lock().clone();
745 // SAFETY: - scope() returns the scope that this proxy is attached to.
746 // - If the destruction contains an event handler, then, by the safety
747 // requirements of set_event_handler4, we know that
748 // - we are either within 'scope since otherwise
749 // destroy_event_handler would have been called and consumed the
750 // event handler earlier, OR
751 // - handle_destruction is a no-op.
752 // If handle_destruction never runs any of the destructions, there
753 // is nothing to show. Otherwise running the drop impl of the event
754 // handler is safe as soon as it is no longer referenced anywhere
755 // since the event handler outlives 'scope.
756 // - Since the proxy is destroyed, once there are no ongoing
757 // dispatches, there wont ever again be any dispatches.
758 // - The _scope variable above ensures that the scope remains valid
759 // for the duration of the function call.
760 unsafe {
761 scope.handle_destruction(destruction);
762 }
763 } else if slf.ever_had_event_handler.load(Relaxed) {
764 let queue = slf.queue.clone();
765 // SAFETY: - We've just destroyed the proxy above.
766 // - By the invariants, the proxy is attached to slf.queue.
767 // - When the queue runs the destruction, no dispatches will be
768 // running and all subsequent dispatches will happen after this line
769 // of code.
770 // - Therefore, libwayland will see that we've destroyed the proxy and
771 // will not call into the event handler.
772 unsafe {
773 queue.run_destruction_on_idle(destruction);
774 }
775 } else {
776 // SAFETY: - If ever_had_event_handler is false, then neither the queue nor
777 // libwayland ever had a reference to this object.
778 unsafe {
779 destruction.run();
780 }
781 }
782 }
783
784 /// # Safety
785 ///
786 /// - The caller must have exclusive access to the proxy pointer.
787 /// - If the proxy is not yet destroyed then it must have a scope and the event
788 /// handler must not be dispatched again.
789 #[inline(never)]
790 unsafe fn destroy_event_handler(&self) {
791 // SAFETY: By the safety requirements of this function, we have exclusive access
792 // to the proxy pointer.
793 let destruction = unsafe { self.create_destruction(false) };
794 if destruction.is_noop() {
795 return;
796 }
797 // SAFETY: By the safety requirements of this function, we have exclusive access
798 // to the proxy pointer.
799 let scope = unsafe { self.scope() };
800 if let Some(scope) = scope {
801 // SAFETY: - scope() returns the scope that this proxy is attached to.
802 // - Since the destruction is not a no-op, we know that this is the
803 // first call to destroy_event_handler.
804 // - By the safety requirements of set_event_handler4, we know that
805 // either we are within 'scope or the destruction is never run. If
806 // the destruction is never run, then there is nothing to show.
807 // Otherwise, since the event handler outlives 'scope, calling its
808 // drop impl is safe if it is no longer reference anywhere.
809 // - If the proxy is destroyed, then, once there are no ongoing
810 // dispatches, there wont ever again be any dispatches.
811 // - Otherwise, since the event handler is never again dispatched, once
812 // there are no ongoing dispatches, it is safe to destroy it.
813 unsafe {
814 scope.handle_destruction(destruction);
815 }
816 } else {
817 // SAFETY: - This function requires that the proxy is already destroyed.
818 // - By the invariants, the proxy is attached to self.data().queue.
819 // - When the queue runs the destruction, no dispatches will be
820 // running and all subsequent dispatches will happen after this line
821 // of code.
822 // - Therefore, libwayland will see that we've destroyed the proxy and
823 // will not call into the event handler.
824 // - This call cannot possibly invalidate self.data, even if dropping the
825 // event handler recursively drops an UntypedOwnedProxy, since we're holding
826 // on to an UntypedOwnedProxy. Therefore self.data().queue remains valid
827 // for the function call.
828 unsafe {
829 self.data().queue.run_destruction_on_idle(destruction);
830 }
831 }
832 }
833
834 /// # Safety
835 ///
836 /// - The caller must have exclusive access to the proxy pointer or must ensure that
837 /// writes to the scope_data field happen before this call.
838 unsafe fn scope(&self) -> Option<&ScopeData> {
839 NonNull::new(self.data().scope_data.load(Relaxed)).map(|s| {
840 // SAFETY: See the documentation of scope_data for why this is safe.
841 unsafe { s.as_ref() }
842 })
843 }
844}
845
846impl Clone for UntypedOwnedProxy {
847 fn clone(&self) -> Self {
848 let slf = self.data();
849 if slf.ref_count.fetch_add(1, Relaxed) > usize::MAX / 2 {
850 std::process::abort();
851 }
852 Self { data: self.data }
853 }
854}
855
856impl Drop for UntypedOwnedProxy {
857 #[inline]
858 fn drop(&mut self) {
859 let slf = self.data();
860 if slf.ref_count.fetch_sub(1, Release) == 1 {
861 fence(Acquire);
862 // SAFETY: - we're in the drop impl
863 // - the acquire fence ensures visibility
864 unsafe {
865 self.drop_slow();
866 }
867 }
868 }
869}
870
871impl OwnedProxyRegistry {
872 /// Destroys all proxies in this registry.
873 pub(crate) fn destroy_all(&self) {
874 for proxy in self.get_todos() {
875 proxy.destroy();
876 }
877 }
878
879 /// # Safety
880 ///
881 /// - All proxies in the registry must belong to a single scope.
882 /// - We must be within the lifetime of the scope.
883 /// - The queue lock must be held.
884 /// - For all of the event handlers attached to proxies in the registry:
885 /// - The event handlers must not current be being dispatched.
886 /// - The event handlers must not be dispatched in the future.
887 unsafe fn destroy_event_handlers(&self) {
888 for proxy in self.get_todos() {
889 let _write_lock = proxy.lock.write();
890 // SAFETY: - We're holding the write lock of the proxy.
891 // - By the safety requirements of this function, the event handlers
892 // are currently not being dispatched and will not be dispatched in
893 // the future.
894 unsafe {
895 proxy.destroy_event_handler();
896 }
897 }
898 }
899
900 fn get_todos(&self) -> Vec<UntypedOwnedProxy> {
901 let proxies = &mut *self.proxies.lock();
902 self.get_todos_locked(proxies)
903 }
904
905 fn get_todos_locked(
906 &self,
907 proxies: &mut HashSet<SyncNonNull<UntypedOwnedProxyData>>,
908 ) -> Vec<UntypedOwnedProxy> {
909 let mut todo = Vec::with_capacity(proxies.len());
910 for proxy in &*proxies {
911 // SAFETY: By the invariants, all pointers in the hash set are valid.
912 let data = unsafe { &*proxy.as_ptr() };
913 let mut ref_count = data.ref_count.load(Relaxed);
914 while ref_count != 0 {
915 if ref_count > usize::MAX / 2 {
916 std::process::abort();
917 }
918 let res = data.ref_count.compare_exchange_weak(
919 ref_count,
920 ref_count + 1,
921 Relaxed,
922 Relaxed,
923 );
924 match res {
925 Ok(_) => {
926 // SAFETY: We've just acquire a strong reference.
927 todo.push(UntypedOwnedProxy { data: *proxy });
928 break;
929 }
930 Err(c) => ref_count = c,
931 }
932 }
933 }
934 *proxies = HashSet::default();
935 todo
936 }
937}
938
939/// An event handler that can handle raw libwayland events.
940///
941/// # Safety
942///
943/// - `WL_INTERFACE` must be a valid wl_interface.
944/// - `mutable_type` must always return the same value.
945pub unsafe trait EventHandler {
946 /// The type of interface that can be handled by this event handler.
947 const WL_INTERFACE: &'static wl_interface;
948
949 /// Returns the mutable data type required by this event handler.
950 #[inline]
951 fn mutable_type() -> Option<(TypeId, &'static str)> {
952 None
953 }
954
955 /// Dispatches a raw libwayland event.
956 ///
957 /// # Safety
958 ///
959 /// - `slf` must have an interface compatible with `WL_INTERFACE`.
960 /// - `opcode` and `args` must conform to an event of `WL_INTERFACE`.
961 /// - Any objects contained in `args` must remain valid for the duration of the call.
962 /// - If `Self::mutable_data` returns `Some`, then `data` must be `&mut T` where `T`
963 /// has the type ID returned by `mutable_data`.
964 unsafe fn handle_event(
965 &self,
966 queue: &Queue,
967 data: *mut u8,
968 slf: &UntypedBorrowedProxy,
969 opcode: u32,
970 args: *mut wl_argument,
971 );
972}
973
974/// The event handler function.
975///
976/// This function is called by libwayland when dispatching an event for the proxy. This
977/// function is only called when the proxy's queue is explicitly being dispatched.
978///
979/// # Safety
980///
981/// - target must be a valid wl_proxy pointer
982/// - the interface of target must be compatible with T::WL_INTERFACE
983/// - event_handler_data must be a pointer to UntypedOwnedProxyData
984/// - the event_handler field in the UntypedOwnedProxy must contain a pointer to T
985/// - opcode and args must conform to T::WL_INTERFACE
986/// - all pointers must remain valid for the duration of this function call
987/// - the previous point includes pointers inside args
988/// - if T is not `Send`, then the current thread must be the thread on which the
989/// event handler was attached
990/// - the queue lock of the proxy must be held
991/// - this must only be called by libwayland as part of an event handler dispatch of the
992/// proxy stored in target
993unsafe extern "C" fn event_handler_func<T>(
994 event_handler_data: *const c_void,
995 target: *mut c_void,
996 opcode: u32,
997 _msg: *const wl_message,
998 args: *mut wl_argument,
999) -> c_int
1000where
1001 T: EventHandler,
1002{
1003 // SAFETY: By the safety requirements of this function, event_handler is a valid pointer
1004 // to UntypedOwnedProxyData.
1005 let proxy_data = unsafe { &*(event_handler_data as *const UntypedOwnedProxyData) };
1006 // SAFETY: Dito, target is and stays valid.
1007 let target = unsafe { NonNull::new_unchecked(target.cast()) };
1008 // SAFETY: Dito, target is and stays valid.
1009 let target =
1010 unsafe { UntypedBorrowedProxy::new_immutable(proxy_data.proxy.libwayland, target) };
1011 let event_handler = proxy_data.event_handler.load(Relaxed).cast::<T>();
1012 // SAFETY: - Dito, event_handler is a valid pointer to T
1013 // - Dito, this function is never called concurrently, therefore it doesn't matter if
1014 // T implements Sync.
1015 // - Dito, if T does not implement Send, then we're creating this reference only in the
1016 // same thread on which the event_handler was attached.
1017 let event_handler = unsafe { &*event_handler };
1018 // SAFETY: - Dito, the queue mutex is held.
1019 let data = unsafe { proxy_data.queue.data() };
1020 let res = catch_unwind(AssertUnwindSafe(|| {
1021 // SAFETY: - Dito, the interface of target is compatible with T::WL_INTERFACE
1022 // - Dito, target is a valid pointer and stays valid
1023 // - Dito, opcode and args conform to T::WL_INTERFACE
1024 // - Dito, we're being called by libwayland as part of a libwayland
1025 // dispatch. If `T::mutable_data` returns `Some`, then Queue::data
1026 // guarantees that `data` can be dereferenced to that type.
1027 unsafe {
1028 event_handler.handle_event(&proxy_data.queue, data, &target, opcode, args);
1029 }
1030 }));
1031 if let Err(e) = res {
1032 DISPATCH_PANIC.set(Some(e));
1033 }
1034 0
1035}
1036
1037thread_local! {
1038 pub(crate) static DISPATCH_PANIC: Cell<Option<Box<dyn Any + Send>>> = const { Cell::new(None) };
1039}