Sigkill Signal Handling

SIGKILL signal Handler

You cannot, at least not for the process being killed.

What you can do is arrange for the parent process to watch for the child process's death, and act accordingly. Any decent process supervision system, such as daemontools, has such a facility built in.

Handle a kill signal

This is it: you cannot catch a SIGKILL, it will definitely kill your program, this is what it's been created for.

SIGKILL signal handling

Signal are "handed off" to a process by the kernel, so sending a signal from processA to processB employs the kernel. When SIGKILL is delivered the kernel does not allow any activity by the process (user mode), specifically process rundown: atexit calls, _exit. Nothing. The process is simply destroyed by the system. This involves some activity in kernel mode. Buffered data is lost. SYSV semaphores and other kernel persistent memory objects are left in memory. It can be a real mess.

If something in kernel memory is causing a hang you use the sysrq interface in linux:

http://tldp.org/HOWTO/Remote-Serial-Console-HOWTO/security-sysrq.html

--to perform whatever semblance of an ordered shutdown you can get.

This is why using SIGKILL is an absolute last resort, because you cannot know what you are breaking. And it will not fix all hangs.

What exactly are you working on?

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"

sending signals to child processes , SIGCONT ,SIGSTOP

There are several issues with your code, among them:

  1. Any processes to be stopped via SIGSTOP must not have a handler registered for that signal. Registering a handler causes the handler's behavior to replace the default behavior of stopping the process.

  2. It's usually a bad idea to register a handler for SIGCONT. Doing so will not prevent a SIGCONT from continuing the process, which is a special characteristic of SIGCONT that can be surprising, but also the handler will fire whenever a SIGCONT is delivered, even if the process was not stopped, which is often a different kind of surprise.

  3. You register your signal handlers only in the parent, after the first fork. The subsequently forked children will inherit those, but the first one will not. Among other things, this will prevent the first child's pause() from being unblocked by the signals the parent sends to it. You can make each child register any needed handlers for itself, or you can register them in the parent, before the first fork.

  4. There is a race between each child's pause() and the parent's first kill() targeting that child. It is possible for the child to receive the SIGCONT before it calls pause(), in which case it will wait for the next signal. You can prevent that by blocking SIGCONT in the parent before forking, and using sigsuspend() in the child, with an appropriate mask, instead of the initial pause(). In that case, you probably want to unblock SIGCONT after returning from that initial sigsuspend().

  5. The parent attempts to send signals to processes that it has not forked yet (kill(pid[i + 1], SIGCONT);).

It's not clear what the full behavior you are trying to achieve is, but you may want to fork all the children first, and only then start sending signals.

Update

With respect to the update to the question,


  1. You apparently want to cycle repeatedly through the child processes, but your code runs through them only once. This is a good reason to implement what I already suggested above: fork all the children first, then, separately, do all the signalling.


Related Topics



Leave a reply



Submit