Skip to content

Commit f5b1117

Browse files
authored
servlet: fix unpark() of onWritePossible() thread
This should fix #12268
1 parent c7202c0 commit f5b1117

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ signature-java = "org.codehaus.mojo.signature:java18:1.0"
112112
tomcat-embed-core = "org.apache.tomcat.embed:tomcat-embed-core:10.1.31"
113113
tomcat-embed-core9 = "org.apache.tomcat.embed:tomcat-embed-core:9.0.89"
114114
truth = "com.google.truth:truth:1.4.4"
115-
undertow-servlet22 = "io.undertow:undertow-servlet:2.2.32.Final"
115+
undertow-servlet22 = "io.undertow:undertow-servlet:2.2.37.Final"
116116
undertow-servlet = "io.undertow:undertow-servlet:2.3.18.Final"
117117

118118
# Do not update: Pinned to the last version supporting Java 8.

servlet/src/main/java/io/grpc/servlet/AsyncServletOutputStreamWriter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
import io.grpc.InternalLogId;
2727
import io.grpc.servlet.ServletServerStream.ServletTransportState;
2828
import java.io.IOException;
29-
import java.time.Duration;
3029
import java.util.Queue;
3130
import java.util.concurrent.ConcurrentLinkedQueue;
31+
import java.util.concurrent.TimeUnit;
3232
import java.util.concurrent.atomic.AtomicReference;
3333
import java.util.concurrent.locks.LockSupport;
3434
import java.util.function.BiFunction;
@@ -128,7 +128,7 @@ public void finest(String str, Object... params) {
128128
log.fine("call completed");
129129
});
130130
};
131-
this.isReady = () -> outputStream.isReady();
131+
this.isReady = outputStream::isReady;
132132
}
133133

134134
/**
@@ -173,7 +173,9 @@ void complete() {
173173
/** Called from the container thread {@link javax.servlet.WriteListener#onWritePossible()}. */
174174
void onWritePossible() throws IOException {
175175
log.finest("onWritePossible: ENTRY. The servlet output stream becomes ready");
176-
assureReadyAndDrainedTurnsFalse();
176+
if (writeState.get().readyAndDrained) {
177+
assureReadyAndDrainedTurnsFalse();
178+
}
177179
while (isReady.getAsBoolean()) {
178180
WriteState curState = writeState.get();
179181

@@ -200,11 +202,9 @@ private void assureReadyAndDrainedTurnsFalse() {
200202
// readyAndDrained should have been set to false already.
201203
// Just in case due to a race condition readyAndDrained is still true at this moment and is
202204
// being set to false by runOrBuffer() concurrently.
205+
parkingThread = Thread.currentThread();
203206
while (writeState.get().readyAndDrained) {
204-
parkingThread = Thread.currentThread();
205-
// Try to sleep for an extremely long time to avoid writeState being changed at exactly
206-
// the time when sleep time expires (in extreme scenario, such as #9917).
207-
LockSupport.parkNanos(Duration.ofHours(1).toNanos()); // should return immediately
207+
LockSupport.parkNanos(TimeUnit.MINUTES.toNanos(1)); // should return immediately
208208
}
209209
parkingThread = null;
210210
}
@@ -254,7 +254,7 @@ interface ActionItem {
254254
@VisibleForTesting // Lincheck test can not run with java.util.logging dependency.
255255
interface Log {
256256
default boolean isLoggable(Level level) {
257-
return false;
257+
return false;
258258
}
259259

260260
default void fine(String str, Object...params) {}

0 commit comments

Comments
 (0)