mirror of
https://github.com/openai/codex.git
synced 2026-04-28 10:21:06 +03:00
3.1 KiB
3.1 KiB
DOs
- Prefer safe signal wrappers: Use
nix::sys::signal::killinstead of manualunsafe.
#[cfg(unix)]
use nix::sys::signal::{kill, Signal};
#[cfg(unix)]
use nix::unistd::Pid;
#[cfg(unix)]
fn suspend(&mut self, terminal: &mut tui::Tui) -> Result<()> {
tui::restore()?;
let _ = kill(Pid::from_raw(0), Signal::SIGTSTP);
*terminal = tui::init(&self.config)?;
terminal.clear()?;
self.app_event_tx.send(AppEvent::RequestRedraw);
Ok(())
}
- Restore, suspend, then re-init and redraw: Leave the terminal clean before/after job control.
#[cfg(unix)]
fn suspend(&mut self, terminal: &mut tui::Tui) -> Result<()> {
tui::restore()?;
let _ = nix::sys::signal::kill(nix::unistd::Pid::from_raw(0), nix::sys::signal::Signal::SIGTSTP);
*terminal = tui::init(&self.config)?;
terminal.clear()?;
self.app_event_tx.send(AppEvent::RequestRedraw);
Ok(())
}
- Gate suspension to Unix and scope deps with cfg: Keep platform-specific code and dependencies isolated.
# codex-rs/tui/Cargo.toml
[target.'cfg(unix)'.dependencies]
nix = { version = "0.29", default-features = false, features = ["signal"] }
match key {
KeyEvent { code: KeyCode::Char('z'), modifiers: KeyModifiers::CONTROL, kind: KeyEventKind::Press, .. } => {
#[cfg(unix)]
{ self.suspend(terminal)?; }
// Non-Unix: no-op
}
_ => {}
}
- Trigger on Ctrl-Z press only: Avoid repeat actions on key repeat/release.
if let KeyEvent {
code: KeyCode::Char('z'),
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
..
} = key {
#[cfg(unix)]
{ self.suspend(terminal)?; }
}
- Send SIGTSTP to the process group: Use PID 0 for standard job-control semantics.
#[cfg(unix)]
let _ = nix::sys::signal::kill(nix::unistd::Pid::from_raw(0), nix::sys::signal::Signal::SIGTSTP);
DON’Ts
- Don’t call
unsafe libc::killdirectly: Prefer a safe wrapper to avoid manualunsafe.
// Avoid:
#[cfg(unix)]
unsafe { libc::kill(0, libc::SIGTSTP) };
- Don’t repurpose Ctrl-Z to “interrupt tasks”: Reserve Ctrl-Z for suspend; use Ctrl-C/Esc for interrupts.
// Avoid:
if let AppState::Chat { widget } = &mut self.app_state {
widget.on_ctrl_z(); // previously interrupted running task
}
- Don’t suspend without restoring first: Restoring before sending SIGTSTP prevents a wedged terminal.
// Avoid (order is wrong):
let _ = nix::sys::signal::kill(nix::unistd::Pid::from_raw(0), nix::sys::signal::Signal::SIGTSTP);
tui::restore()?; // too late
- Don’t emulate suspend on non-Unix: Keep it a no-op instead of custom behavior.
// Avoid:
#[cfg(not(unix))]
self.suspend(terminal)?; // incorrect: non-Unix should do nothing
- Don’t leave the UI stale after resume: Re-init, clear, and request a redraw.
// Avoid: missing re-init/clear/redraw after resume
#[cfg(unix)]
fn suspend(&mut self, _terminal: &mut tui::Tui) -> Result<()> {
tui::restore()?;
let _ = nix::sys::signal::kill(nix::unistd::Pid::from_raw(0), nix::sys::signal::Signal::SIGTSTP);
Ok(()) // UI will be stale
}