Skip to content

Instantly share code, notes, and snippets.

@abhijat
Created August 14, 2025 05:58
Show Gist options
  • Select an option

  • Save abhijat/830aa4a1f5795d4d4792bc8c4c464e30 to your computer and use it in GitHub Desktop.

Select an option

Save abhijat/830aa4a1f5795d4d4792bc8c4c464e30 to your computer and use it in GitHub Desktop.
Slow down a process using ptrace
use anyhow::Result;
use nix::sys::ptrace::Options;
use nix::sys::wait::{Id, WaitPidFlag};
use nix::sys::{ptrace, wait};
use nix::unistd::Pid;
use std::thread;
use std::time::{Duration, Instant};
use sysinfo::System;
fn wait_stopped(pid: Pid) -> Result<()> {
wait::waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED)?;
Ok(())
}
fn pause_for(pid: Pid, d: Duration) -> Result<()> {
ptrace::interrupt(pid)?;
wait_stopped(pid)?;
thread::sleep(d);
Ok(())
}
fn unpause_for(pid: Pid, d: Duration) -> Result<()> {
ptrace::cont(pid, None)?;
thread::sleep(d);
Ok(())
}
fn slowdown_pid(
pid: Pid,
throttle_duration: Duration,
free_duration: Duration,
total_duration: Duration,
) -> Result<()> {
let now = Instant::now();
let deadline = now + total_duration;
ptrace::seize(pid, Options::empty())?;
while Instant::now() < deadline {
let diff = (deadline - Instant::now()).as_secs();
println!("[task-{pid}] throttle remaining: {diff}s",);
pause_for(pid, throttle_duration)?;
unpause_for(pid, free_duration)?;
}
ptrace::interrupt(pid)?;
wait_stopped(pid)?;
ptrace::detach(pid, None)?;
Ok(())
}
fn main() -> Result<()> {
let throttle_duration = Duration::from_millis(900);
let free_duration = Duration::from_millis(300);
let total_duration = Duration::from_secs(100);
let mut threads = Vec::new();
let sys = System::new_all();
for process in sys.processes_by_name("dragonfly".as_ref()) {
if let Some(tasks) = process.tasks() {
for task in tasks {
let pid = task.as_u32() as i32;
let t = throttle_duration;
let f = free_duration;
let tot = total_duration;
threads.push(thread::spawn(move || {
if let Err(error) = slowdown_pid(Pid::from_raw(pid), t, f, tot) {
println!("failed with {error}");
}
}));
}
}
}
for t in threads {
t.join().unwrap();
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment