1 // Copyright 2024 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::os::fd::AsRawFd; 6 7 use tokio::io::unix::AsyncFd; 8 9 /// An async version of `base::Event`. 10 pub struct EventTokio(AsyncFd<base::SafeDescriptor>); 11 12 impl EventTokio { 13 /// WARNING: Sets O_NONBLOCK internally, which will also affect all clones of the `Event`. new(event: base::Event) -> anyhow::Result<Self>14 pub fn new(event: base::Event) -> anyhow::Result<Self> { 15 let fd: base::SafeDescriptor = event.into(); 16 base::add_fd_flags(fd.as_raw_fd(), libc::O_NONBLOCK)?; 17 Ok(Self(AsyncFd::new(fd)?)) 18 } 19 20 /// Blocks until the event is signaled and clears the signal. 21 /// 22 /// It is undefined behavior to wait on an event from multiple threads or processes 23 /// simultaneously. wait(&self) -> std::io::Result<()>24 pub async fn wait(&self) -> std::io::Result<()> { 25 loop { 26 let mut guard = self.0.readable().await?; 27 let io_result = guard.try_io(|inner| { 28 let mut buf: u64 = 0; 29 // SAFETY: This is safe because we made this fd and the pointer we pass can not 30 // overflow because we give the syscall's size parameter properly. 31 let ret = unsafe { 32 libc::read( 33 inner.as_raw_fd(), 34 &mut buf as *mut u64 as *mut libc::c_void, 35 std::mem::size_of::<u64>(), 36 ) 37 }; 38 if ret < 0 { 39 return Err(std::io::Error::last_os_error()); 40 } 41 if ret as usize != std::mem::size_of::<u64>() { 42 return Err(std::io::Error::from(std::io::ErrorKind::UnexpectedEof)); 43 } 44 Ok(()) 45 }); 46 47 match io_result { 48 Ok(result) => return result, 49 Err(_would_block) => continue, 50 } 51 } 52 } 53 } 54