compio_process/
windows.rs

1use std::{
2    io,
3    os::windows::{io::AsRawHandle, process::ExitStatusExt},
4    pin::Pin,
5    process,
6    task::Poll,
7};
8
9use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut};
10use compio_driver::{
11    AsRawFd, OpCode, OpType, RawFd, SharedFd, ToSharedFd,
12    op::{BufResultExt, Recv, Send},
13    syscall,
14};
15use compio_io::{AsyncRead, AsyncWrite};
16use windows_sys::Win32::System::{IO::OVERLAPPED, Threading::GetExitCodeProcess};
17
18use crate::{ChildStderr, ChildStdin, ChildStdout};
19
20struct WaitProcess {
21    child: process::Child,
22}
23
24impl WaitProcess {
25    pub fn new(child: process::Child) -> Self {
26        Self { child }
27    }
28}
29
30impl OpCode for WaitProcess {
31    fn op_type(&self) -> OpType {
32        OpType::Event(self.child.as_raw_handle() as _)
33    }
34
35    unsafe fn operate(self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
36        let mut code = 0;
37        syscall!(
38            BOOL,
39            GetExitCodeProcess(self.child.as_raw_handle() as _, &mut code)
40        )?;
41        Poll::Ready(Ok(code as _))
42    }
43}
44
45pub async fn child_wait(child: process::Child) -> io::Result<process::ExitStatus> {
46    let op = WaitProcess::new(child);
47    let code = compio_runtime::submit(op).await.0?;
48    Ok(process::ExitStatus::from_raw(code as _))
49}
50
51impl AsRawFd for ChildStdout {
52    fn as_raw_fd(&self) -> RawFd {
53        self.0.as_raw_fd()
54    }
55}
56
57impl ToSharedFd<process::ChildStdout> for ChildStdout {
58    fn to_shared_fd(&self) -> SharedFd<process::ChildStdout> {
59        self.0.to_shared_fd()
60    }
61}
62
63impl AsyncRead for ChildStdout {
64    async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
65        let fd = self.to_shared_fd();
66        let op = Recv::new(fd, buffer);
67        compio_runtime::submit(op).await.into_inner().map_advanced()
68    }
69}
70
71impl AsRawFd for ChildStderr {
72    fn as_raw_fd(&self) -> RawFd {
73        self.0.as_raw_fd()
74    }
75}
76
77impl ToSharedFd<process::ChildStderr> for ChildStderr {
78    fn to_shared_fd(&self) -> SharedFd<process::ChildStderr> {
79        self.0.to_shared_fd()
80    }
81}
82
83impl AsyncRead for ChildStderr {
84    async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
85        let fd = self.to_shared_fd();
86        let op = Recv::new(fd, buffer);
87        compio_runtime::submit(op).await.into_inner().map_advanced()
88    }
89}
90
91impl AsRawFd for ChildStdin {
92    fn as_raw_fd(&self) -> RawFd {
93        self.0.as_raw_fd()
94    }
95}
96
97impl ToSharedFd<process::ChildStdin> for ChildStdin {
98    fn to_shared_fd(&self) -> SharedFd<process::ChildStdin> {
99        self.0.to_shared_fd()
100    }
101}
102
103impl AsyncWrite for ChildStdin {
104    async fn write<T: IoBuf>(&mut self, buffer: T) -> BufResult<usize, T> {
105        let fd = self.to_shared_fd();
106        let op = Send::new(fd, buffer);
107        compio_runtime::submit(op).await.into_inner()
108    }
109
110    async fn flush(&mut self) -> io::Result<()> {
111        Ok(())
112    }
113
114    async fn shutdown(&mut self) -> io::Result<()> {
115        Ok(())
116    }
117}