[#1310] Fix deadlock which can happen if limit of MemoryAwareThreadPoolExecutor was exceed and an exceptionCaught(..) is triggered by a write
This commit is contained in:
parent
960067c78a
commit
60695012ab
@ -31,7 +31,9 @@ import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
@ -171,6 +173,8 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
||||
final WritableByteChannel ch = channel.channel;
|
||||
final Queue<MessageEvent> writeBuffer = channel.writeBufferQueue;
|
||||
final int writeSpinCount = channel.getConfig().getWriteSpinCount();
|
||||
List<Throwable> causes = null;
|
||||
|
||||
synchronized (channel.writeLock) {
|
||||
channel.inWriteNowLoop = true;
|
||||
for (;;) {
|
||||
@ -245,7 +249,14 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
||||
future.setFailure(t);
|
||||
}
|
||||
if (iothread) {
|
||||
fireExceptionCaught(channel, t);
|
||||
// An exception was thrown from within a write in the iothread. We store a reference to it
|
||||
// in a list for now and notify the handlers in the chain after the writeLock was released
|
||||
// to prevent possible deadlock.
|
||||
// See #1310
|
||||
if (causes == null) {
|
||||
causes = new ArrayList<Throwable>(1);
|
||||
}
|
||||
causes.add(t);
|
||||
} else {
|
||||
fireExceptionCaughtLater(channel, t);
|
||||
}
|
||||
@ -273,11 +284,18 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
||||
} else if (removeOpWrite) {
|
||||
clearOpWrite(channel);
|
||||
}
|
||||
} else {
|
||||
// close the channel now
|
||||
close(channel, succeededFuture(channel));
|
||||
}
|
||||
}
|
||||
if (causes != null) {
|
||||
for (Throwable cause: causes) {
|
||||
// notify about cause now as it was triggered in the write loop
|
||||
fireExceptionCaught(channel, cause);
|
||||
}
|
||||
}
|
||||
if (!open) {
|
||||
// close the channel now
|
||||
close(channel, succeededFuture(channel));
|
||||
}
|
||||
if (iothread) {
|
||||
fireWriteComplete(channel, writtenBytes);
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user