mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-23 19:17:33 +00:00
83 lines
2.1 KiB
Rust
83 lines
2.1 KiB
Rust
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Author: Johannes Leupolz <dev@leupolz.eu>
|
|
|
|
use std::{
|
|
os::unix::process::CommandExt,
|
|
process::{Child, Command},
|
|
sync::Mutex,
|
|
thread,
|
|
time::Duration,
|
|
};
|
|
|
|
use nix::sys::signal::{self, Signal};
|
|
use nix::unistd::Pid;
|
|
|
|
/// Global singleton
|
|
static VUINPUTD_LOCK: Mutex<()> = Mutex::new(());
|
|
|
|
pub fn ensure_vuinputd_running(args: &[&str]) -> VuinputdGuard {
|
|
VuinputdGuard::start(args)
|
|
}
|
|
|
|
pub struct VuinputdGuard {
|
|
child: Child,
|
|
}
|
|
|
|
impl VuinputdGuard {
|
|
fn start(args: &[&str]) -> Self {
|
|
println!("Acquiring lock to ensure only one vuinputd test instance is running");
|
|
let _mutex = VUINPUTD_LOCK.lock().unwrap();
|
|
println!("Executing vuinputd located via cargo run");
|
|
let mut concat_args = vec![
|
|
"run",
|
|
"-p",
|
|
"vuinputd",
|
|
"--",
|
|
"--major",
|
|
"120",
|
|
"--minor",
|
|
"414796",
|
|
"--devname",
|
|
"vuinput-test",
|
|
];
|
|
concat_args.extend(args);
|
|
let child = unsafe {
|
|
Command::new("cargo")
|
|
.args(concat_args)
|
|
.pre_exec(|| {
|
|
// Last resort, if the parent just is killed.
|
|
libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL);
|
|
Ok(())
|
|
})
|
|
.spawn()
|
|
.expect("failed to start vuinputd")
|
|
};
|
|
|
|
// Optional: give it time to create /dev/vuinput
|
|
thread::sleep(Duration::from_millis(1000));
|
|
|
|
Self { child }
|
|
}
|
|
}
|
|
|
|
impl Drop for VuinputdGuard {
|
|
fn drop(&mut self) {
|
|
let pid = Pid::from_raw(self.child.id() as i32);
|
|
|
|
// First: SIGTERM
|
|
let _ = signal::kill(pid, Signal::SIGTERM);
|
|
|
|
// Wait a bit
|
|
for _ in 0..10 {
|
|
if let Ok(Some(_)) = self.child.try_wait() {
|
|
return;
|
|
}
|
|
thread::sleep(Duration::from_millis(100));
|
|
}
|
|
|
|
// Still alive → SIGKILL
|
|
let _ = signal::kill(pid, Signal::SIGKILL);
|
|
let _ = self.child.wait();
|
|
}
|
|
}
|