@CpsVmThreadOnly("root") public void unexport(BodyReference ref) { assertVmThread(); if (ref==null) return; closures.remove(ref.id); }
/** * Obtains the Groovy compiler to be used for compiling user script * in the CPS-transformed and sandboxed manner. */ private GroovyShell $getShell() { return CpsThreadGroup.current().getExecution().getShell(); }
@Override public void onSuccess(CpsThreadGroup result) { try { // TODO keep track of whether the program was saved anyway after saveState was called but before now, and do not bother resaving it in that case if (result.getExecution().getDurabilityHint().isPersistWithEveryStep()) { result.getExecution().getStorage().flush(); result.saveProgram(); } f.set(null); } catch (Exception x) { f.setException(x); } } @Override public void onFailure(Throwable t) {
@CpsVmThreadOnly CpsStepContext(StepDescriptor step, CpsThread thread, FlowExecutionOwner executionRef, FlowNode node, @CheckForNull Closure body) { this.threadId = thread.id; this.executionRef = executionRef; this.id = node.getId(); this.node = node; this.body = body != null ? thread.group.export(body) : null; this.stepDescriptorId = step.getId(); }
public CpsFlowExecution getExecution() { return group.getExecution(); }
public void onSuccess(Unmarshaller u) { pickleFutures = null; try { CpsFlowExecution old = PROGRAM_STATE_SERIALIZATION.get(); PROGRAM_STATE_SERIALIZATION.set(CpsFlowExecution.this); try { CpsThreadGroup g = (CpsThreadGroup) u.readObject(); result.set(g); try { if (g.isPaused()) { owner.getListener().getLogger().println("Still paused"); } else { owner.getListener().getLogger().println("Ready to run at " + new Date()); // In case we last paused execution due to Jenkins.isQuietingDown, make sure we do something after we restart. g.scheduleRun(); } } catch (IOException x) { LOGGER.log(Level.WARNING, null, x); } } catch (Throwable t) { onFailure(t); } finally { PROGRAM_STATE_SERIALIZATION.set(old); } } finally { r.close(); } }
File tmpFile = File.createTempFile("atomic",null, dir); assertVmThread(); LOGGER.log(FINE, "program state saved"); } catch (RuntimeException e) { propagateErrorToWorkflow(e); throw new IOException("Failed to persist "+f,e); } catch (IOException e) { if (!serializedOK) { propagateErrorToWorkflow(e);
final CpsThreadGroup g = new CpsThreadGroup(this); g.register(s); final SettableFuture<CpsThreadGroup> f = SettableFuture.create(); programPromise = f;
CpsThreadGroup c = CpsThreadGroup.current(); if (c !=null) { c.notifyNewHead(v); } else {
this.execution.saveOwner(); } catch (Exception ex) { LOGGER.log(Level.WARNING, "Error saving execution for "+this.getExecution(), ex); saveProgramIfPossible(false);
@CpsVmThreadOnly @Override public void onSuccess(CpsThreadGroup g) { g.unexport(body); body = null; CpsThread thread = getThread(g); g.getExecution().subsumeHead(parents.get(i)); StepEndNode en = new StepEndNode(flow, (StepStartNode) n, parents); thread.head.setNewHead(en);
@Override public void run() { CpsThread t = g.addThread(new Continuable(s,createInitialEnv()),h,null); t.resume(new Outcome(null, null)); f.set(g); }
/** * Ensures that the current thread is running from {@link CpsVmExecutorService} * * @see CpsVmThreadOnly */ private void assertVmThread() { assert current()==this; }
public boolean isPaused() { if (programPromise.isDone()) { try { return programPromise.get().isPaused(); } catch (ExecutionException | InterruptedException x) { // not supposed to happen LOGGER.log(Level.WARNING, null, x); } } return false; }
return programPromise.get().getThreadDump(); } catch (InterruptedException e) { throw new AssertionError(); // since we are checking programPromise.isDone() upfront
CpsThreadGroup g = new CpsThreadGroup(this); final FlowHead head_ = head;
/** * The code getting evaluated must also get CPS transformation. */ @Ignore("TODO usually future == null, perhaps because CpsThread.resume is intended to be @CpsVmThreadOnly (so assumes that the promise is just set is not cleared by runNextChunk) yet we are calling it from the test thread; extremely dubious test design, should probably be using SemaphoreStep to be more realistic") @Test public void evaluateShallBeCpsTransformed() throws Exception { CpsFlowDefinition flow = new CpsFlowDefinition("evaluate('1+com.cloudbees.groovy.cps.Continuable.suspend(2+3)')", false); createExecution(flow); exec.start(); exec.waitForSuspension(); // TODO: can't we assert that the suspend() ended with value 5? // this should have paused at suspend, so we are going to resume it by having it return a value we control assertFalse(dumpError(), exec.isComplete()); ListenableFuture<CpsThreadGroup> pp = exec.programPromise; assertNotNull(pp); Future<Object> future = pp.get().getThread(0).resume(new Outcome(7,null)); assertNotNull(future); assertEquals(8, future.get()); exec.waitForSuspension(); assertTrue(dumpError(), exec.isComplete()); assertEquals(dumpError(), Result.SUCCESS, exec.getResult()); }
@Override public boolean start() throws Exception { CpsStepContext cps = (CpsStepContext) getContext(); if (parallelStep.closures.isEmpty()) { cps.get(TaskListener.class).getLogger().println("No branches to run"); cps.onSuccess(Collections.<String,Object>emptyMap()); return true; } CpsThread t = CpsThread.current(); ResultHandler r = new ResultHandler(cps, this, parallelStep.isFailFast()); for (Entry<String,Closure> e : parallelStep.closures.entrySet()) { BodyExecution body = cps.newBodyInvoker(t.getGroup().export(e.getValue())) .withStartAction(new ParallelLabelAction(e.getKey())) .withCallback(r.callbackFor(e.getKey())) .start(); bodies.add(body); } return false; }
/** * Like {@link #saveProgram()} but will not fail. * @param enteringQuietState True if we're moving to quiet state - pausing or quieting down and need to write the program. */ @CpsVmThreadOnly void saveProgramIfPossible(boolean enteringQuietState) { if (this.getExecution() != null && (this.getExecution().getDurabilityHint().isPersistWithEveryStep() || enteringQuietState)) { try { // Program may depend on flownodes being saved, so save nodes FlowNodeStorage storage = this.execution.getStorage(); if (storage != null) { storage.flush(); } } catch (IOException ioe) { LOGGER.log(Level.WARNING, "Error persisting FlowNode storage before saving program", ioe); } try { saveProgram(); } catch (IOException x) { LOGGER.log(WARNING, "program state save failed", x); } } }