Fix the dead lock while failing SSL pending writes on a closed channel
Related issue: #2093 Motivation: When a channel with SslHandler is closed with pending writes (either unencrypted or encrypted), SslHandler.channelClosed() attempts to acquire a lock and fail the futures of the pending writes. If a user added a listener to any of the failed futures and the listener attempts to write something, it will make SslHandler.handleDownstream() invoked, which also attempts to acquire the same lock. Because the lock is non-reentrant, even if these two lock acquisitions are taking place in the same thread, the second attempt will block for ever. Modification: Do not fail the futures while holding a lock. Notify them after releasing the lock. Result: One less dead lock
This commit is contained in:
parent
2c17b75a99
commit
2b16d9f670
@ -1735,17 +1735,17 @@ public class SslHandler extends FrameDecoder
|
||||
return;
|
||||
}
|
||||
|
||||
Throwable cause = null;
|
||||
List<ChannelFuture> futures = null;
|
||||
try {
|
||||
for (;;) {
|
||||
PendingWrite pw = pendingUnencryptedWrites.poll();
|
||||
if (pw == null) {
|
||||
break;
|
||||
}
|
||||
if (cause == null) {
|
||||
cause = new ClosedChannelException();
|
||||
if (futures == null) {
|
||||
futures = new ArrayList<ChannelFuture>();
|
||||
}
|
||||
pw.future.setFailure(cause);
|
||||
futures.add(pw.future);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -1753,16 +1753,21 @@ public class SslHandler extends FrameDecoder
|
||||
if (ev == null) {
|
||||
break;
|
||||
}
|
||||
if (cause == null) {
|
||||
cause = new ClosedChannelException();
|
||||
if (futures != null) {
|
||||
futures = new ArrayList<ChannelFuture>();
|
||||
}
|
||||
ev.getFuture().setFailure(cause);
|
||||
futures.add(ev.getFuture());
|
||||
}
|
||||
} finally {
|
||||
pendingUnencryptedWritesLock.unlock();
|
||||
}
|
||||
|
||||
if (cause != null) {
|
||||
if (futures != null) {
|
||||
final ClosedChannelException cause = new ClosedChannelException();
|
||||
final int size = futures.size();
|
||||
for (int i = 0; i < size; i ++) {
|
||||
futures.get(i).setFailure(cause);
|
||||
}
|
||||
fireExceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user