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, Recv, RecvManaged, ResultTakeBuffer, Send},
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 = Recv::new(fd, buffer);
56 compio_runtime::submit(op).await.into_inner().map_advanced()
57 }
58}
59
60impl AsyncReadManaged for ChildStdout {
61 type Buffer<'a> = BorrowedBuffer<'a>;
62 type BufferPool = BufferPool;
63
64 async fn read_managed<'a>(
65 &mut self,
66 buffer_pool: &'a Self::BufferPool,
67 len: usize,
68 ) -> io::Result<Self::Buffer<'a>> {
69 let fd = self.to_shared_fd();
70 let buffer_pool = buffer_pool.try_inner()?;
71 let op = RecvManaged::new(fd, buffer_pool, len)?;
72 compio_runtime::submit_with_flags(op)
73 .await
74 .take_buffer(buffer_pool)
75 }
76}
77
78impl AsyncRead for ChildStderr {
79 async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
80 let fd = self.to_shared_fd();
81 let op = Recv::new(fd, buffer);
82 compio_runtime::submit(op).await.into_inner().map_advanced()
83 }
84}
85
86impl AsyncReadManaged for ChildStderr {
87 type Buffer<'a> = BorrowedBuffer<'a>;
88 type BufferPool = BufferPool;
89
90 async fn read_managed<'a>(
91 &mut self,
92 buffer_pool: &'a Self::BufferPool,
93 len: usize,
94 ) -> io::Result<Self::Buffer<'a>> {
95 let fd = self.to_shared_fd();
96 let buffer_pool = buffer_pool.try_inner()?;
97 let op = RecvManaged::new(fd, buffer_pool, len)?;
98 compio_runtime::submit_with_flags(op)
99 .await
100 .take_buffer(buffer_pool)
101 }
102}
103
104impl AsyncWrite for ChildStdin {
105 async fn write<T: IoBuf>(&mut self, buffer: T) -> BufResult<usize, T> {
106 let fd = self.to_shared_fd();
107 let op = Send::new(fd, buffer);
108 compio_runtime::submit(op).await.into_inner()
109 }
110
111 async fn flush(&mut self) -> io::Result<()> {
112 Ok(())
113 }
114
115 async fn shutdown(&mut self) -> io::Result<()> {
116 Ok(())
117 }
118}