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