compio_process/
windows.rs1use 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 OpCode, OpType, ToSharedFd,
12 op::{BufResultExt, Read, ReadManaged, ResultTakeBuffer, Write},
13 syscall,
14};
15use compio_io::{AsyncRead, AsyncReadManaged, AsyncWrite};
16use compio_runtime::{BorrowedBuffer, BufferPool};
17use windows_sys::Win32::System::{IO::OVERLAPPED, Threading::GetExitCodeProcess};
18
19use crate::{ChildStderr, ChildStdin, ChildStdout};
20
21struct WaitProcess {
22 child: process::Child,
23}
24
25impl WaitProcess {
26 pub fn new(child: process::Child) -> Self {
27 Self { child }
28 }
29}
30
31impl OpCode for WaitProcess {
32 fn op_type(&self) -> OpType {
33 OpType::Event(self.child.as_raw_handle() as _)
34 }
35
36 unsafe fn operate(self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
37 let mut code = 0;
38 syscall!(
39 BOOL,
40 GetExitCodeProcess(self.child.as_raw_handle() as _, &mut code)
41 )?;
42 Poll::Ready(Ok(code as _))
43 }
44}
45
46pub async fn child_wait(child: process::Child) -> io::Result<process::ExitStatus> {
47 let op = WaitProcess::new(child);
48 let code = compio_runtime::submit(op).await.0?;
49 Ok(process::ExitStatus::from_raw(code as _))
50}
51
52impl AsyncRead for ChildStdout {
53 async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
54 let fd = self.to_shared_fd();
55 let op = Read::new(fd, buffer);
56 let res = compio_runtime::submit(op).await.into_inner();
57 unsafe { res.map_advanced() }
58 }
59}
60
61impl AsyncReadManaged for ChildStdout {
62 type Buffer<'a> = BorrowedBuffer<'a>;
63 type BufferPool = BufferPool;
64
65 async fn read_managed<'a>(
66 &mut self,
67 buffer_pool: &'a Self::BufferPool,
68 len: usize,
69 ) -> io::Result<Self::Buffer<'a>> {
70 let fd = self.to_shared_fd();
71 let buffer_pool = buffer_pool.try_inner()?;
72 let op = ReadManaged::new(fd, buffer_pool, len)?;
73 compio_runtime::submit(op)
74 .with_extra()
75 .await
76 .take_buffer(buffer_pool)
77 }
78}
79
80impl AsyncRead for ChildStderr {
81 async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
82 let fd = self.to_shared_fd();
83 let op = Read::new(fd, buffer);
84 let res = compio_runtime::submit(op).await.into_inner();
85 unsafe { res.map_advanced() }
86 }
87}
88
89impl AsyncReadManaged for ChildStderr {
90 type Buffer<'a> = BorrowedBuffer<'a>;
91 type BufferPool = BufferPool;
92
93 async fn read_managed<'a>(
94 &mut self,
95 buffer_pool: &'a Self::BufferPool,
96 len: usize,
97 ) -> io::Result<Self::Buffer<'a>> {
98 let fd = self.to_shared_fd();
99 let buffer_pool = buffer_pool.try_inner()?;
100 let op = ReadManaged::new(fd, buffer_pool, len)?;
101 compio_runtime::submit(op)
102 .with_extra()
103 .await
104 .take_buffer(buffer_pool)
105 }
106}
107
108impl AsyncWrite for ChildStdin {
109 async fn write<T: IoBuf>(&mut self, buffer: T) -> BufResult<usize, T> {
110 let fd = self.to_shared_fd();
111 let op = Write::new(fd, buffer);
112 compio_runtime::submit(op).await.into_inner()
113 }
114
115 async fn flush(&mut self) -> io::Result<()> {
116 Ok(())
117 }
118
119 async fn shutdown(&mut self) -> io::Result<()> {
120 Ok(())
121 }
122}