Search in sources :

Example 11 with ThreadInterruptedError

use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.

the class ExecutionSemaphore method acquire.

/**
 * Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted.
 *
 * @param task
 *          the task to acquire a permit for.
 * @param queuePosition
 *          the position where to place the task in the queue of competing tasks if no permit is free at the time of
 *          invocation.
 * @throws ThreadInterruptedError
 *           if the current thread was interrupted while waiting.
 */
protected void acquire(final IFuture<?> task, final QueuePosition queuePosition) {
    assertSameSemaphore(task);
    final Object acquisitionLock = new Object();
    final AtomicBoolean waitingForPermit = new AtomicBoolean(true);
    compete(task, queuePosition, new IPermitAcquiredCallback() {

        @Override
        public void onPermitAcquired() {
            synchronized (acquisitionLock) {
                if (waitingForPermit.get()) {
                    acquisitionLock.notify();
                } else {
                    release(task);
                }
            }
        }
    });
    // Block the current thread until a permit is acquired.
    synchronized (acquisitionLock) {
        while (!isPermitOwner(task)) {
            try {
                acquisitionLock.wait();
            } catch (final java.lang.InterruptedException e) {
                // Restore the interrupted status because cleared by catching InterruptedException.
                Thread.currentThread().interrupt();
                waitingForPermit.set(false);
                throw new ThreadInterruptedError("Interrupted while competing for a permit").withContextInfo("task", task.getJobInput().getName()).withContextInfo("executionSemaphore", this);
            }
        }
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError)

Example 12 with ThreadInterruptedError

use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.

the class TimeoutClientRunContextStatement method evaluate.

@Override
public void evaluate() throws Throwable {
    final SafeStatementInvoker invoker = new SafeStatementInvoker(m_next);
    final IFuture<Void> future = ModelJobs.schedule(invoker, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("Running test with support for JUnit timeout"));
    try {
        if (m_timeoutMillis <= 0) {
            future.awaitDone();
        } else {
            future.awaitDone(m_timeoutMillis, TimeUnit.MILLISECONDS);
        }
    } catch (ThreadInterruptedError | TimedOutError e) {
        // NOSONAR
        future.cancel(true);
        // JUnit timeout exception
        throw new TestTimedOutException(m_timeoutMillis, TimeUnit.MILLISECONDS);
    }
    invoker.throwOnError();
}
Also used : SafeStatementInvoker(org.eclipse.scout.rt.testing.platform.runner.SafeStatementInvoker) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError) TimedOutError(org.eclipse.scout.rt.platform.util.concurrent.TimedOutError) TestTimedOutException(org.junit.runners.model.TestTimedOutException)

Example 13 with ThreadInterruptedError

use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.

the class AbstractSmartField2 method fetchLookupRows.

/**
 * Loads lookup rows according to the specified {@link ILookupRowProvider}, and notifies the specified callback upon
 * fetching completed.
 *
 * @return {@link IFuture} if data is fetched asynchronously, or <code>null</code> for synchronous fetching, or if
 *         using {@link LocalLookupCall}.
 */
