diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java index b79a42401..0ff38a6c3 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java @@ -557,13 +557,19 @@ private Env createInitialEnv() { private CpsScript parseScript() throws IOException { // classloader hierarchy. See doc/classloader.md - trusted = new CpsGroovyShellFactory(this).forTrusted().build(); - shell = new CpsGroovyShellFactory(this).withParent(trusted).build(); + CpsScript s; + try { + trusted = new CpsGroovyShellFactory(this).forTrusted().build(); + shell = new CpsGroovyShellFactory(this).withParent(trusted).build(); - CpsScript s = (CpsScript) shell.reparse("WorkflowScript",script); + s = (CpsScript) shell.reparse("WorkflowScript",script); - for (Entry e : loadedScripts.entrySet()) { - shell.reparse(e.getKey(), e.getValue()); + for (Entry e : loadedScripts.entrySet()) { + shell.reparse(e.getKey(), e.getValue()); + } + } catch (RuntimeException | Error x) { + closeShells(); + throw x; } s.execution = this; @@ -1304,20 +1310,26 @@ synchronized void onProgramEnd(Outcome outcome) { this.persistedClean = Boolean.TRUE; } - void cleanUpHeap() { - LOGGER.log(Level.FINE, "cleanUpHeap on {0}", owner); + private void closeShells() { try { if (shell != null) { + LOGGER.fine(() -> "closing main class loader from " + owner); shell.getClassLoader().close(); shell = null; } if (trusted != null) { + LOGGER.fine(() -> "closing trusted class loader from " + owner); trusted.getClassLoader().close(); trusted = null; } } catch (IOException x) { LOGGER.log(Level.WARNING, "failed to close class loaders from " + owner, x); } + } + + void cleanUpHeap() { + LOGGER.log(Level.FINE, "cleanUpHeap on {0}", owner); + closeShells(); if (scriptClass != null) { try { cleanUpLoader(scriptClass.getClassLoader(), new HashSet<>(), new HashSet<>());