This repository was archived by the owner on Mar 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 60
This repository was archived by the owner on Mar 20, 2021. It is now read-only.
Request is interrupted by the timer thread although transaction timeout does not occur. #1840
Copy link
Copy link
Closed
Description
Request is interrupted by the timer thread although transaction timeout does not occur.
This problem occurs when the thread pool starts and AbstractThreadPool#onWorkerStarted is called.
**AbstractThreadPool.java** protected void onWorkerStarted(final Worker worker) {
if (delayedQueue != null) {
delayedQueue.add(worker, NEVER_TIMEOUT, TimeUnit.MILLISECONDS);
}
ProbeNotifier.notifyThreadAllocated(this, worker.t);
}
By adding NEVER_TIMEOUT(=Long.MAX_VALUE) to delayedQueue, timeout becomes minus value because of overflow.
**DelayedExecutor.java DelayQueue** public void add(final E elem, final long delay, final TimeUnit timeUnit) {
if (delay >= 0) {
resolver.setTimeoutMillis(elem, System.currentTimeMillis()***(1) +
TimeUnit.MILLISECONDS.convert(delay, timeUnit));
queue.put(elem, this);
}
}
At the same time, if the timer thread executes following code,
timeoutMillis may be minus value because the previous overflow at DelayQueue.
In this case, currentTimeMillis - timeoutMillis >= 0 may be true if currentTimeMillis is smaller than *** (1).
Therefore, unexpected timeout occurs and the thread is interrupted.
**DelayedExecutor.java DelayedRunnable** private class DelayedRunnable implements Runnable {
@SuppressWarnings("unchecked")
@Override
public void run() {
while(isStarted) {
final long currentTimeMillis = System.currentTimeMillis();
for (final DelayQueue delayQueue : queues) {
if (delayQueue.queue.isEmpty()) continue;
final Resolver resolver = delayQueue.resolver;
for (Iterator it = delayQueue.queue.keySet().iterator(); it.hasNext(); ) {
final Object element = it.next();
final long timeoutMillis = resolver.getTimeoutMillis(element);
if (timeoutMillis == UNSET_TIMEOUT) {
it.remove();
if (wasModified(timeoutMillis,
resolver.getTimeoutMillis(element))) {
delayQueue.queue.put(element, delayQueue);
}
} else if (currentTimeMillis - timeoutMillis >= 0) {
it.remove();
if (wasModified(timeoutMillis,
resolver.getTimeoutMillis(element))) {
delayQueue.queue.put(element, delayQueue);
} else {
try {
if (!delayQueue.worker.doWork(element)) {
delayQueue.queue.put(element, delayQueue);
}
} catch (Exception ignored) {
}
}
}
}
}
synchronized(sync) {
if (!isStarted) return;
try {
sync.wait(checkIntervalMillis);
} catch (InterruptedException ignored) {
}
}
}
}
}
This problem will be reproducible by the following batch.
**start_stop.bat**@echo off
setlocal enabledelayedexpansion
:loop
call C:\work\glassfish4\glassfish\bin\asadmin start-cluster cluster
SET CMD="call C:\work\glassfish4\glassfish\bin\asadmin deploy --target cluster --force c:\work\apps\HelloServlet.war"
SET EXCEPTION="SSLHandshakeException"
FOR /f "usebackq DELIMS=" %%a IN (`%CMD%`) DO (
ECHO %%a
ECHO %%a | find %EXCEPTION%
IF !ERRORLEVEL! == 0 (
exit /b 1
)
)
call C:\work\glassfish4\glassfish\bin\asadmin undeploy --target cluster HelloServlet
call C:\work\glassfish4\glassfish\bin\asadmin stop-cluster cluster
goto :loop
endlocal
This batch will exit by SSLHandshakeException in Grizzly.
Application deployed with name HelloServlet.
Warning: Command _deploy did not complete successfully on server instance instance: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Warning: Command _deploy did not complete successfully on server instance instance: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Reactions are currently unavailable