2

I've found that if I have something like:

#!/usr/bin/env bash

function abort-politely {
  echo 'Aborting politely'
  {
    sleep 5
    touch .stop
  }
}
trap 'abort-politely' SIGINT

{
  while [ ! -r .stop ] ; do echo hello world ; sleep 1 ; done
  rm -f .stop
} &
wait $!

echo Exiting

it behaves as I would expect, which is to say that the background task continues for 5s after the interrupt:

hello world
hello world
hello world
hello world
<Ctrl+C pressed>
Aborting politely
hello world
hello world
hello world
hello world
hello world
Exiting

However, if instead I introduce process substitution as part of the background process...

#!/usr/bin/env bash

function abort-politely {
  echo 'Aborting politely'
  {
    sleep 5
    touch .stop
  }
}
trap 'abort-politely' SIGINT

{
  # The "while" loop below is all that has changed
  while [ ! -r .stop ] && read line; do echo hello $line ; done < <(
    while : ; do echo world ; sleep 1 ; done
  )
  rm -f .stop
} &
wait $!

echo Exiting

...the background process seems to exit immediately when Ctrl+C is pressed:

hello world
hello world
hello world
hello world
<Ctrl+C pressed>
Aborting politely
<5 seconds delay>
Exiting

I had expected the same output as in the first case.

How come this doesn't work as I expected? Is there a way to make it behave as I had hoped? I suppose what I need is for the process substitution to continue until it is no longer being read from. (I wondered if adding trap '' SIGINT inside the process substitution block might be the solution, but then it just exits immediately.)

IpsRich
  • 797
  • 10
  • 23

1 Answers1

1

The SIGINT signal propagates through the subprocesses causing the process substitution shell to abort itself.

You can avoid it by adding trap : SIGINT:

  while [ ! -r .stop ] && read line; do echo hello $line ; done < <(
    trap : SIGINT
    while : ; do echo world ; sleep 1 ; done
  )
konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • Thanks for that! Bizarrely, this seems to be exactly the same as what I originally tried: `trap '' SIGINT` but both of these exited immediately when I ran them. I realise now that this was probably due to a rogue `.stop` file from a previous run! When I re-run it, it works fine. So anyway, your solution led me to the answer, so deserves to be marked as correct even if it is essentially the same as I'd tried before! What is weird is that this one prints an extra "hello world" after it has printed "Exiting" and has exited. Not sure why that is. – IpsRich Jan 04 '22 at 12:54
  • It might be simply a delayed response issue. – konsolebox Jan 04 '22 at 12:57