2

I'm piping output of an interactive command (ghci) through sed-based script to add some colors:

ghci | colorize.sh

where colorize.sh is something like:

#!/bin/bash
trap '' INT
sed '...some pattern...'

Now if I hit Ctrl-C I want only ghci to receive it (it does not terminate), and I want sed to thrive (or perhaps get restarted?) and still process the output of ghci.

This script does not work and I don't know why.

  • I forgot to add: the script does not work likely because it captures only the first SIGINT – Łukasz Lew Jul 30 '18 at 19:42
  • What makes you think the script captures only the first SIGINT? – Andy Dalton Jul 31 '18 at 15:22
  • I can't reproduce it... Why do you think you're not getting the signal more than once? Can you check with ps and see that sed was indeed interrupted? – filbranden Jul 31 '18 at 21:27
1

First, let me start out by saying that this doesn't answer your question, but I hope might help clarify what's happening. I suspect that what you think is happening might not really be happening. Consider this simple example:

# The 'writer' reads input from standard input and
# echos it to standard output.  It handles SIGINT by
# printing INT to standard output.
$ cat writer
#!/bin/bash
function foo() {
    echo "INT"
}

trap foo INT

while read x; do echo $x; done

# The 'reader' reads input from standard input and pipes what is
# read to 'sed', which converts it to upper case.  It ignores SIGINT.
# When it receives EOF on standard input, it writes "done".
$ cat reader
#!/bin/bash
trap '' INT
cat | sed -e 's/\(.*\)/\U\1/'
echo "done"

Now, when I run both, piping the output of writer into reader:

$ ./writer | ./reader
hello
HELLO
^CINT
^CINT
^CINT
world
WORLD
^D
done
$

The writer script reads reads from standard input and writes to the standard output – the pipe. The reader scripts reads from standard input — the pipe — and writes to standard output. When I hit Ctrl-C, the writer writes "INT"; the reader ignores the signal (multiple times). Eventually, I enter Ctrl-D (EOF), and the writer terminates. When the reader receives the EOF, it terminates and writes "done".

Note that the reader ignores the SIGINT more than once, and that neither the pipe nor sed is interrupted when the writer handles the SIGINT.

  • Your script works indeed the way we would expect. If I modify it with my sed expression: while read x; do echo "$x" | sed "..."; done, that works too as far as SIGINT is concerned. I can't use read because the prompt of ghci does not end with a newline. I'm curious why sed gets killed in my original script. – Łukasz Lew Jul 31 '18 at 20:38
  • This script trap '' INT; while true; do sed "$sedAll"; done seems to be a good solution. I'm happy sed is not stateful. I still would like to understand why sed sees the SIGINT – Łukasz Lew Jul 31 '18 at 20:51
  • I was too quick to say that this works, obviously it never exits which is problematic. – Łukasz Lew Jul 31 '18 at 20:55
  • I updated the reader to use sed; sed is not interrupted by the signal. – Andy Dalton Jul 31 '18 at 21:13
  • And my example does exit on EOF (i.e., Ctrl-D). – Andy Dalton Jul 31 '18 at 21:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.