Skip to content

Commit

Permalink
wip: blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
oneofthezombies committed Feb 11, 2024
1 parent 72c444a commit d6be6a5
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 119 deletions.
3 changes: 1 addition & 2 deletions crates/libs/kill_tree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ readme.workspace = true
[dependencies]
tracing = "0.1.40"
tokio = { version = "1.36.0", features = ["full"], optional = true }
async-trait = { version = "0.1.77", optional = true }

[dev-dependencies]
tokio = { version = "1.36.0", features = ["test-util"] }
Expand All @@ -32,4 +31,4 @@ bindgen = "0.69.2"

[features]
blocking = []
tokio = ["dep:tokio", "dep:async-trait"]
tokio = ["dep:tokio"]
217 changes: 100 additions & 117 deletions crates/libs/kill_tree/src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::core::{Config, Error, KillOutput, ProcessId, ProcessInfo, ProcessInfos, Result};
use crate::core::{
Config, Error, KillOutput, Killable, ProcessId, ProcessInfo, ProcessInfos, Result,
};
use std::ffi;
use tracing::instrument;
use windows::Win32::{
Expand Down Expand Up @@ -43,151 +45,132 @@ pub(crate) fn child_process_id_map_filter(process_info: &ProcessInfo) -> bool {
process_info.parent_process_id == process_info.process_id
}

#[cfg(feature = "blocking")]
pub(crate) mod blocking {
use super::*;

struct Killer {}
struct Killer {}

impl crate::blocking::Killable for Killer {
fn kill(&self, process_id: ProcessId) -> Result<KillOutput> {
crate::windows::blocking::kill(process_id)
}
impl Killable for Killer {
fn kill(&self, process_id: ProcessId) -> Result<KillOutput> {
crate::windows::kill(process_id)
}
}

pub(crate) fn new_killer(_config: &Config) -> Result<impl crate::blocking::Killable> {
Ok(Killer {})
}
pub(crate) fn new_killer(_config: &Config) -> Result<impl Killable> {
Ok(Killer {})
}

#[instrument]
pub(crate) fn kill(process_id: ProcessId) -> Result<KillOutput> {
let result: Result<KillOutput>;
unsafe {
let open_result = OpenProcess(PROCESS_TERMINATE, false, process_id);
match open_result {
Ok(process_handle) => {
{
// do NOT return early from this block
result = TerminateProcess(process_handle, 1)
.and(Ok(KillOutput::Killed { process_id }))
.or_else(|e| {
if e.code() == E_ACCESSDENIED {
// Access is denied.
// This happens when the process is already terminated.
// This treat as success.
Ok(KillOutput::MaybeAlreadyTerminated {
process_id,
source: e.into(),
})
} else {
Err(e.into())
}
});
}
CloseHandle(process_handle)?;
}
Err(e) => {
if e.code() == E_INVALIDARG {
// The parameter is incorrect.
// This happens when the process is already terminated.
// This treat as success.
result = Ok(KillOutput::MaybeAlreadyTerminated {
process_id,
source: e.into(),
#[instrument]
pub(crate) fn kill(process_id: ProcessId) -> Result<KillOutput> {
let result: Result<KillOutput>;
unsafe {
let open_result = OpenProcess(PROCESS_TERMINATE, false, process_id);
match open_result {
Ok(process_handle) => {
{
// do NOT return early from this block
result = TerminateProcess(process_handle, 1)
.and(Ok(KillOutput::Killed { process_id }))
.or_else(|e| {
if e.code() == E_ACCESSDENIED {
// Access is denied.
// This happens when the process is already terminated.
// This treat as success.
Ok(KillOutput::MaybeAlreadyTerminated {
process_id,
source: e.into(),
})
} else {
Err(e.into())
}
});
} else {
result = Err(e.into());
}
}
CloseHandle(process_handle)?;
}
Err(e) => {
if e.code() == E_INVALIDARG {
// The parameter is incorrect.
// This happens when the process is already terminated.
// This treat as success.
result = Ok(KillOutput::MaybeAlreadyTerminated {
process_id,
source: e.into(),
});
} else {
result = Err(e.into());
}
}
}
result
}
result
}

#[instrument]
pub(crate) fn get_process_infos() -> Result<ProcessInfos> {
let mut process_infos = ProcessInfos::new();
let mut error: Option<Error> = None;
unsafe {
let snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?;
{
// do NOT return early from this block
let mut process_entry = std::mem::zeroed::<PROCESSENTRY32>();
let process_entry_size = u32::try_from(std::mem::size_of::<PROCESSENTRY32>());
match process_entry_size {
Ok(process_entry_size) => {
process_entry.dwSize = process_entry_size;
match Process32First(snapshot_handle, &mut process_entry) {
Ok(()) => loop {
process_infos.push(ProcessInfo {
process_id: process_entry.th32ProcessID,
parent_process_id: process_entry.th32ParentProcessID,
name: ffi::CStr::from_ptr(
process_entry.szExeFile.as_ptr().cast(),
)
#[instrument]
pub(crate) fn get_process_infos() -> Result<ProcessInfos> {
let mut process_infos = ProcessInfos::new();
let mut error: Option<Error> = None;
unsafe {
let snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?;
{
// do NOT return early from this block
let mut process_entry = std::mem::zeroed::<PROCESSENTRY32>();
let process_entry_size = u32::try_from(std::mem::size_of::<PROCESSENTRY32>());
match process_entry_size {
Ok(process_entry_size) => {
process_entry.dwSize = process_entry_size;
match Process32First(snapshot_handle, &mut process_entry) {
Ok(()) => loop {
process_infos.push(ProcessInfo {
process_id: process_entry.th32ProcessID,
parent_process_id: process_entry.th32ParentProcessID,
name: ffi::CStr::from_ptr(process_entry.szExeFile.as_ptr().cast())
.to_string_lossy()
.into_owned(),
});
match Process32Next(snapshot_handle, &mut process_entry) {
Ok(()) => {}
Err(e) => {
if e.code() != ERROR_NO_MORE_FILES.into() {
error = Some(e.into());
}
break;
});
match Process32Next(snapshot_handle, &mut process_entry) {
Ok(()) => {}
Err(e) => {
if e.code() != ERROR_NO_MORE_FILES.into() {
error = Some(e.into());
}
break;
}
},
Err(e) => {
error = Some(e.into());
}
},
Err(e) => {
error = Some(e.into());
}
}
Err(e) => {
error = Some(Error::InvalidCast {
source: e,
reason: "size of PROCESSENTRY32 to u32".into(),
});
}
}
Err(e) => {
error = Some(Error::InvalidCast {
source: e,
reason: "size of PROCESSENTRY32 to u32".into(),
});
}
}
CloseHandle(snapshot_handle)?;
}
if let Some(e) = error {
Err(e)
} else {
Ok(process_infos)
}
CloseHandle(snapshot_handle)?;
}
if let Some(e) = error {
Err(e)
} else {
Ok(process_infos)
}
}

#[cfg(feature = "tokio")]
pub(crate) mod tokio {
#[cfg(feature = "blocking")]
pub(crate) mod blocking {
use super::*;
use async_trait::async_trait;

#[derive(Clone)]
struct Killer {}

#[async_trait]
impl crate::tokio::Killable for Killer {
async fn kill(&self, process_id: ProcessId) -> Result<KillOutput> {
crate::windows::tokio::kill(process_id).await
}
}

pub(crate) fn new_killer(_config: &Config) -> Result<impl crate::tokio::Killable> {
Ok(Killer {})
pub(crate) fn get_process_infos() -> Result<ProcessInfos> {
crate::windows::get_process_infos()
}
}

#[instrument]
async fn kill(process_id: ProcessId) -> Result<KillOutput> {
::tokio::task::spawn_blocking(move || crate::windows::blocking::kill(process_id)).await?
}
#[cfg(feature = "tokio")]
pub(crate) mod tokio {
use super::*;

#[instrument]
pub(crate) async fn get_process_infos() -> Result<ProcessInfos> {
::tokio::task::spawn_blocking(move || blocking::get_process_infos()).await?
crate::windows::get_process_infos()
}
}

Expand Down

0 comments on commit d6be6a5

Please sign in to comment.