Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #15981: Generation fails with: RejectedExecutionException'. Perhaps the thread pool was stopped? #2533

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -453,31 +453,33 @@ object JsEngine {
* So you should minimize the number of time it is done.
*/
def sandboxed[T](policyFileUrl: URL, maxThread: Int = 1, timeout: FiniteDuration = DEFAULT_MAX_EVAL_DURATION)(script: SandboxedJsEngine => IOResult[T]): IOResult[T] = {
var sandbox = new SandboxSecurityManager(policyFileUrl)
var threadFactory = new RudderJsEngineThreadFactory(sandbox)
var pool = Executors.newFixedThreadPool(maxThread, threadFactory)
System.setSecurityManager(sandbox)

getJsEngine().flatMap { jsEngine =>
val engine = new SandboxedJsEngine(jsEngine, sandbox, pool, timeout)

try {
script(engine)
} catch {
case RudderFatalScriptException(message, cause) =>
SystemError(message, cause).fail
} finally {
final case class ManagedJsEnv(pool: ExecutorService, engine: SandboxedJsEngine)

val managedJsEngine = Managed.make(
getJsEngine().flatMap( jsEngine =>
IOResult.effect {
val sandbox = new SandboxSecurityManager(policyFileUrl)
val threadFactory = new RudderJsEngineThreadFactory(sandbox)
val pool = Executors.newFixedThreadPool(maxThread, threadFactory)
System.setSecurityManager(sandbox)
ManagedJsEnv(pool, new SandboxedJsEngine(jsEngine, sandbox, pool, timeout))
}
)
) { managedJsEnv =>
IOResult.effect{
//clear everything
pool.shutdownNow()
pool = null
threadFactory = null
sandbox = null
managedJsEnv.pool.shutdownNow()
//check & clear interruption of the calling thread
Thread.currentThread().isInterrupted()
//restore the "none" security manager
System.setSecurityManager(null)
}
}.foldM(
err => JsDirectiveParamLoggerPure.error(err.fullMsg)
, ok => ok.succeed
)
}

managedJsEngine.use(managedJsEnv => script(managedJsEnv.engine))
}

protected[policies] def getJsEngine(): IOResult[ScriptEngine] = {
Expand Down Expand Up @@ -620,7 +622,7 @@ object JsEngine {
task.get(maxTime.toMillis, TimeUnit.MILLISECONDS)
} catch {
case ex: ExecutionException => //this can happen when jsengine get security exception... Yeah...
throw RudderFatalScriptException(s"Evaluating script '${name}' was forced interrupted due to ${ex.getMessage}, aborting.", ex)
SystemError(s"Evaluating script '${name}' was forced interrupted due to ${ex.getMessage}, aborting.", ex).fail

case ex: TimeoutException =>
//try to interrupt the thread
Expand All @@ -639,23 +641,19 @@ object JsEngine {
}
} catch {
case ex: ThreadDeath =>
throw RudderFatalScriptException(s"Evaluating script '${name}' took more than ${maxTime.toString()}, and " +
"we were force to kill the thread. Check for infinite loop or uninterruptible system calls", ex)
SystemError(s"Evaluating script '${name}' took more than ${maxTime.toString()}, and " +
"we were force to kill the thread. Check for infinite loop or uninterruptible system calls", ex).fail

case ex: InterruptedException =>
throw RudderFatalScriptException(s"Evaluating script '${name}' was forced interrupted, aborting.", ex)
SystemError(s"Evaluating script '${name}' was forced interrupted, aborting.", ex).fail
}
}
} catch {
case ex: RejectedExecutionException =>
throw RudderFatalScriptException(s"Evaluating script '${name}' lead to a '${ex.getClass.getName}'. Perhaps the thread pool was stopped?", ex)
SystemError(s"Evaluating script '${name}' lead to a '${ex.getClass.getName}'. Perhaps the thread pool was stopped?", ex).fail
}
}
}
/*
* An exception marker class to handle thread related error cases
*/
protected[policies] case class RudderFatalScriptException(message: String, cause: Throwable) extends Exception(message, cause)

/*
* A sandboxed security manager, allowing only restricted
Expand Down