1 // Copyright 2022 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::ffi::CString; 6 use std::mem::MaybeUninit; 7 use std::os::windows::io::AsRawHandle; 8 use std::os::windows::io::RawHandle; 9 use std::ptr::null; 10 use std::time::Duration; 11 12 use serde::Deserialize; 13 use serde::Serialize; 14 use win_util::SecurityAttributes; 15 use win_util::SelfRelativeSecurityDescriptor; 16 use winapi::shared::minwindef::DWORD; 17 use winapi::shared::minwindef::FALSE; 18 use winapi::shared::minwindef::TRUE; 19 use winapi::shared::winerror::WAIT_TIMEOUT; 20 use winapi::um::handleapi::DuplicateHandle; 21 use winapi::um::processthreadsapi::GetCurrentProcess; 22 use winapi::um::synchapi::CreateEventA; 23 use winapi::um::synchapi::OpenEventA; 24 use winapi::um::synchapi::ResetEvent; 25 use winapi::um::synchapi::SetEvent; 26 use winapi::um::synchapi::WaitForSingleObject; 27 use winapi::um::winbase::INFINITE; 28 use winapi::um::winbase::WAIT_FAILED; 29 use winapi::um::winbase::WAIT_OBJECT_0; 30 use winapi::um::winnt::DUPLICATE_SAME_ACCESS; 31 use winapi::um::winnt::EVENT_MODIFY_STATE; 32 use winapi::um::winnt::HANDLE; 33 34 use super::errno_result; 35 use super::Error; 36 use super::RawDescriptor; 37 use super::Result; 38 use crate::descriptor::AsRawDescriptor; 39 use crate::descriptor::FromRawDescriptor; 40 use crate::descriptor::IntoRawDescriptor; 41 use crate::descriptor::SafeDescriptor; 42 use crate::Event; 43 use crate::EventWaitResult; 44 45 /// A safe wrapper around Windows synchapi methods used to mimic Linux eventfd (man 2 eventfd). 46 /// Since the eventfd isn't using "EFD_SEMAPHORE", we don't need to keep count so we can just use 47 /// events. 48 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] 49 #[serde(transparent)] 50 pub(crate) struct PlatformEvent { 51 event_handle: SafeDescriptor, 52 } 53 54 pub trait EventExt { new_auto_reset() -> Result<Event>55 fn new_auto_reset() -> Result<Event>; open(name: &str) -> Result<Event>56 fn open(name: &str) -> Result<Event>; create_event_with_name(name: &str) -> Result<Event>57 fn create_event_with_name(name: &str) -> Result<Event>; 58 } 59 60 impl EventExt for Event { new_auto_reset() -> Result<Event>61 fn new_auto_reset() -> Result<Event> { 62 PlatformEvent::new_with_manual_reset(false).map(Event) 63 } 64 open(name: &str) -> Result<Event>65 fn open(name: &str) -> Result<Event> { 66 PlatformEvent::open(name).map(Event) 67 } 68 create_event_with_name(name: &str) -> Result<Event>69 fn create_event_with_name(name: &str) -> Result<Event> { 70 PlatformEvent::create_event_with_name(name).map(Event) 71 } 72 } 73 74 impl PlatformEvent { new_with_manual_reset(manual_reset: bool) -> Result<PlatformEvent>75 pub fn new_with_manual_reset(manual_reset: bool) -> Result<PlatformEvent> { 76 // SAFETY: Safe because return value is checked. 77 let handle = unsafe { 78 CreateEventA( 79 SecurityAttributes::new_with_security_descriptor( 80 SelfRelativeSecurityDescriptor::get_singleton(), 81 /* inherit= */ false, 82 ) 83 .as_mut(), 84 if manual_reset { TRUE } else { FALSE }, 85 FALSE, // initial state = unsignalled 86 null(), 87 ) 88 }; 89 if handle.is_null() { 90 return errno_result(); 91 } 92 Ok(PlatformEvent { 93 event_handle: 94 // SAFETY: Safe because the descriptor is valid. 95 unsafe { SafeDescriptor::from_raw_descriptor(handle) }, 96 }) 97 } 98 create_event_with_name(name: &str) -> Result<PlatformEvent>99 pub fn create_event_with_name(name: &str) -> Result<PlatformEvent> { 100 let event_str = CString::new(String::from(name)).unwrap(); 101 // SAFETY: Safe because return value is checked. 102 let handle = unsafe { 103 CreateEventA( 104 SecurityAttributes::new_with_security_descriptor( 105 SelfRelativeSecurityDescriptor::get_singleton(), 106 /* inherit= */ false, 107 ) 108 .as_mut(), 109 FALSE, // manual_reset = false 110 FALSE, // initial state = unsignalled 111 event_str.as_ptr(), 112 ) 113 }; 114 if handle.is_null() { 115 return errno_result(); 116 } 117 Ok(PlatformEvent { 118 event_handle: 119 // SAFETY: Safe because the descriptor is valid. 120 unsafe { SafeDescriptor::from_raw_descriptor(handle) }, 121 }) 122 } 123 new() -> Result<PlatformEvent>124 pub fn new() -> Result<PlatformEvent> { 125 // Require manual reset 126 PlatformEvent::new_with_manual_reset(true) 127 } 128 open(name: &str) -> Result<PlatformEvent>129 pub fn open(name: &str) -> Result<PlatformEvent> { 130 let event_str = CString::new(String::from(name)).unwrap(); 131 // SAFETY: Safe because return value is checked. 132 let handle = unsafe { OpenEventA(EVENT_MODIFY_STATE, FALSE, event_str.as_ptr()) }; 133 if handle.is_null() { 134 return errno_result(); 135 } 136 Ok(PlatformEvent { 137 event_handle: 138 // SAFETY: Safe because the descriptor is valid. 139 unsafe { SafeDescriptor::from_raw_descriptor(handle) }, 140 }) 141 } 142 143 /// See `Event::signal`. signal(&self) -> Result<()>144 pub fn signal(&self) -> Result<()> { 145 // SAFETY: Safe because the descriptor is valid. 146 let event_result = unsafe { SetEvent(self.event_handle.as_raw_descriptor()) }; 147 if event_result == 0 { 148 return errno_result(); 149 } 150 Ok(()) 151 } 152 reset(&self) -> Result<()>153 pub fn reset(&self) -> Result<()> { 154 // SAFETY: Safe because the descriptor is valid. 155 let res = unsafe { ResetEvent(self.event_handle.as_raw_descriptor()) }; 156 if res == 0 { 157 errno_result() 158 } else { 159 Ok(()) 160 } 161 } 162 163 /// Wait for the event with an optional timeout and reset the event if it was signaled. wait_and_reset(&self, timeout: Option<Duration>) -> Result<EventWaitResult>164 fn wait_and_reset(&self, timeout: Option<Duration>) -> Result<EventWaitResult> { 165 let milliseconds = match timeout { 166 Some(timeout) => timeout.as_millis() as DWORD, 167 None => INFINITE, 168 }; 169 170 // SAFETY: 171 // Safe because we pass an event object handle owned by this PlatformEvent. 172 let wait_result = match unsafe { 173 WaitForSingleObject(self.event_handle.as_raw_descriptor(), milliseconds) 174 } { 175 WAIT_OBJECT_0 => Ok(EventWaitResult::Signaled), 176 WAIT_TIMEOUT => Ok(EventWaitResult::TimedOut), 177 WAIT_FAILED => errno_result(), 178 other => Err(Error::new(other)), 179 }?; 180 181 if wait_result == EventWaitResult::Signaled { 182 self.reset()?; 183 } 184 185 Ok(wait_result) 186 } 187 188 /// See `Event::wait`. wait(&self) -> Result<()>189 pub fn wait(&self) -> Result<()> { 190 let wait_result = self.wait_and_reset(None)?; 191 // Waiting with `INFINITE` can only return when the event is signaled or an error occurs. 192 // `EventWaitResult::TimedOut` is not valid here. 193 assert_eq!(wait_result, EventWaitResult::Signaled); 194 Ok(()) 195 } 196 197 /// See `Event::wait_timeout`. wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult>198 pub fn wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult> { 199 self.wait_and_reset(Some(timeout)) 200 } 201 try_clone(&self) -> Result<PlatformEvent>202 pub fn try_clone(&self) -> Result<PlatformEvent> { 203 let mut event_clone: HANDLE = MaybeUninit::uninit().as_mut_ptr(); 204 // SAFETY: Safe because return value is checked. 205 let duplicate_result = unsafe { 206 DuplicateHandle( 207 GetCurrentProcess(), 208 self.event_handle.as_raw_descriptor(), 209 GetCurrentProcess(), 210 &mut event_clone, 211 0, 212 0, 213 DUPLICATE_SAME_ACCESS, 214 ) 215 }; 216 if duplicate_result == 0 { 217 return errno_result(); 218 } 219 Ok( 220 // SAFETY: Safe because the descriptor is valid. 221 unsafe { PlatformEvent::from_raw_descriptor(event_clone) }, 222 ) 223 } 224 } 225 226 impl AsRawDescriptor for PlatformEvent { as_raw_descriptor(&self) -> RawDescriptor227 fn as_raw_descriptor(&self) -> RawDescriptor { 228 self.event_handle.as_raw_descriptor() 229 } 230 } 231 232 impl FromRawDescriptor for PlatformEvent { 233 // SAFETY: Safe because the descriptor is expected to be valid. from_raw_descriptor(descriptor: RawDescriptor) -> Self234 unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self { 235 PlatformEvent { 236 event_handle: SafeDescriptor::from_raw_descriptor(descriptor), 237 } 238 } 239 } 240 241 impl AsRawHandle for PlatformEvent { as_raw_handle(&self) -> RawHandle242 fn as_raw_handle(&self) -> RawHandle { 243 self.as_raw_descriptor() 244 } 245 } 246 247 impl IntoRawDescriptor for PlatformEvent { into_raw_descriptor(self) -> RawDescriptor248 fn into_raw_descriptor(self) -> RawDescriptor { 249 self.event_handle.into_raw_descriptor() 250 } 251 } 252 253 impl From<PlatformEvent> for SafeDescriptor { from(evt: PlatformEvent) -> Self254 fn from(evt: PlatformEvent) -> Self { 255 evt.event_handle 256 } 257 } 258 259 impl From<SafeDescriptor> for PlatformEvent { from(sd: SafeDescriptor) -> Self260 fn from(sd: SafeDescriptor) -> Self { 261 PlatformEvent { event_handle: sd } 262 } 263 } 264 265 // Safety: 266 // PlatformEvent is safe for send & Sync despite containing a raw handle to its 267 // file mapping object. As long as the instance to PlatformEvent stays alive, this 268 // pointer will be a valid handle. 269 unsafe impl Send for PlatformEvent {} 270 // Safety: See comments for impl Send 271 unsafe impl Sync for PlatformEvent {} 272 273 #[cfg(test)] 274 mod tests { 275 use winapi::shared::winerror::WAIT_TIMEOUT; 276 use winapi::um::winbase::INFINITE; 277 use winapi::um::winbase::WAIT_OBJECT_0; 278 279 use super::*; 280 281 #[test] new()282 fn new() { 283 PlatformEvent::new().unwrap(); 284 } 285 286 #[test] read_write()287 fn read_write() { 288 let evt = PlatformEvent::new().unwrap(); 289 evt.signal().unwrap(); 290 assert_eq!(evt.wait(), Ok(())); 291 } 292 293 #[test] read_write_auto_reset()294 fn read_write_auto_reset() { 295 let evt = PlatformEvent::new_with_manual_reset(false).unwrap(); 296 evt.signal().unwrap(); 297 298 // Wait for the notification. 299 // SAFETY: Safe because return value is checked. 300 let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), INFINITE) }; 301 assert_eq!(result, WAIT_OBJECT_0); 302 303 // The notification should have reset since we already received it. 304 // SAFETY: Safe because return value is checked. 305 let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) }; 306 assert_eq!(result, WAIT_TIMEOUT); 307 } 308 309 #[test] read_write_notifies_until_read()310 fn read_write_notifies_until_read() { 311 let evt = PlatformEvent::new().unwrap(); 312 evt.signal().unwrap(); 313 314 // Wait for the notification. 315 // SAFETY: Safe because return value is checked. 316 let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), INFINITE) }; 317 assert_eq!(result, WAIT_OBJECT_0); 318 319 // The notification should still be active because read wasn't called. 320 // SAFETY: Safe because return value is checked. 321 let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) }; 322 assert_eq!(result, WAIT_OBJECT_0); 323 324 // Read and ensure the notification has cleared. 325 evt.wait().expect("Failed to read event."); 326 // SAFETY: Safe because return value is checked. 327 let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) }; 328 assert_eq!(result, WAIT_TIMEOUT); 329 } 330 331 #[test] clone()332 fn clone() { 333 let evt = PlatformEvent::new().unwrap(); 334 let evt_clone = evt.try_clone().unwrap(); 335 evt.signal().unwrap(); 336 assert_eq!(evt_clone.wait(), Ok(())); 337 } 338 339 #[test] timeout()340 fn timeout() { 341 let evt = PlatformEvent::new().expect("failed to create event"); 342 assert_eq!( 343 evt.wait_timeout(Duration::from_millis(1)) 344 .expect("failed to read from event with timeout"), 345 EventWaitResult::TimedOut 346 ); 347 } 348 } 349