From 3d4ae360746c7f95b42a685d1254e69d0f0061f4 Mon Sep 17 00:00:00 2001 From: Kun Zhang Date: Mon, 12 Sep 2016 09:58:46 -0700 Subject: [PATCH] Fix a deadlock in TransportSet. Honor the lock order that transport lock > channel lock. Resolves #2246 --- core/src/main/java/io/grpc/internal/TransportSet.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/grpc/internal/TransportSet.java b/core/src/main/java/io/grpc/internal/TransportSet.java index 025b83276f..d89a8ac49c 100644 --- a/core/src/main/java/io/grpc/internal/TransportSet.java +++ b/core/src/main/java/io/grpc/internal/TransportSet.java @@ -249,9 +249,14 @@ final class TransportSet implements WithLogId { delayedTransport.endBackoff(); boolean shutdownDelayedTransport = false; Runnable runnable = null; + // TransportSet as a channel layer class should not call into transport methods while + // holding the lock, thus we call hasPendingStreams() outside of the lock. It will cause + // a _benign_ race where the TransportSet may transition to CONNECTING when there is not + // pending stream. + boolean hasPendingStreams = delayedTransport.hasPendingStreams(); synchronized (lock) { reconnectTask = null; - if (delayedTransport.hasPendingStreams()) { + if (hasPendingStreams) { // Transition directly to CONNECTING runnable = startNewTransport(delayedTransport); } else {