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.
This commit is contained in:
Marco Mastropaolo
2024-06-18 16:39:29 +02:00
committed by GitHub
parent 6940925635
commit 8002ddd167
+8 -3
View File
@@ -460,10 +460,15 @@ impl CGDisplay {
/// Provides a list of displays that are active (or drawable).
#[inline]
pub fn active_displays() -> Result<Vec<CGDirectDisplayID>, CGError> {
let count = CGDisplay::active_display_count()?;
let mut buf: Vec<CGDirectDisplayID> = 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<CGDirectDisplayID> = 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)