beanshell2
beanshell2 copied to clipboard
Feature request: interruptor: Provide a way to interrupt looping script, conditionally and controllably.
Feature request: interruptor.
As a scripting language, it's likely to be embedded into other host
applications. However scripting can easily cause deadlock. While it would be
nice for host applications to have some control over the running script, rather
than easily hang due to script error.
One real example is the javascript engine in modern browsers. If a script has
run too long, you will see a popup dialog asking whether to stop the script, or
continue it.
Such a feature makes the script engine more usable in actual production
environment.
The feature is easy to implement, but the hard part is how to define the common
interface. So it should be reviewed and revised carefully.
I had some experiments and it works in my environment. The attachment is the
delta code (as well as the base code).
The implement covers 3 possible loop points in scripting:
while (including do-while)
for
enhanced for (BSH only).
There are possibly other points:
Recursive function call (both directly and indirectly). However I think that
may not be the point to check. Recursive function call will finally and easily
result in stackoverflow. So it will not hang the script for long.
Original issue reported on code.google.com by [email protected] on 11 Oct 2012 at 4:01
Attachments:
It seems issue #63 is for the same feature. Link it here. Let's find a proper
and common way to achieve this...
http://code.google.com/p/beanshell2/issues/detail?id=63
Original comment by [email protected] on 11 Oct 2012 at 7:31
One problem with this is that stopping a script could still deadlock another
part of the code e.g. by acquiring and not releasing a lock. Anyone trying to
control this will have to somehow keep track of all locks, monitors, etc.
acquired by the script and break those locks after stopping the script.
Original comment by [email protected] on 16 Jan 2014 at 3:47
@bogusandre, you are correct. The java lock could be another point for deadlock
and that should be considered carefully. This is likely non-trivial task.
The bsh_delta_interruptor provided above was an update to handle
while/do-while/for/enhanced-for loops. Here's some example usage, which is used
in http://robotypo.appspot.com to avoid deadlocking:
/**
* Interruptor specifies some conditions to indicate interruption.
*
* Usage example 1:
*
* Interpreter i = ...
* DefaultInterruptor r = new DefaultInterruptor();
* i.setInterruptor(r);
*
* r.resetTimeLimit(3000); //3 seconds at the most
* i.source(...);
*
* Usage example 2: Use time limit and accumulated time limit
*
* r.resetAccumulatedTimeLimit(10000); //set total time limit
* i.source(...);
* r.resetTimeLimit(3000);
* //invoke part of the script, e.g. from XThis...
* //...
* r.resetTimeLimit(3000);
* i.eval(...);
* r.resetTimeLimit(3000);
* //invoke some other part of the script using the same interpreter.
* //...
*
* Usage example 3: Control whether to continue on timeout.
*
* Interruptor r = new DefaultInterruptor() {
* protected boolean onTimeout() {
* boolean continueScript = ... //ask user whether to stop the script or not
* return continueScript;
* }
* };
Original comment by [email protected] on 17 Jan 2014 at 3:06
This may not be a good total solution, but hope it can be helpful for some
simple use cases, e.g. educational app, etc.
Original comment by [email protected] on 17 Jan 2014 at 3:08
It isn't possible just to wrap the eval task in a thread and monitor it with
another thread?
Something like this:
Thread t = new Thread(
new Runnable(){
@Override
public void run(){
Interpreter i = new Interpreter();
i.eval("code");
}
}
);
//Somewhere
ScheduledExecutorService _instance = Executors.newScheduledThreadPool(5);
_instance.schedule(/*runnable that stops thread t*/null, 3000,
TimeUnit.MILLISECONDS);
Original comment by [email protected] on 26 Jun 2014 at 9:26