Skip to content

Commit e8a9dfd

Browse files
committed
..
1 parent a6aa198 commit e8a9dfd

File tree

2 files changed

+63
-27
lines changed

2 files changed

+63
-27
lines changed

yazi-plugin/src/process/child.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,39 @@ use super::Status;
99
use crate::process::Output;
1010

1111
pub struct Child {
12-
inner: tokio::process::Child,
13-
stdin: Option<BufWriter<ChildStdin>>,
14-
stdout: Option<BufReader<ChildStdout>>,
15-
stderr: Option<BufReader<ChildStderr>>,
12+
inner: tokio::process::Child,
13+
stdin: Option<BufWriter<ChildStdin>>,
14+
stdout: Option<BufReader<ChildStdout>>,
15+
stderr: Option<BufReader<ChildStderr>>,
16+
#[cfg(windows)]
17+
job_handle: Option<std::os::windows::io::RawHandle>,
18+
}
19+
20+
#[cfg(windows)]
21+
impl Drop for Child {
22+
fn drop(&mut self) {
23+
if let Some(h) = self.job_handle.take() {
24+
unsafe { windows_sys::Win32::Foundation::CloseHandle(h) };
25+
}
26+
}
1627
}
1728

1829
impl Child {
19-
pub fn new(mut inner: tokio::process::Child) -> Self {
30+
pub fn new(
31+
mut inner: tokio::process::Child,
32+
#[cfg(windows)] job_handle: Option<std::os::windows::io::RawHandle>,
33+
) -> Self {
2034
let stdin = inner.stdin.take().map(BufWriter::new);
2135
let stdout = inner.stdout.take().map(BufReader::new);
2236
let stderr = inner.stderr.take().map(BufReader::new);
23-
Self { inner, stdin, stdout, stderr }
37+
Self {
38+
inner,
39+
stdin,
40+
stdout,
41+
stderr,
42+
#[cfg(windows)]
43+
job_handle,
44+
}
2445
}
2546

2647
pub(super) async fn wait(&mut self) -> io::Result<ExitStatus> {

yazi-plugin/src/process/command.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ impl Command {
4343
unsafe {
4444
self.inner.pre_exec(move || {
4545
let rlp = libc::rlimit { rlim_cur: max as _, rlim_max: max as _ };
46-
if libc::setrlimit(libc::RLIMIT_AS, &rlp) != 0 {
47-
return Err(io::Error::last_os_error());
48-
}
46+
libc::setrlimit(libc::RLIMIT_AS, &rlp);
4947
Ok(())
5048
});
5149
}
@@ -55,29 +53,46 @@ impl Command {
5553

5654
#[cfg(windows)]
5755
fn spawn(&mut self) -> io::Result<Child> {
58-
unsafe {
59-
let job = CreateJobObjectW(std::ptr::null_mut(), std::ptr::null());
60-
61-
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = std::mem::zeroed();
62-
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
63-
info.ProcessMemoryLimit = 536870912; // 512MB
64-
65-
SetInformationJobObject(
66-
job,
67-
JobObjectExtendedLimitInformation,
68-
&mut info as *mut _ as *mut _,
69-
std::mem::size_of::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>() as u32,
70-
);
56+
use std::os::windows::io::RawHandle;
7157

72-
let mut child =
73-
Command::new("your_program").args(&["arg1", "arg2"]).stdout(Stdio::piped()).spawn()?;
58+
use windows_sys::Win32::System::JobObjects::{AssignProcessToJobObject, CreateJobObjectW, JOB_OBJECT_LIMIT_PROCESS_MEMORY, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JobObjectExtendedLimitInformation, SetInformationJobObject};
7459

75-
AssignProcessToJobObject(job, child.as_raw_handle() as HANDLE);
60+
fn assign_job(max: usize, handle: RawHandle) -> io::Result<RawHandle> {
61+
unsafe {
62+
let job = CreateJobObjectW(std::ptr::null_mut(), std::ptr::null());
63+
if job.is_null() {
64+
return Err(io::Error::last_os_error());
65+
}
7666

77-
let status = child.wait()?;
67+
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = std::mem::zeroed();
68+
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
69+
info.ProcessMemoryLimit = max;
70+
71+
let result = SetInformationJobObject(
72+
job,
73+
JobObjectExtendedLimitInformation,
74+
&mut info as *mut _ as *mut _,
75+
std::mem::size_of_val(&info) as u32,
76+
);
77+
78+
if result == 0 {
79+
Err(io::Error::last_os_error())
80+
} else if AssignProcessToJobObject(job, handle) == 0 {
81+
Err(io::Error::last_os_error())
82+
} else {
83+
Ok(job)
84+
}
85+
}
86+
}
7887

79-
CloseHandle(job);
88+
let child = self.inner.spawn()?;
89+
if let (Some(max), Some(handle)) = (self.memory, child.raw_handle()) {
90+
if let Ok(job) = assign_job(max, handle) {
91+
return Ok(Child::new(child, Some(job)));
92+
}
8093
}
94+
95+
Ok(Child::new(child, None))
8196
}
8297

8398
async fn output(&mut self) -> io::Result<std::process::Output> {

0 commit comments

Comments
 (0)