use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.
the class FutureAwaitTest method testBlockingConditionWaitFor_Interrupted.
@Test(timeout = 5000)
public void testBlockingConditionWaitFor_Interrupted() throws java.lang.InterruptedException {
final IBlockingCondition condition = Jobs.newBlockingCondition(true);
// Run the test in a separate thread
IFuture<Void> controller = Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
Thread.currentThread().interrupt();
try {
condition.waitFor();
fail("interruption expected");
} catch (ThreadInterruptedError e) {
assertTrue(Thread.currentThread().isInterrupted());
}
}
}, Jobs.newInput());
controller.awaitDoneAndGet(10, TimeUnit.SECONDS);
}
use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.
the class AbstractServiceTunnel method checkAlreadyCancelled.
/**
* Will throw a CancellationException if the future is already cancelled.
*
* @throws ThreadInterruptedError
* if the current thread is cancelled
*/
protected void checkAlreadyCancelled(ServiceTunnelRequest serviceRequest) {
final RunMonitor monitor = RunMonitor.CURRENT.get();
if (monitor != null && monitor.isCancelled()) {
final StringBuilder cancellationExceptionText = new StringBuilder();
cancellationExceptionText.append("RunMonitor is already cancelled.");
if (serviceRequest != null) {
cancellationExceptionText.append(" (Request was '");
cancellationExceptionText.append(serviceRequest.getServiceInterfaceClassName());
cancellationExceptionText.append(".");
cancellationExceptionText.append(serviceRequest.getOperation());
cancellationExceptionText.append("(..)')");
}
throw new ThreadInterruptedError(cancellationExceptionText.toString());
}
}
use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.
the class RemoteServiceInvocationCallable method cancel.
/**
* Cancels the remote service operation on server side.
*/
public void cancel() {
try {
final String sessionId = m_serviceRequest.getSessionId();
if (sessionId == null) {
// cannot cancel an event without session. The IRunMonitorCancelService requires a session.
return;
}
final Method serviceMethod = IRunMonitorCancelService.class.getMethod(IRunMonitorCancelService.CANCEL_METHOD, long.class);
final Object[] serviceArgs = new Object[] { m_serviceRequest.getRequestSequence() };
ServiceTunnelRequest request = m_tunnel.createRequest(IRunMonitorCancelService.class, serviceMethod, serviceArgs);
request.setClientNodeId(m_serviceRequest.getClientNodeId());
request.setSessionId(sessionId);
request.setUserAgent(m_serviceRequest.getUserAgent());
m_tunnel.invokeService(request);
} catch (final FutureCancelledError | ThreadInterruptedError e) {
// NOSONAR
// NOOP: Do not cancel 'cancel-request' to prevent loop.
} catch (RuntimeException | NoSuchMethodException e) {
LOG.warn("Failed to cancel server processing [requestSequence={}]", m_serviceRequest.getRequestSequence(), e);
}
}
use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.
the class MutualExclusionTest method testBlockingCondition_InterruptedWhileReAcquiringTheMutex.
/**
* We have 3 jobs that are scheduled simultaneously. Thereby, job1 enters a blocking condition which in turn lets job2
* run. Job2 unblocks job1 so that job1 is trying to re-acquire the mutex. While waiting for the mutex to be
* available, job1 is interrupted due to a cancel-request of job2.<br/>
* This test verifies, that job1 is interrupted, competes for the mutex anew and only continues once a permit becomes
* available. Also, job3 must not start running as long as job1 did not complete.
*/
@Test
// regression
@Times(100)
public void testBlockingCondition_InterruptedWhileReAcquiringTheMutex() throws java.lang.InterruptedException {
// synchronized because modified/read by different threads.
final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
final IBlockingCondition condition = Jobs.newBlockingCondition(true);
final BlockingCountDownLatch latchJob2 = new BlockingCountDownLatch(1);
final BlockingCountDownLatch job1FinishLatch = new BlockingCountDownLatch(1);
final IFuture<Void> future1 = ModelJobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("running-1");
try {
protocol.add("before-blocking-1");
condition.waitFor();
} catch (ThreadInterruptedError e) {
protocol.add("interrupted-1 (a)");
} catch (RuntimeException e) {
protocol.add("jobException-1");
}
if (Thread.currentThread().isInterrupted()) {
protocol.add("interrupted-1 (b)");
}
if (ModelJobs.isModelThread()) {
protocol.add("model-thread-1");
}
protocol.add("done-1");
job1FinishLatch.countDown();
}
}, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-1").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
final IFuture<Void> future2 = ModelJobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("running-2a");
if (future1.getState() == JobState.WAITING_FOR_BLOCKING_CONDITION) {
protocol.add("job2: job-1-waiting-for-blocking-condition");
}
if (!future1.getExecutionSemaphore().isPermitOwner(future1)) {
protocol.add("job2: job-1-not-permit-owner");
}
protocol.add("unblocking condition");
condition.setBlocking(false);
// job-1 (interrupted acquisition task), job-2 (latch), job-3 (waiting for mutex)
JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 3);
if (future1.getState() == JobState.WAITING_FOR_PERMIT) {
protocol.add("job2: job-1-waiting-for-mutex");
}
protocol.add("before-cancel-job1-2");
// interrupt job1 while acquiring the mutex
future1.cancel(true);
// job-1 (interrupted acquisition task), job-1 (re-acquiring a permit), job-2 (latch), job-3 (waiting for mutex)
JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 4);
// cancelled, but still running
JobTestUtil.waitForState(future1, JobState.DONE);
protocol.add("running-2b");
latchJob2.countDownAndBlock();
protocol.add("done-2");
}
}, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-2").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
final IFuture<Void> future3 = ModelJobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("done-3");
}
}, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-3").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
assertTrue(latchJob2.await());
assertEquals(future1.getState(), JobState.DONE);
assertEquals(future2.getState(), JobState.RUNNING);
assertEquals(future3.getState(), JobState.WAITING_FOR_PERMIT);
latchJob2.unblock();
Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(JOB_IDENTIFIER).toFilter(), 5, TimeUnit.SECONDS);
List<String> expectedProtocol = new ArrayList<>();
expectedProtocol.add("running-1");
expectedProtocol.add("before-blocking-1");
expectedProtocol.add("running-2a");
expectedProtocol.add("job2: job-1-waiting-for-blocking-condition");
expectedProtocol.add("job2: job-1-not-permit-owner");
expectedProtocol.add("unblocking condition");
expectedProtocol.add("job2: job-1-waiting-for-mutex");
expectedProtocol.add("before-cancel-job1-2");
expectedProtocol.add("running-2b");
expectedProtocol.add("done-2");
expectedProtocol.add("interrupted-1 (b)");
expectedProtocol.add("model-thread-1");
expectedProtocol.add("done-1");
expectedProtocol.add("done-3");
assertEquals(expectedProtocol, protocol);
assertEquals(future1.getState(), JobState.DONE);
assertEquals(future2.getState(), JobState.DONE);
assertEquals(future3.getState(), JobState.DONE);
assertTrue(future1.isCancelled());
future1.awaitDone(1, TimeUnit.NANOSECONDS);
assertFalse(future2.isCancelled());
future2.awaitDone(1, TimeUnit.NANOSECONDS);
assertFalse(future3.isCancelled());
future3.awaitDone(1, TimeUnit.NANOSECONDS);
}
use of org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError in project scout.rt by eclipse.
the class DefaultBeanInstanceProducer method getApplicationScopedInstance.
private T getApplicationScopedInstance(final IBean<T> bean) {
T instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
if (m_creatorThread.compareAndSet(null, Thread.currentThread())) {
try {
// check again to avoid race conditions
instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
// current thread has to create instance
instance = safeCreateInstance(bean.getBeanClazz());
m_applicationScopedInstance.set(instance);
return instance;
} finally {
synchronized (this) {
// reset creator thread so that another one tries to create the bean again in case the current ran into an exception.
m_creatorThread.set(null);
// wake up other threads waiting on the application-scoped instance
this.notifyAll();
}
}
}
// remember creator thread for logging purposes
final Thread creatorThread = m_creatorThread.get();
final int maxWaitTimeSeconds = getDeadlockDetectionMaxWaitTimeSeconds();
final long maxWaitEndTimeMillis = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(maxWaitTimeSeconds);
boolean logDebug = LOG.isDebugEnabled();
do {
try {
synchronized (this) {
if (m_creatorThread.get() == null) {
break;
}
long waitTimeMillis = logDebug ? TimeUnit.SECONDS.toMillis(Math.min(maxWaitTimeSeconds, DEADLOCK_DETECTION_DEBUG_WAIT_TIME_SECONDS)) : maxWaitEndTimeMillis - System.currentTimeMillis();
if (waitTimeMillis > 0) {
// wait for the creator to complete, but not too long because the notify signal could have been missed
this.wait(waitTimeMillis);
}
}
} catch (InterruptedException e) {
throw new ThreadInterruptedError("Thread has been interrupted");
}
if (m_creatorThread.get() == null) {
break;
}
if (logDebug) {
logWarnPotentialDeadlock(creatorThread);
logDebug = false;
}
} while (// try as long as the other thread is still creating the bean and the max wait time has not been elapsed
System.currentTimeMillis() < maxWaitEndTimeMillis);
// check if bean has been created in the meantime
instance = m_applicationScopedInstance.get();
if (instance != null) {
return instance;
}
// bean has not been created
if (System.currentTimeMillis() < maxWaitEndTimeMillis) {
throw new BeanCreationException("Thread was waiting on bean instance creator thread which most likely failed (check the log).").withContextInfo("beanClass", bean == null || bean.getBeanClazz() == null ? "n/a" : bean.getBeanClazz().getName()).withContextInfo("creatorThreadID", creatorThread == null ? "n/a" : creatorThread.getId()).withContextInfo("creatorThreadName", creatorThread == null ? "n/a" : creatorThread.getName());
} else {
logWarnPotentialDeadlock(creatorThread);
throw new BeanCreationException("Potential deadlock detected: bean is being created by another thread. Either the creation takes longer than {}s " + "or the current and the creator threads are blocking each other (check the log).", maxWaitTimeSeconds).withContextInfo("beanClass", bean == null || bean.getBeanClazz() == null ? "n/a" : bean.getBeanClazz().getName()).withContextInfo("creatorThreadID", creatorThread == null ? "n/a" : creatorThread.getId()).withContextInfo("creatorThreadName", creatorThread == null ? "n/a" : creatorThread.getName());
}
}
Aggregations