Sample Header Ad - 728x90

Prevent SIGINT propagation from subshell to parent shell in Zsh

1 vote
1 answer
58 views
I need to prevent SIGINT (Ctrl-C) from propagating from a subshell to its parent shell functions in Zsh. Here's a minimal example:
function sox-record {
    local output="${1:-$(mktemp).wav}"
    (
        rec "${output}" trim 0 300  # Part of sox package
    )
    echo "${output}"  # Need this to continue executing after Ctrl-C
}

function audio-postprocess {
    local audio="$(sox-record)"
    # Process the audio file...
    echo "${audio}"
}

function audio-transcribe {
    local audio="$(audio-postprocess)"
    # Send to transcription service...
    transcribe_audio "${audio}"  # Never reached if Ctrl-C during recording
}
The current workaround requires trapping SIGINT at every level, which leads to repetitive, error-prone code:
function sox-record {
    local output="${1:-$(mktemp).wav}"
    setopt localtraps
    trap '' INT
    (
        rec "${output}" trim 0 300
    )
    trap - INT
    echo "${output}"
}

function audio-postprocess {
    setopt localtraps
    trap '' INT
    local audio="$(sox-record)"
    trap - INT
    # Process the audio file...
    echo "${audio}"
}

function audio-transcribe {
    setopt localtraps
    trap '' INT
    local audio="$(audio-postprocess)"
    trap - INT
    # Send to transcription service...
    transcribe_audio "${audio}"
}
When the user presses Ctrl-C to stop the recording, I want: 1. The rec subprocess to terminate (working) 2. The parent functions to continue executing (requires trapping SIGINT in every caller) I know that: - SIGINT is sent to all processes in the foreground process group - Using setsid creates a new process group but prevents signals from reaching the child - Adding trap '' INT in the parent requires all callers to also trap SIGINT to prevent propagationj Is there a way to isolate SIGINT to just the subshell without requiring signal handling in all parent functions? Or is this fundamentally impossible due to how Unix process groups and signal propagation work? --- I took a look at [this question](https://unix.stackexchange.com/questions/80975/preventing-propagation-of-sigint-to-parent-process) , and I tried this:
function sox-record {
    local output="${1:-$(mktemp).wav}"

    zsh -mfc "rec "${output}" trim 0 300" &2 || true

    echo "${output}"
}
While this works when I just call sox-record, when I call a parent function like audio-postprocess, Ctrl-C doesn't do anything. (And I have to use pkill to kill rec.)
function audio-postprocess {
    local audio="$(sox-record)"

    # Process the audio file...
    echo "${audio}"
}
Asked by HappyFace (1694 rep)
Nov 3, 2024, 04:34 PM
Last activity: Nov 3, 2024, 06:07 PM