trap

Set signal handlers.

Source: src/execution/builtins.f90:1347-1466, src/system/signal_handling.f90

Synopsis

trap [-lp] [[action] signal ...]

Description

The trap builtin allows scripts to catch signals and execute cleanup code. It's essential for writing robust scripts that handle interruption gracefully.

Options

OptionDescription
-lList all signal names
-pPrint trap commands

Signals

Common signals:

SignalNumberDescription
HUP1Hangup
INT2Interrupt (Ctrl+C)
QUIT3Quit (Ctrl+\)
TERM15Termination
EXIT0Shell exit
ERR-Command error
DEBUG-Before each command
RETURN-Function/source return

Usage

Set Trap

trap 'echo "Caught SIGINT"' INT

Multiple Signals

trap 'cleanup' INT TERM EXIT

Ignore Signal

trap '' INT    # Ignore Ctrl+C

Reset to Default

trap - INT     # Reset INT handler

List Signals

trap -l

Show Current Traps

trap -p
trap -p INT    # Show specific

Examples

Cleanup on Exit

#!/usr/bin/env fortsh
tmpfile=$(mktemp)

cleanup() {
    rm -f "$tmpfile"
    echo "Cleaned up"
}
trap cleanup EXIT

# Script work...
echo "data" > "$tmpfile"
# Cleanup runs automatically on exit

Handle Ctrl+C

#!/usr/bin/env fortsh
trap 'echo "Use quit to exit"; continue' INT

while true; do
    read -p "Command: " cmd
    [[ $cmd == quit ]] && break
    eval "$cmd"
done

Graceful Shutdown

#!/usr/bin/env fortsh
running=true

shutdown() {
    echo "Shutting down..."
    running=false
}
trap shutdown TERM INT

while $running; do
    process_work
    sleep 1
done

echo "Exited cleanly"

Error Handling

#!/usr/bin/env fortsh
set -e

on_error() {
    echo "Error on line $1" >&2
    exit 1
}
trap 'on_error $LINENO' ERR

# Commands that might fail...

Debug Tracing

trap 'echo "+ $BASH_COMMAND"' DEBUG
# Every command is printed before execution

Pseudo-Signals

SignalTriggered
EXITWhen shell exits
ERRWhen command fails (with set -e)
DEBUGBefore each command
RETURNWhen function/source returns

EXIT Example

trap 'echo "Goodbye"' EXIT
# Runs on normal exit, error, or signal

ERR Example

set -e
trap 'echo "Failed: $BASH_COMMAND"' ERR
false   # Triggers ERR trap

Common Patterns

Lock File

lockfile="/var/run/script.lock"

cleanup() {
    rm -f "$lockfile"
}
trap cleanup EXIT

echo $$ > "$lockfile"

Signal Forwarding

child_pid=""
cleanup() {
    [[ -n "$child_pid" ]] && kill "$child_pid" 2>/dev/null
}
trap cleanup EXIT INT TERM

long_process &
child_pid=$!
wait $child_pid

Re-raise Signal

cleanup() {
    echo "Cleaning up..."
    trap - TERM
    kill -TERM $$
}
trap cleanup TERM

Implementation

Source: signal_handling.f90

  • Traps stored in shell%traps array
  • Real signals registered via c_sigaction()
  • Pseudo-signals handled by shell logic

Exit Status

StatusCondition
0Success
1Invalid signal or option

Notes

  • SIGKILL and SIGSTOP cannot be trapped
  • Traps are reset in subshells
  • Action runs in current shell context
  • Empty action ('') ignores signal

See Also