Search in sources :

Example 6 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsFlowExecution method croak.

/**
 * Report a fatal error in the VM.
 */
void croak(Throwable t) {
    setResult(Result.FAILURE);
    onProgramEnd(new Outcome(null, t));
    cleanUpHeap();
}
Also used : Outcome(com.cloudbees.groovy.cps.Outcome)

Example 7 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsThreadGroup method run.

/**
 * Run the CPS program a little bit.
 *
 * <p>
 * The amount of execution needs to be small enough so as not to hog CPS VM thread
 * In particular, time sensitive activities like the interruption wants to run on CPS VM thread.
 *
 * @return
 *      true if this program can still execute further. false if the program is suspended
 *      and requires some external event to become resumable again. The false return value
 *      is akin to a Unix thread waiting for I/O completion.
 */
@CpsVmThreadOnly("root")
private boolean run() {
    boolean changed = false;
    boolean ending = false;
    boolean stillRunnable = false;
    // TODO: maybe instead of running all the thread, run just one thread in round robin
    for (CpsThread t : threads.values().toArray(new CpsThread[threads.size()])) {
        if (t.isRunnable()) {
            Outcome o = t.runNextChunk();
            if (o.isFailure()) {
                // failed thread is non-resumable
                assert !t.isAlive();
                // workflow produced an exception
                Result result = Result.FAILURE;
                Throwable error = o.getAbnormal();
                if (error instanceof FlowInterruptedException) {
                    result = ((FlowInterruptedException) error).getResult();
                }
                execution.setResult(result);
                FlowNode fn = t.head.get();
                if (fn != null) {
                    t.head.get().addAction(new ErrorAction(error));
                }
            }
            if (!t.isAlive()) {
                LOGGER.fine("completed " + t);
                // do this after ErrorAction is set above
                t.fireCompletionHandlers(o);
                threads.remove(t.id);
                if (threads.isEmpty()) {
                    execution.onProgramEnd(o);
                    ending = true;
                }
            } else {
                stillRunnable |= t.isRunnable();
            }
            changed = true;
        }
    }
    if (changed && !stillRunnable) {
        execution.persistedClean = null;
        saveProgramIfPossible(false);
    }
    if (ending) {
        execution.cleanUpHeap();
        if (scripts != null) {
            scripts.clear();
        }
        closures.clear();
        try {
            Util.deleteFile(execution.getProgramDataFile());
        } catch (IOException x) {
            LOGGER.log(Level.WARNING, "Failed to delete program.dat in " + execution, x);
        }
    }
    return stillRunnable;
}
Also used : ErrorAction(org.jenkinsci.plugins.workflow.actions.ErrorAction) Outcome(com.cloudbees.groovy.cps.Outcome) FlowInterruptedException(org.jenkinsci.plugins.workflow.steps.FlowInterruptedException) IOException(java.io.IOException) Result(hudson.model.Result) FlowNode(org.jenkinsci.plugins.workflow.graph.FlowNode)

Example 8 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsBodyExecution method launch.

/**
 * Starts evaluating the body.
 *
 * If the body is a synchronous closure, this method evaluates the closure synchronously.
 * Otherwise, the body is asynchronous and the method schedules another thread to evaluate the body.
 *
 * @param currentThread
 *      The thread whose context the new thread will inherit.
 */
@CpsVmThreadOnly
/*package*/
void launch(CpsBodyInvoker params, CpsThread currentThread, FlowHead head) {
    if (isLaunched())
        throw new IllegalStateException("Already launched");
    StepStartNode sn = addBodyStartFlowNode(head);
    for (Action a : params.startNodeActions) {
        if (a != null)
            sn.addAction(a);
    }
    head.setNewHead(sn);
    CpsFlowExecution.maybeAutoPersistNode(sn);
    StepContext sc = new CpsBodySubContext(context, sn);
    for (BodyExecutionCallback c : callbacks) {
        c.onStart(sc);
    }
    try {
        // TODO: handle arguments to closure
        Object x = params.body.getBody(currentThread).call();
        // pointless synchronization to make findbugs happy. This is already done, so there's no cancelling this anyway.
        synchronized (this) {
            this.thread = currentThread;
        }
        onSuccess.receive(x);
    } catch (CpsCallableInvocation e) {
        // execute this closure asynchronously
        // TODO: does it make sense that the new thread shares the same head?
        CpsThread t = currentThread.group.addThread(createContinuable(currentThread, e), head, ContextVariableSet.from(currentThread.getContextVariables(), params.contextOverrides));
        // due to earlier cancellation
        synchronized (this) {
            t.resume(new Outcome(null, stopped));
            assert this.thread == null;
            this.thread = t;
        }
    } catch (Throwable t) {
        // body has completed synchronously and abnormally
        synchronized (this) {
            this.thread = currentThread;
        }
        onFailure.receive(t);
    }
}
Also used : ErrorAction(org.jenkinsci.plugins.workflow.actions.ErrorAction) Action(hudson.model.Action) BodyInvocationAction(org.jenkinsci.plugins.workflow.actions.BodyInvocationAction) StepStartNode(org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode) StepContext(org.jenkinsci.plugins.workflow.steps.StepContext) CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) Outcome(com.cloudbees.groovy.cps.Outcome) BodyExecutionCallback(org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback)

Example 9 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsScriptTest method evaluateShallBeCpsTransformed.

/**
 * 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)')");
    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());
}
Also used : Outcome(com.cloudbees.groovy.cps.Outcome) Ignore(org.junit.Ignore) Test(org.junit.Test)

Aggregations

Outcome (com.cloudbees.groovy.cps.Outcome)9 Continuable (com.cloudbees.groovy.cps.Continuable)2 ConstantBlock (com.cloudbees.groovy.cps.impl.ConstantBlock)2 CpsCallableInvocation (com.cloudbees.groovy.cps.impl.CpsCallableInvocation)2 ThrowBlock (com.cloudbees.groovy.cps.impl.ThrowBlock)2 IOException (java.io.IOException)2 ErrorAction (org.jenkinsci.plugins.workflow.actions.ErrorAction)2 FlowStartNode (org.jenkinsci.plugins.workflow.graph.FlowStartNode)2 Block (com.cloudbees.groovy.cps.Block)1 Env (com.cloudbees.groovy.cps.Env)1 DefaultInvoker (com.cloudbees.groovy.cps.sandbox.DefaultInvoker)1 SandboxInvoker (com.cloudbees.groovy.cps.sandbox.SandboxInvoker)1 AbortException (hudson.AbortException)1 Action (hudson.model.Action)1 Result (hudson.model.Result)1 Nonnull (javax.annotation.Nonnull)1 BodyInvocationAction (org.jenkinsci.plugins.workflow.actions.BodyInvocationAction)1 StepStartNode (org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode)1 FlowNode (org.jenkinsci.plugins.workflow.graph.FlowNode)1 BodyExecutionCallback (org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback)1