[#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.SelectionKey;
|
||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@ -171,6 +173,8 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
|||||||
final WritableByteChannel ch = channel.channel;
|
final WritableByteChannel ch = channel.channel;
|
||||||
final Queue<MessageEvent> writeBuffer = channel.writeBufferQueue;
|
final Queue<MessageEvent> writeBuffer = channel.writeBufferQueue;
|
||||||
final int writeSpinCount = channel.getConfig().getWriteSpinCount();
|
final int writeSpinCount = channel.getConfig().getWriteSpinCount();
|
||||||
|
List<Throwable> causes = null;
|
||||||
|
|
||||||
synchronized (channel.writeLock) {
|
synchronized (channel.writeLock) {
|
||||||
channel.inWriteNowLoop = true;
|
channel.inWriteNowLoop = true;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -245,7 +249,14 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
|||||||
future.setFailure(t);
|
future.setFailure(t);
|
||||||
}
|
}
|
||||||
if (iothread) {
|
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 {
|
} else {
|
||||||
fireExceptionCaughtLater(channel, t);
|
fireExceptionCaughtLater(channel, t);
|
||||||
}
|
}
|
||||||
@ -273,11 +284,18 @@ abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
|
|||||||
} else if (removeOpWrite) {
|
} else if (removeOpWrite) {
|
||||||
clearOpWrite(channel);
|
clearOpWrite(channel);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
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 the channel now
|
||||||
close(channel, succeededFuture(channel));
|
close(channel, succeededFuture(channel));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (iothread) {
|
if (iothread) {
|
||||||
fireWriteComplete(channel, writtenBytes);
|
fireWriteComplete(channel, writtenBytes);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user