compio_process/
windows.rs1use std::{
2 io,
3 os::windows::{io::AsRawHandle, process::ExitStatusExt},
4 process,
5 task::Poll,
6};
7
8use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut};
9use compio_driver::{
10 BufferRef, OpCode, OpType, ResultTakeBuffer, ToSharedFd,
11 op::{BufResultExt, Read, ReadManaged, Write},
12 syscall,
13};
14use compio_io::{AsyncRead, AsyncReadManaged, AsyncWrite};
15use compio_runtime::Runtime;
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
30unsafe impl OpCode for WaitProcess {
31 type Control = ();
32
33 unsafe fn init(&mut self, _: &mut Self::Control) {}
34
35 fn op_type(&self, _: &Self::Control) -> OpType {
36 OpType::Event(self.child.as_raw_handle() as _)
37 }
38
39 unsafe fn operate(
40 &mut self,
41 _: &mut Self::Control,
42 _optr: *mut OVERLAPPED,
43 ) -> Poll<io::Result<usize>> {
44 let mut code = 0;
45 syscall!(
46 BOOL,
47 GetExitCodeProcess(self.child.as_raw_handle() as _, &mut code)
48 )?;
49 Poll::Ready(Ok(code as _))
50 }
51}
52
53pub async fn child_wait(child: process::Child) -> io::Result<process::ExitStatus> {
54 let op = WaitProcess::new(child);
55 let code = compio_runtime::submit(op).await.0?;
56 Ok(process::ExitStatus::from_raw(code as _))
57}
58
59impl AsyncRead for ChildStdout {
60 async fn read<B: IoBufMut>(&mut self, buffer: B) -> BufResult<usize, B> {
61 let fd = self.to_shared_fd();
62 let op = Read::new(fd, buffer);
63 let res = compio_runtime::submit(op).await.into_inner();
64 unsafe { res.map_advanced() }
65 }
66}
67
68impl AsyncReadManaged for ChildStdout {
69 type Buffer = BufferRef;
70
71 async fn read_managed(&mut self, len: usize) -> io::Result<Option<Self::Buffer>> {
72 let fd = self.to_shared_fd();
73 let res = Runtime::with_current(|rt| {
74 let buffer_pool = rt.buffer_pool()?;
75 let op = ReadManaged::new(fd, &buffer_pool, len)?;
76 io::Result::Ok(rt.submit(op))
77 })?
78 .await;
79 unsafe { res.take_buffer() }
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 = Read::new(fd, buffer);
87 let res = compio_runtime::submit(op).await.into_inner();
88 unsafe { res.map_advanced() }
89 }
90}
91
92impl AsyncReadManaged for ChildStderr {
93 type Buffer = BufferRef;
94
95 async fn read_managed(&mut self, len: usize) -> io::Result<Option<Self::Buffer>> {
96 let fd = self.to_shared_fd();
97 let res = Runtime::with_current(|rt| {
98 let buffer_pool = rt.buffer_pool()?;
99 let op = ReadManaged::new(fd, &buffer_pool, len)?;
100 io::Result::Ok(rt.submit(op))
101 })?
102 .await;
103 unsafe { res.take_buffer() }
104 }
105}
106
107impl AsyncWrite for ChildStdin {
108 async fn write<T: IoBuf>(&mut self, buffer: T) -> BufResult<usize, T> {
109 let fd = self.to_shared_fd();
110 let op = Write::new(fd, buffer);
111 compio_runtime::submit(op).await.into_inner()
112 }
113
114 async fn flush(&mut self) -> io::Result<()> {
115 Ok(())
116 }
117
118 async fn shutdown(&mut self) -> io::Result<()> {
119 Ok(())
120 }
121}