5

I have a method to return an HTTP response after a Groovy script is executed. I've created an anonymous thread that is supposed to execute the Groovy script. However, as a precaution, I want the thread to stop after 3 seconds so as to prevent bad scripts (ie: infinite loops) from continuing to run.

public Response runScript(String script) {
    GroovyShell shell = new GroovyShell();
    Thread thread = new Thread() {
       public void run() {
           Script validatedScript = shell.parse(script);
           validatedScript.run();
       }
    };
    thread.start();
    thread.join(3000);
    return Response.ok("It ran!", MediaType.TEXT_PLAIN).build();
}

This code works fine for scripts that do not have an infinite loop. However, if there is an infinite loop, the response "It ran!" is delivered to the client, but the thread is still alive. How do I kill this thread after the join()?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
L Becker
  • 685
  • 8
  • 28

3 Answers3

3

If the script is untrusted and you can't depend on it to be well-behaved then you can't use interruption, which requires the cooperation of the thread being canceled (by either explicitly checking the flag with Thread.currentThread().isInterrupted or by entering a call to sleep, wait, or join (and even then the code can squelch the InterruptedException in an unhelpful way)).

You can terminate it only by calling Thread#stop on it:

thread.join(3000);
if (thread.isAlive()) {
    thread.stop();
}

The stop method is deprecated because it can leave the terminated thread's activity in a bad state; ThreadDeath can be thrown anywhere, so there is no good way to ensure that the stopped thread gets a chance to cleanup before it exits. However, the stop method hasn't been removed from the API on account of cases like this, and it seems unlikely that this method will be removed anytime soon.

Deprecation here doesn't mean so much "this method will be removed in a later version" as "danger, don't use this unless you know what you're doing".

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
0

Just check if the thread is alive:

Thread thread = new Thread()
    thread.join(3000)

    if (thread.isAlive()) {
        thread.interrupt()
        // TODO
    } else {
        // TODO
    }
Matheus
  • 134
  • 8
0

Unfortumately the interrupt() method would not help you unless your script has a blocking operation in it. The interrupt() method interrupts the thread only if it is blocked.

You cannot terminate a running thread just like that. You can check if the thread still works using the thread.isAlive() method, but you cannot stop it.

I suggest you try to modify your script.run() so that it would end eventually and no endless thread working is ever reached

Krasimir Stoev
  • 1,734
  • 11
  • 9