Skip to content

Instantly share code, notes, and snippets.

@ocadaruma
Created December 20, 2022 04:07
Show Gist options
  • Save ocadaruma/24d305b739c55b7c04dd711972a8e965 to your computer and use it in GitHub Desktop.
Save ocadaruma/24d305b739c55b7c04dd711972a8e965 to your computer and use it in GitHub Desktop.
[package]
name = "sighandler-study"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
signal-hook = "0.3.14"
libc = "0.2.126"
use libc::pid_t;
use std::fs::OpenOptions;
use std::io::Write;
use std::os::unix::fs::OpenOptionsExt;
use std::sync::mpsc::channel;
use std::time::{Duration, SystemTime};
use std::{process, thread, time};
const SYS_TGKILL: i64 = 234;
const SYS_GETTID: i64 = 186;
fn main() {
let args: Vec<String> = std::env::args().collect();
let path = args[1].clone();
unsafe {
signal_hook::low_level::register(signal_hook::consts::SIGVTALRM, || {
println!("{}: SIGVTALRM called. tid={}", unix_millis(), gettid());
})
.unwrap();
}
let (tx_tid1, rx_tid1) = channel();
let (tx_tid2, rx_tid2) = channel();
let handle1 = thread::spawn(move || {
let mut file = OpenOptions::new()
.append(true)
.create(true)
.custom_flags(libc::O_SYNC)
.open(path)
.unwrap();
let mut buf = [0u8; 64];
tx_tid1.send(gettid()).unwrap();
file.write(&buf).unwrap();
thread::sleep(Duration::from_millis(2000));
});
let handle2 = thread::spawn(move || {
tx_tid2.send(gettid()).unwrap();
thread::sleep(Duration::from_millis(2000));
});
let tid1 = rx_tid1.recv().unwrap();
let tid2 = rx_tid2.recv().unwrap();
println!("tid1={}, tid2={}", tid1, tid2);
// sleep for a bit to expect syscall starts
thread::sleep(Duration::from_millis(100));
println!("{}: gonna send signals", unix_millis());
unsafe {
libc::syscall(
SYS_TGKILL,
process::id(),
tid1,
signal_hook::consts::SIGVTALRM,
);
libc::syscall(
SYS_TGKILL,
process::id(),
tid2,
signal_hook::consts::SIGVTALRM,
);
}
handle1.join().unwrap();
handle2.join().unwrap();
}
fn unix_millis() -> u64 {
SystemTime::now()
.duration_since(time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}
fn gettid() -> pid_t {
unsafe { libc::syscall(SYS_GETTID) as pid_t }
}
# Inject write delay into the device to simulate slow disk
$ echo 3000 | sudo tee /sys/fs/ddi/8\:17/write_delay
$ ./sighandler-study-bin /path/to/test.bin
file path: /path/to/test.bin
tid1=1693, tid2=1694
1658217824684: gonna send signals
1658217824684: SIGVTALRM called. tid=1694
1658217832317: SIGVTALRM called. tid=1693
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment