mirror of
https://github.com/openai/codex.git
synced 2026-09-16 12:13:30 +00:00
utils: reset exception ports in pre_exec
This commit is contained in:
@@ -119,6 +119,8 @@ async fn spawn_process_with_stdin_mode(
|
||||
unsafe {
|
||||
command.pre_exec(move || {
|
||||
crate::process_group::detach_from_tty()?;
|
||||
#[cfg(target_os = "macos")]
|
||||
let _ = crate::process_group::reset_to_system_crash_reporter();
|
||||
#[cfg(target_os = "linux")]
|
||||
crate::process_group::set_parent_death_signal(parent_pid)?;
|
||||
Ok(())
|
||||
|
||||
@@ -19,6 +19,13 @@ use std::io;
|
||||
|
||||
use tokio::process::Child;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use libc::c_char;
|
||||
#[cfg(target_os = "macos")]
|
||||
use libc::c_int;
|
||||
#[cfg(target_os = "macos")]
|
||||
use libc::c_uint;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
/// Ensure the child receives SIGTERM when the original parent dies.
|
||||
///
|
||||
@@ -44,6 +51,103 @@ pub fn set_parent_death_signal(_parent_pid: i32) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
/// Reset exception ports to the system crash reporter.
|
||||
///
|
||||
/// This breaks any inherited connection to a wrapping crash handler before
|
||||
/// `exec`, so crashes in the spawned process are reported by the system.
|
||||
pub fn reset_to_system_crash_reporter() -> bool {
|
||||
type MachPort = c_uint;
|
||||
type KernReturn = c_int;
|
||||
type ExceptionMask = c_uint;
|
||||
type ExceptionBehavior = c_int;
|
||||
type ThreadStateFlavor = c_int;
|
||||
|
||||
const KERN_SUCCESS: KernReturn = 0;
|
||||
const MACH_PORT_NULL: MachPort = 0;
|
||||
const MACH_PORT_DEAD: MachPort = MachPort::MAX;
|
||||
|
||||
const EXC_CRASH: u32 = 10;
|
||||
const EXC_RESOURCE: u32 = 11;
|
||||
const EXC_GUARD: u32 = 12;
|
||||
|
||||
const EXC_MASK_CRASH: ExceptionMask = 1 << EXC_CRASH;
|
||||
const EXC_MASK_RESOURCE: ExceptionMask = 1 << EXC_RESOURCE;
|
||||
const EXC_MASK_GUARD: ExceptionMask = 1 << EXC_GUARD;
|
||||
|
||||
const EXCEPTION_STATE_IDENTITY: ExceptionBehavior = 3;
|
||||
const MACH_EXCEPTION_CODES: ExceptionBehavior = 0x8000_0000u32 as ExceptionBehavior;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
const MACHINE_THREAD_STATE: ThreadStateFlavor = 1;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const MACHINE_THREAD_STATE: ThreadStateFlavor = 7;
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
|
||||
const MACHINE_THREAD_STATE: ThreadStateFlavor = 1;
|
||||
|
||||
unsafe extern "C" {
|
||||
static bootstrap_port: MachPort;
|
||||
fn bootstrap_look_up(
|
||||
bp: MachPort,
|
||||
service_name: *const c_char,
|
||||
sp: *mut MachPort,
|
||||
) -> KernReturn;
|
||||
fn mach_task_self() -> MachPort;
|
||||
fn task_set_exception_ports(
|
||||
task: MachPort,
|
||||
exception_mask: ExceptionMask,
|
||||
new_port: MachPort,
|
||||
behavior: ExceptionBehavior,
|
||||
new_flavor: ThreadStateFlavor,
|
||||
) -> KernReturn;
|
||||
}
|
||||
|
||||
const REPORT_CRASH_SERVICE: &[u8] = b"com.apple.ReportCrash\0";
|
||||
let service_name = REPORT_CRASH_SERVICE.as_ptr().cast::<c_char>();
|
||||
|
||||
let mut report_crash: MachPort = MACH_PORT_NULL;
|
||||
let lookup = unsafe {
|
||||
bootstrap_look_up(
|
||||
bootstrap_port,
|
||||
service_name,
|
||||
&mut report_crash as *mut MachPort,
|
||||
)
|
||||
};
|
||||
if lookup != KERN_SUCCESS || report_crash == MACH_PORT_DEAD || report_crash == MACH_PORT_NULL {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Best-effort: include resource/guard masks, then fall back to crash-only
|
||||
// when those exceptions are unsupported in this context.
|
||||
let mask = EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD;
|
||||
let behavior = EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES;
|
||||
|
||||
let task = unsafe { mach_task_self() };
|
||||
let primary = unsafe {
|
||||
task_set_exception_ports(task, mask, report_crash, behavior, MACHINE_THREAD_STATE)
|
||||
};
|
||||
if primary == KERN_SUCCESS {
|
||||
return true;
|
||||
}
|
||||
|
||||
let fallback = unsafe {
|
||||
task_set_exception_ports(
|
||||
task,
|
||||
EXC_MASK_CRASH,
|
||||
report_crash,
|
||||
behavior,
|
||||
MACHINE_THREAD_STATE,
|
||||
)
|
||||
};
|
||||
fallback == KERN_SUCCESS
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
/// No-op on non-macOS platforms.
|
||||
pub fn reset_to_system_crash_reporter() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Detach from the controlling TTY by starting a new session.
|
||||
pub fn detach_from_tty() -> io::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user