From 8002ddd167174f30108d9b3b81cf80578b54609b Mon Sep 17 00:00:00 2001 From: Marco Mastropaolo Date: Tue, 18 Jun 2024 16:39:29 +0200 Subject: [PATCH] Fixes a minor race condition in active_displays (#686) Fixes a minor race condition in active_displays that might happen if a display is removed between the active_display_count and the CGGetActiveDisplayList. In that case the returned vec would be inconsistent and contain one (or more) spurious null displays. Note: the returned value will always be subject to TOC/TOU, of course, but this specific case has the returned value containing invalid displays with id=0 that were never supposed to be in the returned value in any possible state of the displays; this commit fixes this case. --- core-graphics/src/display.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core-graphics/src/display.rs b/core-graphics/src/display.rs index 9592dc4..daceb8f 100644 --- a/core-graphics/src/display.rs +++ b/core-graphics/src/display.rs @@ -460,10 +460,15 @@ impl CGDisplay { /// Provides a list of displays that are active (or drawable). #[inline] pub fn active_displays() -> Result, CGError> { - let count = CGDisplay::active_display_count()?; - let mut buf: Vec = vec![0; count as usize]; - let result = unsafe { CGGetActiveDisplayList(count, buf.as_mut_ptr(), ptr::null_mut()) }; + let expected_count = CGDisplay::active_display_count()?; + let mut buf: Vec = vec![0; expected_count as usize]; + + let mut actual_count: u32 = 0; + + let result = + unsafe { CGGetActiveDisplayList(expected_count, buf.as_mut_ptr(), &mut actual_count) }; if result == 0 { + buf.truncate(actual_count as usize); Ok(buf) } else { Err(result)