Skip to content

Commit

Permalink
try
Browse files Browse the repository at this point in the history
  • Loading branch information
glandium committed Jan 14, 2025
1 parent 01c0d4c commit 36dec17
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ tempfile = "3"
[profile.release]
codegen-units = 1
panic = "abort"
debug = true

[profile.dev]
panic = "abort"
Expand Down
35 changes: 29 additions & 6 deletions src/hg_connect_stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::process::{self, ChildStdin, ChildStdout, Command, Stdio};
use std::str::FromStr;
use std::sync::{Arc, Condvar, Mutex};
use std::thread::{self, JoinHandle};
use std::time::Duration;
use std::{mem, ptr};

use bstr::{BStr, BString};
Expand Down Expand Up @@ -304,7 +305,7 @@ pub fn get_stdio_connection(url: &Url, flags: c_int) -> Option<Box<dyn HgRepo>>
unsafe { NamedPipe::from_raw_handle(proc.stderr.take().unwrap().into_raw_handle()) };
const STDERR: Token = Token(0);
const WAKER: Token = Token(1);
let mut events = Events::with_capacity(2);
let mut events = Events::with_capacity(1);
let mut poll = Poll::new().unwrap();
poll.registry()
.register(
Expand Down Expand Up @@ -340,13 +341,32 @@ pub fn get_stdio_connection(url: &Url, flags: c_int) -> Option<Box<dyn HgRepo>>
let stderr = unsafe { FdFile::stderr() };
let mut writer = PrefixWriter::new("remote: ", stderr);
let mut buf = [0; 1024];
'outer: loop {
poll.poll(&mut events, None).unwrap();
let mut block = true;
let mut read_finished = false;
let mut notify = 0;
loop {
match poll.poll(&mut events, if block { None } else { Some(Duration::ZERO) }) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
e => e.map(|_| ()).unwrap(),
}
if !block && events.is_empty() {
if read_finished {
break;
}
while notify > 0 {
synchronizer.condvar.notify_one();
notify -= 1;
}
block = true;
}
for event in &events {
match event.token() {
STDERR => {
if event.is_read_closed() {
break 'outer;
read_finished = true;
block = false;
continue;
}
// Work around https://github.com/tokio-rs/mio/issues/1855
if !event.is_readable() {
Expand All @@ -358,12 +378,15 @@ pub fn get_stdio_connection(url: &Url, flags: c_int) -> Option<Box<dyn HgRepo>>
e => e.map(|_| &[]).unwrap(),
};
if buf.is_empty() {
break 'outer;
read_finished = true;
block = false;
continue;
}
writer.write_all(buf).unwrap();
}
WAKER => {
synchronizer.condvar.notify_one();
block = false;
notify += 1;
}
_ => {}
}
Expand Down
63 changes: 63 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5182,6 +5182,7 @@ static mut HAS_GIT_REPO: bool = false;

#[no_mangle]
unsafe extern "C" fn cinnabar_main(_argc: c_int, argv: *const *const c_char) -> c_int {
hang_monitor();
let now = Instant::now();

// We look at argv[0] to choose what behavior to take, but it's not
Expand Down Expand Up @@ -5235,6 +5236,7 @@ unsafe extern "C" fn cinnabar_main(_argc: c_int, argv: *const *const c_char) ->
curl_sys::curl_global_cleanup();
}
}
STOP.store(true, std::sync::atomic::Ordering::Relaxed);
match ret {
Ok(code) => code,
Err(msg) => {
Expand Down Expand Up @@ -5456,3 +5458,64 @@ pub fn experiment_similarity() -> &'static CStr {
unsafe extern "C" fn do_panic(err: *const u8, len: usize) {
panic!("{}", std::slice::from_raw_parts(err, len).as_bstr());
}

use ::libc::{sigaction, syscall, SYS_tgkill};

Check failure on line 5462 in src/main.rs

View workflow job for this annotation

GitHub Actions / clippy (macos-latest, 1.84.0)

unresolved import `libc::SYS_tgkill`

error[E0432]: unresolved import `libc::SYS_tgkill` --> src/main.rs:5462:34 | 5462 | use ::libc::{sigaction, syscall, SYS_tgkill}; | ^^^^^^^^^^ no `SYS_tgkill` in the root

static BACKTRACES: Mutex<Vec<(i32, String)>> = Mutex::new(Vec::new());
static STOP: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);

unsafe fn gettid() -> c_int {
syscall(::libc::SYS_gettid) as i32

Check failure on line 5468 in src/main.rs

View workflow job for this annotation

GitHub Actions / clippy (macos-latest, 1.84.0)

cannot find value `SYS_gettid` in crate `libc`

error[E0425]: cannot find value `SYS_gettid` in crate `libc` --> src/main.rs:5468:21 | 5468 | syscall(::libc::SYS_gettid) as i32 | ^^^^^^^^^^ not found in `libc`
}

extern "C" fn signal_handler(_sig: c_int) {
let bt = backtrace::Backtrace::new();
let thread_id = unsafe { gettid() };
let mut traces = BACKTRACES.lock().unwrap();
traces.push((thread_id, format!("{:?}", bt)));
}

fn hang_monitor() {
unsafe {
let mut sa: sigaction = std::mem::zeroed();
sa.sa_sigaction = signal_handler as usize;
sa.sa_flags = ::libc::SA_SIGINFO;
sigaction(::libc::SIGUSR1, &sa, std::ptr::null_mut());
}
std::thread::spawn(|| {
for _ in 0..100000 {
std::thread::sleep(std::time::Duration::from_millis(1));
if STOP.load(std::sync::atomic::Ordering::Relaxed) {
return;
}
}
eprintln!("timeout");
let self_tid = unsafe { gettid() };
let tids = std::fs::read_dir("/proc/self/task")
.unwrap()
.map(|e| {
e.unwrap()
.file_name()
.into_string()
.unwrap()
.parse::<i32>()
.unwrap()
})
.filter(|tid| *tid != self_tid)
.collect_vec();
let ntids = tids.len();
for tid in tids {
unsafe {
syscall(SYS_tgkill, ::libc::getpid(), tid, ::libc::SIGUSR1);
}
}
while BACKTRACES.lock().unwrap().len() < ntids {
std::thread::sleep(std::time::Duration::from_millis(1000));
}
for (tid, bt) in &BACKTRACES.lock().unwrap()[..] {
eprintln!("Thread {}", tid);
eprintln!("{}", bt);
}
std::process::abort();
});
}

0 comments on commit 36dec17

Please sign in to comment.