private IFuture<Void> fetchLookupRows(final ILookupRowProvider<VALUE> dataProvider, final ILookupRowFetchedCallback<VALUE> callback, final boolean asynchronousFetching, final int maxRowCount) {
    cancelPotentialLookup();
    if (getLookupCall() == null) {
        callback.onSuccess(Collections.<ILookupRow<VALUE>>emptyList());
        return null;
    }
    // Prepare the lookup call.
    final ILookupCall<VALUE> lookupCall = cloneLookupCall();
    lookupCall.setMaxRowCount(maxRowCount > 0 ? maxRowCount : getBrowseMaxRowCount());
    // Prepare processing of the fetched rows.
    final ILookupRowFetchedCallback<VALUE> internalCallback = new ILookupRowFetchedCallback<VALUE>() {

        @Override
        public void onSuccess(final List<? extends ILookupRow<VALUE>> rows) {
            joinModelThreadAndUpdateField(rows, null);
        }

        @Override
        public void onFailure(final RuntimeException e) {
            joinModelThreadAndUpdateField(null, e);
        }

        private void joinModelThreadAndUpdateField(final List<? extends ILookupRow<VALUE>> rows, final RuntimeException exception) {
            if (ModelJobs.isModelThread()) {
                updateField(rows, exception);
            } else {
                // Note: The model job will not commence execution if the current ClientRunContext is or gets cancelled.
                try {
                    ClientRunContext callerRunContext = ClientRunContexts.copyCurrent();
                    if (callerRunContext.getRunMonitor().isCancelled()) {
                        return;
                    }
                    ModelJobs.schedule(new IRunnable() {

                        @Override
                        public void run() throws Exception {
                            updateField(rows, exception);
                        }
                    }, ModelJobs.newInput(callerRunContext).withName("Updating {}", AbstractSmartField2.this.getClass().getName())).awaitDone();
                } catch (ThreadInterruptedError e) {
                    /*
            This state can be reached by a race condition when the job's RunMonitor is in canceled state and later the ModelJob is run.
            This yields to a Thread.interrupt in the RunContext.ThreadInterrupter...
            
            at RunContext$ThreadInterrupter.cancel(boolean) line: 563
            at RunMonitor.cancel(ICancellable, boolean) line: 160
            at RunMonitor.registerCancellable(ICancellable) line: 104  <---------------------
            at RunContext$ThreadInterrupter.<init>(Thread, RunMonitor) line: 545
            at ClientRunContext(RunContext).call(Callable<RESULT>, Class<IExceptionTranslator<EXCEPTION>>) line: 154
            at RunContextRunner<RESULT>.intercept(Chain<RESULT>) line: 38
            
            which itself causes the running job to be interrupted with a InterruptedException
            
            at org.eclipse.scout.rt.platform.job.internal.JobExceptionTranslator.translateInterruptedException(JobExceptionTranslator.java:49)
            at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.awaitDone(JobFutureTask.java:339)
            at org.eclipse.scout.rt.client.ui.form.fields.smartfield2.AbstractSmartField2$7.joinModelThreadAndUpdateField(AbstractSmartField2.java:1598)
            at org.eclipse.scout.rt.client.ui.form.fields.smartfield2.AbstractSmartField2$7.onSuccess(AbstractSmartField2.java:1575)
            at org.eclipse.scout.rt.shared.services.lookup.LookupCall.loadData(LookupCall.java:437)
            at org.eclipse.scout.rt.shared.services.lookup.LookupCall$5.run(LookupCall.java:417)
            */
                    return;
                }
            }
        }

        private void updateField(final List<? extends ILookupRow<VALUE>> rows, final RuntimeException exception) {
            try {
                if (exception != null) {
                    // throw to handle exception at the end.
                    throw exception;
                }
                final List<ILookupRow<VALUE>> result = new ArrayList<>(rows);
                dataProvider.afterProvide(lookupCall, result);
                callback.onSuccess(result);
            } catch (FutureCancelledError | ThreadInterruptedError e) {
                // NOSONAR
                callback.onSuccess(Collections.<ILookupRow<VALUE>>emptyList());
            } catch (final RuntimeException e) {
                callback.onFailure(e);
            }
        }
    };
    // Start fetching lookup rows.
    IFuture<Void> asyncLookupFuture = null;
    try {
        dataProvider.beforeProvide(lookupCall);
        if (asynchronousFetching) {
            asyncLookupFuture = dataProvider.provideAsync(lookupCall, internalCallback, ClientRunContexts.copyCurrent());
        } else {
            dataProvider.provideSync(lookupCall, internalCallback);
            asyncLookupFuture = null;
        }
    } catch (final RuntimeException e) {
        internalCallback.onFailure(e);
        asyncLookupFuture = null;
    }
    m_lookupFuture = asyncLookupFuture;
    return asyncLookupFuture;
}
Also used : ILookupRow(org.eclipse.scout.rt.shared.services.lookup.ILookupRow) ArrayList(java.util.ArrayList) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) FutureCancelledError(org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledError) ILookupRowFetchedCallback(org.eclipse.scout.rt.shared.services.lookup.ILookupRowFetchedCallback) List(java.util.List) ArrayList(java.util.ArrayList)

Example 14 with ThreadInterruptedError

use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.

the class AbstractClientSession method cancelRunningJobs.

protected void cancelRunningJobs() {
    // Filter matches all running jobs that have the same client session associated, except the current thread
    // and model jobs. Because the current thread is (or should be) a model job, we cannot wait for other
    // model threads. They are always cancelled.
    IFilter<IFuture<?>> runningJobsFilter = Jobs.newFutureFilterBuilder().andMatch(new SessionFutureFilter(ISession.CURRENT.get())).andMatchNotFuture(IFuture.CURRENT.get()).andMatchNot(ModelJobFutureFilter.INSTANCE).andMatchNotState(JobState.DONE, JobState.REJECTED).toFilter();
    // Wait for running jobs to complete before we cancel them
    long delay = NumberUtility.nvl(CONFIG.getPropertyValue(JobCompletionDelayOnSessionShutdown.class), 0L);
    if (delay > 0L) {
        try {
            Jobs.getJobManager().awaitDone(runningJobsFilter, delay, TimeUnit.SECONDS);
        } catch (TimedOutError e) {
        // NOSONAR
        // NOP (not all jobs have been finished within the delay)
        } catch (ThreadInterruptedError e) {
            LOG.warn("Failed to await for running jobs to complete.", e);
        }
    }
    // Cancel remaining jobs and write a warning to the logger
    Set<IFuture<?>> runningFutures = Jobs.getJobManager().getFutures(runningJobsFilter);
    if (!runningFutures.isEmpty()) {
        LOG.warn("Some running client jobs found while stopping the client session; sent a cancellation request to release associated worker threads. [session={}, user={}, jobs={}]", AbstractClientSession.this, getUserId(), runningFutures);
        Jobs.getJobManager().cancel(Jobs.newFutureFilterBuilder().andMatchFuture(runningFutures).toFilter(), true);
    }
    // Now cancel all other model jobs. Because the current thread is a model job, they can never run anyway.
    Set<IFuture<?>> runningModelJobs = Jobs.getJobManager().getFutures(Jobs.newFutureFilterBuilder().andMatch(new SessionFutureFilter(ISession.CURRENT.get())).andMatchNotFuture(IFuture.CURRENT.get()).andMatch(ModelJobFutureFilter.INSTANCE).andMatchNotState(JobState.DONE, JobState.REJECTED).toFilter());
    if (!runningModelJobs.isEmpty()) {
        LOG.info("Cancel running model jobs because the client session was shut down. [session={}, user={}, jobs={}]", AbstractClientSession.this, getUserId(), runningModelJobs);
        Jobs.getJobManager().cancel(Jobs.newFutureFilterBuilder().andMatchFuture(runningModelJobs).toFilter(), true);
    }
}
Also used : SessionFutureFilter(org.eclipse.scout.rt.shared.job.filter.future.SessionFutureFilter) JobCompletionDelayOnSessionShutdown(org.eclipse.scout.rt.client.ClientConfigProperties.JobCompletionDelayOnSessionShutdown) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError) TimedOutError(org.eclipse.scout.rt.platform.util.concurrent.TimedOutError) IFuture(org.eclipse.scout.rt.platform.job.IFuture)

