Jython JSR223 Signal Handler not Called

167 views Asked by At

I am using the jython 2.7 jsr223 script engine. And I like to cleanup on termination of the jython execution.

Termination: Interrupting the thread which runs the jython script engine.

Cleanup: Registering signal handlers: signal.signal(signal.SIGTERM, cleanup)

In the jython code I see that, as an example the sleep, reacts with throwing a KeyboardInterruot exception. Code below:

public static void sleep(double secs) {
if (secs == 0) {
    // Conform to undocumented, or at least very underdocumented, but quite
    // reasonable behavior in CPython. See Alex Martelli's answer,
    // https://stackoverflow.com/a/790246/423006
    java.lang.Thread.yield();
} else {
    try {
        java.lang.Thread.sleep((long)(secs * 1000));
    }
    catch (java.lang.InterruptedException e) {
        throw new PyException(Py.KeyboardInterrupt, "interrupted sleep");
        }
    }
}

The above code raises a new exception: PyException(Py.KeyboardInterrupt, "interrupted sleep").

Theoretically the KeyboardInterrupt exception could be catched and the signal handler could be executed. Nevertheless the KeyboardInterrupt is not consistently thrown with all commands. The subprocess.check_call command in jython is implemented in a way that it doesn't throw a KeyboardInterrupt exception, nor fires any SIGINT or SIGTERM when the jython execution is interrupted. So the kill behavior might change on the implementation of the currently executing python-java equivalent (jython command).

People with similar problems say that changing the jython console would help to have SIGINT triggered. : How do you intercept a keyboard interrupt (CTRL-C) in Jython?

So I set the python.console=org.python.core.PlainConsole. The Jython code says: Alternatively, you could set python.console here,

but be aware that this will also affect the console in applications that embed a PythonInterpreter, or use Jython as a JSR-223 script engine.

So it should affect the script engine execution through jsr223. But the SIGINT script handler is not triggered even with python.console=org.python.core.PlainConsole as a property set in the JVM.

So there it seems there is no way to cleanup when jython execution when it runs a sub-process and gets interrupted.

Nevertheless I found that the signal handler in a jython execution is executed when I interrupt the jvm which runs the node. This thread indicates that the JVM termination does not forward the SIGTERM or SIGINT signal. But executes shutdown hooks: What happens when the JVM is terminated?

Debugging the shutdown hooks didn't reveal their execution at jvm termination.

So how and why do the SIGINT and SIGTERM handlers get executed that way?

Below is the code for testing signal handlers an the KeyboardInterrupt exception with jython:

import subprocess
import sys
import signal
import time

print 'Start'

def cleanup(signum, frame):
    outputFile = open('output.log','w')
    print "Starting cleanup"
    outputFile.write("Start cleanup")
    time.sleep(5)
    outputFile.write("Finished cleanup")
    outputFile.close()
    print "Done"
    sys.exit(0)

signal.signal(signal.SIGTERM, cleanup)
signal.signal(signal.SIGINT, cleanup)

try: outputFile = open('output.log','w')
    outputFile.write("Start sleeping bash subprocess:")
    outputFile.close()
    subprocess.check_call("sleep 10h", shell=True)
except KeyboardInterrupt as interrupt: outputFile = open('output.log','w')
    outputFile.write("Keyboard INterrupt caught")
    outputFile.close()

How do I execute the python/jython SIGTERM and SIGINT signal handlers when a jsr223 jython script engine thread is interrupted (execution terminated)???

Thank you so much for your help!

0

There are 0 answers