Nashorn LOCAL_JS_SANDBOX_MAX_MEMORY introduced

This commit is contained in:
Sergey Matvienko 2024-03-26 19:25:44 +01:00
parent a7eee8fe62
commit eba645c542
3 changed files with 9 additions and 4 deletions

View File

@ -866,6 +866,8 @@ js:
monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}" monitor_thread_pool_size: "${LOCAL_JS_SANDBOX_MONITOR_THREAD_POOL_SIZE:4}"
# Maximum CPU time in milliseconds allowed for script execution # Maximum CPU time in milliseconds allowed for script execution
max_cpu_time: "${LOCAL_JS_SANDBOX_MAX_CPU_TIME:8000}" max_cpu_time: "${LOCAL_JS_SANDBOX_MAX_CPU_TIME:8000}"
# Maximum memory in Bytes which JS executor thread can allocate (approximate calculation). A zero memory limit in combination with a non-zero CPU limit is not recommended due to the implementation of Nashorn 0.4.2. 100MiB is effectively unlimited for most cases
max_memory: "${LOCAL_JS_SANDBOX_MAX_MEMORY:104857600}"
# Maximum allowed JavaScript execution errors before JavaScript will be blacklisted # Maximum allowed JavaScript execution errors before JavaScript will be blacklisted
max_errors: "${LOCAL_JS_SANDBOX_MAX_ERRORS:3}" max_errors: "${LOCAL_JS_SANDBOX_MAX_ERRORS:3}"
# JS Eval max request timeout. 0 - no timeout # JS Eval max request timeout. 0 - no timeout

View File

@ -145,14 +145,14 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
log.trace("[{}] InvokeScript uuid {} with timeout {}ms", tenantId, scriptId, getMaxInvokeRequestsTimeout()); log.trace("[{}] InvokeScript uuid {} with timeout {}ms", tenantId, scriptId, getMaxInvokeRequestsTimeout());
var task = doInvokeFunction(scriptId, args); var task = doInvokeFunction(scriptId, args);
var resultFuture = Futures.transformAsync(task.getResultFuture(), output -> { var resultFuture = Futures.transform(task.getResultFuture(), output -> {
String result = JacksonUtil.toString(output); String result = JacksonUtil.toString(output);
if (resultSizeExceeded(result)) { if (resultSizeExceeded(result)) {
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException( throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException(
format("Script invocation result exceeds maximum allowed size of %s symbols", getMaxResultSize()) format("Script invocation result exceeds maximum allowed size of %s symbols", getMaxResultSize())
)); ));
} }
return Futures.immediateFuture(output); return output;
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
return withTimeoutAndStatsCallback(scriptId, task, resultFuture, invokeCallback, getMaxInvokeRequestsTimeout()); return withTimeoutAndStatsCallback(scriptId, task, resultFuture, invokeCallback, getMaxInvokeRequestsTimeout());

View File

@ -41,7 +41,6 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@Slf4j @Slf4j
@ -65,6 +64,9 @@ public class NashornJsInvokeService extends AbstractJsInvokeService {
@Value("${js.local.max_cpu_time}") @Value("${js.local.max_cpu_time}")
private long maxCpuTime; private long maxCpuTime;
@Value("${js.local.max_memory}")
private long maxMemory;
@Getter @Getter
@Value("${js.local.max_errors}") @Value("${js.local.max_errors}")
private int maxErrors; private int maxErrors;
@ -107,12 +109,13 @@ public class NashornJsInvokeService extends AbstractJsInvokeService {
@Override @Override
public void init() { public void init() {
super.init(); super.init();
jsExecutor = MoreExecutors.listeningDecorator(Executors.newWorkStealingPool(jsExecutorThreadPoolSize)); jsExecutor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(jsExecutorThreadPoolSize, "nashorn-js-executor"));
if (useJsSandbox) { if (useJsSandbox) {
sandbox = NashornSandboxes.create(); sandbox = NashornSandboxes.create();
monitorExecutorService = ThingsBoardExecutors.newWorkStealingPool(monitorThreadPoolSize, "nashorn-js-monitor"); monitorExecutorService = ThingsBoardExecutors.newWorkStealingPool(monitorThreadPoolSize, "nashorn-js-monitor");
sandbox.setExecutor(monitorExecutorService); sandbox.setExecutor(monitorExecutorService);
sandbox.setMaxCPUTime(maxCpuTime); sandbox.setMaxCPUTime(maxCpuTime);
sandbox.setMaxMemory(maxMemory);
sandbox.allowNoBraces(false); sandbox.allowNoBraces(false);
sandbox.allowLoadFunctions(true); sandbox.allowLoadFunctions(true);
sandbox.setMaxPreparedStatements(30); sandbox.setMaxPreparedStatements(30);