Example 15 with ThreadInterruptedError

use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.

the class MutualExclusionTest method testAcquisition5.

/**
 * Task1 acquires the mutex. Then, task2 tries to acquire the mutex and blocks until acquired. Because task2 cannot
 * acquire the mutex (hold by task1), it is cancelled hard (interrupted=true). That causes task2 no longer to wait for
 * the mutex, meaning that when task1 releases the mutex, task2 does not become the mutex owner.
 */
@Test(timeout = 5_000)
public void testAcquisition5() throws java.lang.InterruptedException {
    final ExecutionSemaphore mutex = (ExecutionSemaphore) m_task1.getExecutionSemaphore();
    assertEquals(0, mutex.getCompetitorCount());
    // Make task1 to acquire the mutex
    IPermitAcquiredCallback callbackTask1 = mock(IPermitAcquiredCallback.class);
    assertTrue(mutex.compete(m_task1, QueuePosition.HEAD, callbackTask1));
    verify(callbackTask1, times(1)).onPermitAcquired();
    assertTrue(mutex.isPermitOwner(m_task1));
    assertEquals(1, mutex.getCompetitorCount());
    // Task2 tries to acquire the mutex, and blocks until acquired
    final BlockingCountDownLatch interruptedLatch = new BlockingCountDownLatch(1);
    IFuture<Void> future = Jobs.schedule(new IRunnable() {

        @Override
        public void run() throws Exception {
            try {
                mutex.acquire(m_task2, QueuePosition.TAIL);
            } catch (ThreadInterruptedError e) {
                interruptedLatch.countDown();
            }
        }
    }, Jobs.newInput().withExceptionHandling(null, false));
    JobTestUtil.waitForPermitCompetitors(mutex, 2);
    assertTrue(mutex.isPermitOwner(m_task1));
    assertEquals(2, mutex.getCompetitorCount());
    future.cancel(true);
    assertTrue(interruptedLatch.await());
    assertTrue(mutex.isPermitOwner(m_task1));
    assertEquals(2, mutex.getCompetitorCount());
    mutex.release(m_task1);
    assertFalse(mutex.isPermitOwner(m_task2));
    assertEquals(0, mutex.getCompetitorCount());
}
Also used : BlockingCountDownLatch(org.eclipse.scout.rt.testing.platform.util.BlockingCountDownLatch) IExecutionSemaphore(org.eclipse.scout.rt.platform.job.IExecutionSemaphore) IPermitAcquiredCallback(org.eclipse.scout.rt.platform.job.internal.ExecutionSemaphore.IPermitAcquiredCallback) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException) Test(org.junit.Test)

Aggregations

ThreadInterruptedError (org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError)36 IRunnable (org.eclipse.scout.rt.platform.util.concurrent.IRunnable)20 Test (org.junit.Test)14 BlockingCountDownLatch (org.eclipse.scout.rt.testing.platform.util.BlockingCountDownLatch)13 TimedOutError (org.eclipse.scout.rt.platform.util.concurrent.TimedOutError)8 FutureCancelledError (org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledError)7 AssertionException (org.eclipse.scout.rt.platform.util.Assertions.AssertionException)5 ArrayList (java.util.ArrayList)4 ProcessingException (org.eclipse.scout.rt.platform.exception.ProcessingException)4 ClientRunContext (org.eclipse.scout.rt.client.context.ClientRunContext)3 PlatformException (org.eclipse.scout.rt.platform.exception.PlatformException)3 IBlockingCondition (org.eclipse.scout.rt.platform.job.IBlockingCondition)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 JMSException (javax.jms.JMSException)2 NamingException (javax.naming.NamingException)2 IClientSession (org.eclipse.scout.rt.client.IClientSession)2 IMessageBox (org.eclipse.scout.rt.client.ui.messagebox.IMessageBox)2 RunMonitor (org.eclipse.scout.rt.platform.context.RunMonitor)2 VetoException (org.eclipse.scout.rt.platform.exception.VetoException)2