Is There Some Cases in Which Sigkill Will Not Work

How to gracefully handle the SIGKILL signal in Java

It is impossible for any program, in any language, to handle a SIGKILL. This is so it is always possible to terminate a program, even if the program is buggy or malicious. But SIGKILL is not the only means for terminating a program. The other is to use a SIGTERM. Programs can handle that signal. The program should handle the signal by doing a controlled, but rapid, shutdown. When a computer shuts down, the final stage of the shutdown process sends every remaining process a SIGTERM, gives those processes a few seconds grace, then sends them a SIGKILL.

The way to handle this for anything other than kill -9 would be to register a shutdown hook. If you can use (SIGTERM) kill -15 the shutdown hook will work. (SIGINT) kill -2 DOES cause the program to gracefully exit and run the shutdown hooks.

Registers a new virtual-machine shutdown hook.

The Java virtual machine shuts down in response to two kinds of events:

  • The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
  • The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.

I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, as expected. On a kill -15 it DOES run the shutdown hook every time.

public class TestShutdownHook
{
public static void main(String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
@Override
public void run()
{
System.out.println("Shutdown hook ran!");
}
});

while (true)
{
Thread.sleep(1000);
}
}
}

There isn't any way to really gracefully handle a kill -9 in any program.

In rare circumstances the virtual
machine may abort, that is, stop
running without shutting down cleanly.
This occurs when the virtual machine
is terminated externally, for example
with the SIGKILL signal on Unix or the
TerminateProcess call on Microsoft
Windows.

The only real option to handle a kill -9 is to have another watcher program watch for your main program to go away or use a wrapper script. You could do with this with a shell script that polled the ps command looking for your program in the list and act accordingly when it disappeared.

#!/usr/bin/env bash

java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"

Why is the KILL signal handler not executing when my child process dies

I couldn't find anything in the bash documentation that would explain the observed behavior, so I turned to the source code. Debugging lead to the function notify_of_job_status(). The line that prints the message about a killed subprocess can be reached only if all of the following conditions hold:

  1. the subprocess is registered in the job table (i.e. has not been disown-ed)
  2. the shell was NOT started in interactive mode
  3. the signal that terminated the child process is NOT trapped in the parent shell (see the signal_is_trapped (termsig) == 0 check)

Demonstration:

$ cat test.sh 
echo Starting a subprocess
LC_ALL=C sleep 100 &
Active_pid=$!
case "$1" in
disown) disown ;;
trapsigkill) trap "echo Signal SIGKILL caught" 9 ;;
esac
sleep 1
kill -9 $Active_pid
sleep 1
echo End of script

$ # Demonstrate the undesired message
$ bash test.sh
Starting a subprocess
test.sh: line 14: 15269 Killed LC_ALL=C sleep 100
End of script

$ # Suppress the undesired message by disowning the child process
$ bash test.sh disown
Starting a subprocess
End of script

$ # Suppress the undesired message by trapping SIGKILL in the parent shell
$ bash test.sh trapsigkill
Starting a subprocess
End of script

$ # Suppress the undesired message by using an interactive shell
$ bash -i test.sh
Starting a subprocess
End of script

How this removes the trace of the first test without executing echo Signal SIGKILL ?

The trap is not executed since the KILL signal is received by the sub-process rather than the shell process for which the trap has been set. The effect of the trap on the diagnostics is in the (somewhat arguable) logic in the notify_of_job_status() function.

kill() system call with SIGTERM is not working

It can be a permission issue.
Print the Process Id using

'getpid();'

Kill it manually from terminal.

'sudo kill -9 processid'

Is it safe to send a SIGKILL to `git status`?

Since SIGKILL cannot be caught and immediately terminates Git, this may leave behind various oddities or problems.

Git is designed to be reasonably resilient: for instance, instead of just writing out its index, it writes an updated index to a file named .git/index.lock, and then uses what's meant to be an atomic OS-level process to replace the old .git/index file with the new contents in .git/index.lock while calling the new file .git/index. This atomic operation is a rename system call: Git depends on the OS to implement it as an atomic operation, that either completely happens, or never starts.

Similar schemes are used to update references and other files, including loose objects and pack files. Not every file system on every OS obeys these rules, and if the OS itself crashes, you can get into various troublesome cases, but on the whole this works pretty well.

What happens if Git is killed, with the un-catch-able SIGKILL, during one of these critical sections is that the lock file remains left behind. A future Git invocation stops and tells you that there is a lock file and it cannot proceed. It then becomes your job to inspect the system as a whole, determine whether this is a stale lock, and hence whether it can be removed. If so, removing the stale lock and retrying the operation should recover.

When the OS itself crashes, Git may lose files that Git cannot operate without. Your best bet for this kind of problem is to have another repository somewhere else, preferably physically distant so that a common event (e.g., building catches fire and all the computers within it burn up or are ruined by fire suppression) does not damage the other Git repository. For less extreme cases, sometimes the repository is repairable in-place.

One of the most common failures is for the OS to completely delete the file named .git/HEAD, and with this file gone, Git no longer believes that the repository is a repository. Re-create the file (e.g., echo ref: refs/heads/master > .git/HEAD) and the repository is back. If your system obeys the POSIX file atomicity rules, this particular case cannot happen even for SIGKILL.



Related Topics



Leave a reply



Submit