Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions brush-core/src/traps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,19 @@ impl TrapHandlerConfig {
/// * `signal_type` - The type of signal to register a handler for.
/// * `command` - The command to execute when the signal is trapped.
/// * `source_info` - The source info for where the trap handler was defined.
///
/// Signals recorded as ignored at shell entry remain ignored, so registration attempts for
/// them are silently declined.
pub fn register_handler(
&mut self,
signal_type: TrapSignal,
command: String,
source_info: crate::SourceInfo,
) {
if self.ignored_signal_name_at_entry(signal_type).is_some() {
return;
}

let _ = self.handlers.insert(
signal_type,
TrapHandler {
Expand Down Expand Up @@ -284,4 +291,44 @@ mod tests {

assert_eq!(ignored, vec![(10, "SIGUSR1")]);
}

#[test]
fn ignored_signal_at_entry_cannot_be_trapped_or_reset() {
let Some(signal) = crate::sys::signal::Signal::iterator().next() else {
return;
};
let trap_signal = TrapSignal::Signal(signal);
let mut traps = TrapHandlerConfig::default();
traps.record_ignored_signal_at_entry(signal as i32, signal.as_str().to_owned());

traps.register_handler(
trap_signal,
"echo caught".to_owned(),
crate::SourceInfo::default(),
);
traps.remove_handlers(trap_signal);

assert!(!traps.handles(trap_signal));
assert_eq!(
traps.ignored_signal_name_at_entry(trap_signal),
Some(signal.as_str())
);
}

#[test]
fn signal_not_ignored_at_entry_can_be_trapped() {
let Some(signal) = crate::sys::signal::Signal::iterator().next() else {
return;
};
let trap_signal = TrapSignal::Signal(signal);
let mut traps = TrapHandlerConfig::default();

traps.register_handler(
trap_signal,
"echo caught".to_owned(),
crate::SourceInfo::default(),
);

assert!(traps.handles(trap_signal));
}
}
14 changes: 14 additions & 0 deletions brush-shell/tests/cases/compat/builtins/trap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,20 @@ cases:
stdin: |
bash -c 'trap "" USR1; exec "$1" --norc --noprofile -c "trap -p USR1; (trap -p USR1)"' _ "$0"

- name: "signals ignored at shell entry cannot be trapped or reset"
stdin: |
bash -c 'trap "" USR1; signal=$(kill -l USR1); exec "$1" --norc --noprofile -c "$2" _ "$signal"' _ "$0" '
trap "echo named" USR1
trap -p USR1
trap - USR1
trap -p USR1
trap "echo numeric" "$1"
trap -p "$1"
trap - "$1"
trap -p "$1"
(trap "echo subshell" USR1; trap -p USR1)
'

- name: "trap -p - with specific signal"
stdin: |
trap 'echo "[int]"' INT
Expand Down
Loading