Skip to content

Commit 6f620cd

Browse files
committed
[UNDERTOW-2125] At ReadTimeoutStreamSourceConduit, skip expiration if connection is not open.
Also: - prevent unneeded duplicate scheduling by checking if handle is null before rescheduling - make handle volatile and properly synchronize with a double check when rescheduling timeout expiration - [UNDERTOW-2083] calculate the elapsed time in the expiration properly when throwing the timeout exception Signed-off-by: Flavia Rainone <[email protected]>
1 parent 9a06b56 commit 6f620cd

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

core/src/main/java/io/undertow/conduits/ReadTimeoutStreamSourceConduit.java

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@
1818

1919
package io.undertow.conduits;
2020

21-
import java.io.IOException;
22-
import java.nio.ByteBuffer;
23-
import java.nio.channels.FileChannel;
24-
import java.util.concurrent.TimeUnit;
25-
2621
import io.undertow.UndertowLogger;
2722
import io.undertow.UndertowMessages;
2823
import io.undertow.UndertowOptions;
@@ -41,6 +36,11 @@
4136
import org.xnio.conduits.ReadReadyHandler;
4237
import org.xnio.conduits.StreamSourceConduit;
4338

39+
import java.io.IOException;
40+
import java.nio.ByteBuffer;
41+
import java.nio.channels.FileChannel;
42+
import java.util.concurrent.TimeUnit;
43+
4444
/**
4545
* Wrapper for read timeout. This should always be the first wrapper applied to the underlying channel.
4646
*
@@ -49,7 +49,7 @@
4949
*/
5050
public final class ReadTimeoutStreamSourceConduit extends AbstractStreamSourceConduit<StreamSourceConduit> {
5151

52-
private XnioExecutor.Key handle;
52+
private volatile XnioExecutor.Key handle;
5353
private final StreamConnection connection;
5454
private volatile long expireTime = -1;
5555
private final OpenListener openListener;
@@ -60,14 +60,21 @@ public final class ReadTimeoutStreamSourceConduit extends AbstractStreamSourceCo
6060
private final Runnable timeoutCommand = new Runnable() {
6161
@Override
6262
public void run() {
63-
handle = null;
64-
if (expireTime == -1) {
63+
synchronized (ReadTimeoutStreamSourceConduit.this) {
64+
handle = null;
65+
}
66+
if (expireTime == -1 || !connection.isOpen()) {
6567
return;
6668
}
6769
long current = System.currentTimeMillis();
6870
if (current < expireTime) {
6971
//timeout has been bumped, re-schedule
70-
handle = WorkerUtils.executeAfter(connection.getIoThread(),timeoutCommand, (expireTime - current) + FUZZ_FACTOR, TimeUnit.MILLISECONDS);
72+
if (handle == null) {
73+
synchronized (ReadTimeoutStreamSourceConduit.this) {
74+
if (handle == null)
75+
handle = WorkerUtils.executeAfter(connection.getIoThread(), timeoutCommand, (expireTime - current) + FUZZ_FACTOR, TimeUnit.MILLISECONDS);
76+
}
77+
}
7178
return;
7279
}
7380
UndertowLogger.REQUEST_LOGGER.tracef("Timing out channel %s due to inactivity", connection.getSourceChannel());
@@ -131,12 +138,16 @@ private void handleReadTimeout(final long ret) throws IOException {
131138
final long expireTimeVar = expireTime;
132139
if (expireTimeVar != -1 && currentTime > expireTimeVar) {
133140
IoUtils.safeClose(connection);
134-
throw UndertowMessages.MESSAGES.readTimedOut(this.getTimeout());
141+
throw UndertowMessages.MESSAGES.readTimedOut(currentTime - (expireTimeVar - this.getTimeout()));
135142
}
136143
}
137144
expireTime = currentTime + timeout;
138145
if (handle == null) {
139-
handle = connection.getIoThread().executeAfter(timeoutCommand, timeout, TimeUnit.MILLISECONDS);
146+
synchronized (this) {
147+
if (handle == null)
148+
handle = connection.getIoThread().executeAfter(timeoutCommand, timeout, TimeUnit.MILLISECONDS);
149+
}
150+
140151
}
141152
}
142153

@@ -232,9 +243,13 @@ public void terminateReads() throws IOException {
232243

233244
private void cleanup() {
234245
if (handle != null) {
235-
handle.remove();
236-
handle = null;
237-
expireTime = -1;
246+
synchronized (this) {
247+
if (handle != null) {
248+
handle.remove();
249+
handle = null;
250+
expireTime = -1;
251+
}
252+
}
238253
}
239254
}
240255

@@ -247,7 +262,7 @@ public void suspendReads() {
247262
private void checkExpired() throws ReadTimeoutException {
248263
synchronized (this) {
249264
if (expired) {
250-
throw UndertowMessages.MESSAGES.readTimedOut(System.currentTimeMillis());
265+
throw UndertowMessages.MESSAGES.readTimedOut(System.currentTimeMillis() - (expireTime - getTimeout()));
251266
}
252267
}
253268
}

0 commit comments

Comments
 (0)