• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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