-1

Let us say I have a function that is run in the foreground. This function traps SIGINT and ignores EOF (for preventing Control + C and Control + D). This function creates a subshell that runs a command in the background.

I would think that SIGINT would be caught by the main function. However, using Control + C while running the main function does still result in the subshell receiving SIGINT and being killed before what is expected.

I have also attempted to add the traps for SIGINT and ignoring EOF in the subshell itself, but that did not seem to work either.

Here is a relatively-minimal example that encapsulates the issue, using the mpv command:

function play_video_until_yes {
    trap '' 2
    set -o ignoreeof
    
    videourl="$1"
    read -r mpv_pid < <(mpv --loop "$videourl" --no-video &>/dev/null & echo $!)
    
    while true; do
        read -rp "Input y for yes: " answer
        if [[ "$answer" = "y" ]]; then
            break
        fi
        printf "\nIncorrect. Try again.\n"
    done
    
    kill "$mpv_pid" >/dev/null
    
    trap 2
    set +o ignoreeof
}

One can run this function with a command-line argument of any YouTube video (e.g. play_video_until_yes "https://www.youtube.com/watch?v=usNsCeOV4GM") and press Control + C while the main process is asking for user input. This causes the subshell to quit, presumably due to the SIGINT.

Gigi Bayte 2
  • 838
  • 1
  • 8
  • 20

1 Answers1

0

I did a fair amount of research on this and was able to find one answer. It works, but it is less than ideal.

I had to install a separate package called util-linux via Homebrew on my Mac to get the setsid command. Then, I was able to use that command to run the mpv command in a separate process group to prevent SIGINT from being forwarded to it.

So, here is what my solution looked like after that:

function play_video_until_yes {
    trap '' 2
    set -o ignoreeof

    videourl="$1"
    read -r mpv_pid < <( /opt/homebrew/opt/util-linux/bin/setsid mpv --loop "$videourl" --no-video &>/dev/null & echo $!)

    while true; do
        read -rp "Input y for yes: " answer
        if [[ "$answer" = "y" ]]; then
            break
        fi
        printf "\nIncorrect. Try again.\n"
    done

    kill "$mpv_pid" >/dev/null

    trap 2
    set +o ignoreeof
}

I would still prefer a solution that uses commands already present on macOS, but this solution stands its ground for now.

Gigi Bayte 2
  • 838
  • 1
  • 8
  • 20