#[cfg(target_os = "windows")]
mod imp {
use anyhow::{Result, anyhow};
use tracing::warn;
use windows::Win32::Foundation::{CloseHandle, HANDLE};
use windows::Win32::System::JobObjects::{
AssignProcessToJobObject, CreateJobObjectW, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JobObjectExtendedLimitInformation,
SetInformationJobObject, TerminateJobObject,
};
use windows::core::PCWSTR;
pub struct JobObject {
handle: HANDLE,
}
unsafe impl Send for JobObject {}
unsafe impl Sync for JobObject {}
impl JobObject {
pub fn assign_handle(process: HANDLE) -> Result<Self> {
unsafe {
let handle = CreateJobObjectW(None, PCWSTR::null())
.map_err(|e| anyhow!("CreateJobObjectW: {e:?}"))?;
let job = JobObject { handle };
AssignProcessToJobObject(handle, process)
.map_err(|e| anyhow!("AssignProcessToJobObject: {e:?}"))?;
Ok(job)
}
}
pub fn assign_handle_kill_on_close(process: HANDLE) -> Result<Self> {
unsafe {
let handle = CreateJobObjectW(None, PCWSTR::null())
.map_err(|e| anyhow!("CreateJobObjectW: {e:?}"))?;
let job = JobObject { handle };
let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default();
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(
handle,
JobObjectExtendedLimitInformation,
&info as *const _ as *const core::ffi::c_void,
std::mem::size_of::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>() as u32,
)
.map_err(|e| anyhow!("SetInformationJobObject(KILL_ON_JOB_CLOSE): {e:?}"))?;
AssignProcessToJobObject(handle, process)
.map_err(|e| anyhow!("AssignProcessToJobObject: {e:?}"))?;
Ok(job)
}
}
pub fn terminate(&self) {
unsafe {
if let Err(e) = TerminateJobObject(self.handle, 1) {
warn!(
target: "kanade_agent::job_object",
"TerminateJobObject failed: {e:?}",
);
}
}
}
}
impl Drop for JobObject {
fn drop(&mut self) {
unsafe {
let _ = CloseHandle(self.handle);
}
}
}
}
#[cfg(target_os = "windows")]
pub use imp::JobObject;
#[cfg(not(target_os = "windows"))]
pub struct JobObject;
#[cfg(not(target_os = "windows"))]
impl JobObject {
pub fn terminate(&self) {}
}