help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] How to trap SIGTERM?


From: Pierre Gaston
Subject: Re: [Help-bash] How to trap SIGTERM?
Date: Sat, 20 Apr 2013 11:18:22 +0300




On Sat, Apr 20, 2013 at 7:51 AM, Bob Proulx <address@hidden> wrote:
Peng Yu wrote:
> #!/usr/bin/env bash
>
> echo $$
> trap "echo Booh!; exit" SIGTERM
> while true
> do
>   sleep 60
> done
>
> I have the above script. I run it and get the process id. Then I use
> "kill -SIGTERM pid" to kill it. But the script fails to respond. Does
> anybody know how to get the script respond to SIGTERM? Thanks.

There are two serious problems with the script that should be fixed.

If you trap a signal then you should not simply "exit".  That rewrites
the exit code and hides the kill-on-signal.  Instead you should have
the script kill itself.

  trap "echo foo 1>&2; trap - TERM; kill -TERM $$" TERM

Do you really need this for TERM also?

I  understand this for INT and perhaps QUIT because the a calling shell is doing some extra work in this case and kinda need this,
but it is also true for any existing signal?
I don't think bash does something special with it besides perhaps setting the status.

Would it not  be reasonable for a script or any program (for instance a daemon) to exit normally after a sigterm?

Imo in practice it would make no difference if you resend TERM or not in a script, except perhaps if someone wants to investigate how it exits but  in this case I would set a trap inside the script. 

 

But that is only *if* you need to catch the signal.  In your example
here you do not.  Instead with bash if you have things to do at shell
exit time then use the "EXIT" trap case.  And do not call exit from
the EXIT trap.

Try this:

  #!/usr/bin/env bash
  echo $$
  trap "echo Booh!" EXIT
  while true
  do
    sleep 60
  done

Importantly notice that the exit code is now correct when you kill it
with a signal.

Note however that the sleep is cast adrift and isn't killed just
because the script interpreter bash parent is killed.  It will run
until it exits unless it is also killed.

Bob

I didn't know this, so I tried to convince myself, and it is true for TERM.
However I got some strange results with INT...I'm not sure how to interpret them.

I ran the following test program in C:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>

int main(int argc, char ** argv) {

 
  int pid = fork();
  if (pid == 0 ) {
    execl("./termt", "./termt", NULL);
    return 0;
  }
  if (pid > 0) {
    //give some time to the shell to really start
    struct timespec sleep;
    sleep.tv_sec = 2;
    sleep.tv_nsec =0;
    nanosleep(&sleep, NULL);
    if (kill(pid, atoi(argv[1])) <0) {
      printf("kill failed\n");
    }
    int status;
    if (pid ==  waitpid(pid, &status, 0)) {
      if (WIFSIGNALED(status)) {
        printf("Child exited with status: %d and signal: %d \n", status, WTERMSIG(status));
      } else if (WIFEXITED(status)){
        printf("Child exit normally: %d\n", WEXITSTATUS(status));
      }
    } else {
      printf("wait failed");
    }
  } else {
    printf("fork failed\n");
    return 0;
  }
}

Basically it forks, run the ./termt script, kill it and check the exit status
If I use it to run the script:

#!/usr/bin/env bash
sleep 5 

I get:

$ for i in 2  15;do ./sigtest $i;done
Child exit normally: 0
Child exited with status: 15 and signal: 15

I'm not quite sure why the shell doesn't indicate that it was killed with INT.
The same happens with the EXIT trap:

#!/usr/bin/env bash
trap "echo Booh!" EXIT
sleep 5 

$ for i in 2  15;do ./sigtest $i;done
booh!
Child exit normally: 0
booh!
Child exited with status: 15 and signal: 15

 so the trap is indeed not affecting TERM.
INT is not simply ignored (like QUIT is) because if I reset the trap, running:

#!/usr/bin/env bash
trap "echo booh!" EXIT
trap "echo INT;trap - INT;kill -INT $$" INT
sleep 5

I get:

$ for i in 2  15;do ./sigtest $i;done
INT
booh!
Child exited with status: 2 and signal: 2
booh!
Child exited with status: 15 and signal: 15

So resetting the trap seems to do what I would expect, the shell exits indicating that it has been killed with INT.

The shell is doing some strange handling, if I change the script to:

#!/usr/bin/env bash
trap "echo booh!" EXIT
sleep 5  & wait $!

I get:

$ for i in 2  15;do ./sigtest $i;done
booh!
Child exit normally: 129
booh!
Child exited with status: 15 and signal: 15

As I said I'm not sure what are the rationale behind all that.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]