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