-1

I've got what I think is a strange one here. I have the following environment.

  • A Linux compiled binary which sets up a signal handler to disable things like Ctrl+C, Ctrl+z, etc. This is done by calling signal on: SIGINT, SITTSTP and SIGQUIT. The signal handler simply prints an error message that user is not allowed to abort the program.
  • After setting up the signal handler, the binary calls an interactive ash script.
  • This interactive ash script ALSO disables all methods of breaking out of the script. It does this with "trap '' INT TSTP" at the very beginning. This works and if one enters Ctrl+C, etc it simply echoes the control character to the terminal but does not exit.

Individually both the binary and ash script prevent user from exiting.

However, notice what happens below:

  1. Allow control to be returned to the binary by normal completion of the interactive shell script. Once control returns to the binary, entering Ctrl+C works and does not allow user to break out of the program. This is proper behavior.

Where it is wrong is:

  1. Type a few Ctrl+C's during the time the interactive shell script is running and once control returns to the binary, the exit code is changed to something other than what the shell script is doing.

Here is an example:

In C code, let's say I have:

void sigintHandler(int sig_num)
{
    fprintf(stderr, "You are not allowed to exit this program.\n");
    return;
}
void main(void)
{
    signal(SIGINT, sigintHandler);
    int ret = system("/etc/scripts/test.sh");
    printf("test.sh returned: %d exit status.\n", ret);
}

And in test.sh I have:

#!/bin/ash
# Disable interrupts so that one cannot exit shell script.
trap '' INT TSTP
echo -n "Do you want to create abc file? (y/n): "
read answer
if [ $answer == "y" ];then
    touch /tmp/abc
fi
if [ -f /tmp/abc ]; then
    echo "Returning 1"
    exit 1
else
    echo "Returning 2"
    exit 2
fi

If I run the C binary normally I get the correct exit status (1 or 2) depending on whether file exists. Actually I get 256 or 512 which indicates it is storing the exit code in the 2nd byte. Point is this works consistently every time.

But now if I hit Ctrl+C while the shell script is running (before answering the question presented) and say I answer "n" which is exit code of 2. In the C binary the code I get back is sometimes 2 (not 512, indicating the exit code is now in the LOWER byte) but MORE often I get back a code of 0! This happens even though I see the message "Returning 2" which is echoed by the shell script.

This is driving me nuts trying to figure out why a simple exit code is being messed up.

Can anyone provide some suggestions?

Thanks much Allen

  • [man system](http://man7.org/linux/man-pages/man3/system.3.html): "the return value is a "wait status" that can be examined using the macros described in waitpid(2). (i.e.,WIFEXITED(), WEXITSTATUS(), and so on)." – kaylum Nov 23 '16 at 02:27
  • Do the same symptoms appear with different shells? (eg, use #!/bin/bash, #!/bin/sh, #!/bin/dash, #!/bin/ksh, etc) – William Pursell Nov 23 '16 at 02:45
  • @kaylum WIFSIGNALED returned true and WTERMSIG returned 2 which is SIGINT. But the problem is that this interrupt is disabled so the shell script was NOT terminated at all. This happens will sh, ash and bash. I don't have the others installed. Thanks Allen – Allen McWongahey Nov 23 '16 at 14:39

1 Answers1

0

I found the issue.

Previously I was using trap '' INT TSTP to disable interrupts in the shell script. Though this works to prevent shell script from being aborted it led to the issue in this post. I suspect that in disabling the ability to abort the shell script in this way, the upper level shell framework was not aware of this and all it knew is that Ctrl+C or whatever was pressed and returned SIGINT as the exit code despite what the shell script itself was exiting with.

The solution is to use:

stty -isig

at the beginning of the shell script.

This not only disables interrupts but ALSO lets the upper level framework know that this is what you've done so that it ignores the fact that Ctrl+C was pressed.

I found this information on the following page:

https://unix.stackexchange.com/questions/80975/preventing-propagation-of-sigint-to-parent-process

Thanks everyone, Allen

Community
  • 1
  • 1