NETTY-384 Another deadlock in ChunkedWriteHandler
ChunkedWriteHandler.discard() do not issue write requests to trigger exceptionCaught events and to notify write futures anymore. Instead, it triggers exceptionCaught events and notifies write futures by itself. Therefore, no write lock is involved during discard(), avoiding the reported dead lock. However, this is a temporary solution, and eventually Netty must introduce more robust event thread model.
This commit is contained in:
parent
d72b89db21
commit
73d1f3fe02
@ -17,6 +17,7 @@ package org.jboss.netty.handler.stream;
|
|||||||
|
|
||||||
import static org.jboss.netty.channel.Channels.*;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
|
|
||||||
|
import java.nio.channels.ClosedChannelException;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
@ -150,7 +151,10 @@ public class ChunkedWriteHandler implements ChannelUpstreamHandler, ChannelDowns
|
|||||||
ctx.sendUpstream(e);
|
ctx.sendUpstream(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void discard(ChannelHandlerContext ctx) {
|
private void discard(ChannelHandlerContext ctx) {
|
||||||
|
ClosedChannelException cause = null;
|
||||||
|
boolean fireExceptionCaught = false;
|
||||||
|
synchronized (this) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (currentEvent == null) {
|
if (currentEvent == null) {
|
||||||
currentEvent = queue.poll();
|
currentEvent = queue.poll();
|
||||||
@ -166,19 +170,24 @@ public class ChunkedWriteHandler implements ChannelUpstreamHandler, ChannelDowns
|
|||||||
Object m = currentEvent.getMessage();
|
Object m = currentEvent.getMessage();
|
||||||
if (m instanceof ChunkedInput) {
|
if (m instanceof ChunkedInput) {
|
||||||
closeInput((ChunkedInput) m);
|
closeInput((ChunkedInput) m);
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger a ClosedChannelException
|
// Trigger a ClosedChannelException
|
||||||
Channels.write(
|
if (cause == null) {
|
||||||
ctx, currentEvent.getFuture(), ChannelBuffers.EMPTY_BUFFER,
|
cause = new ClosedChannelException();
|
||||||
currentEvent.getRemoteAddress());
|
|
||||||
} else {
|
|
||||||
// Trigger a ClosedChannelException
|
|
||||||
ctx.sendDownstream(currentEvent);
|
|
||||||
}
|
}
|
||||||
|
currentEvent.getFuture().setFailure(cause);
|
||||||
|
fireExceptionCaught = true;
|
||||||
|
|
||||||
currentEvent = null;
|
currentEvent = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fireExceptionCaught) {
|
||||||
|
Channels.fireExceptionCaught(currentEvent.getChannel(), cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void flush(ChannelHandlerContext ctx) throws Exception {
|
private synchronized void flush(ChannelHandlerContext ctx) throws Exception {
|
||||||
final Channel channel = ctx.getChannel();
|
final Channel channel = ctx.getChannel();
|
||||||
if (!channel.isConnected()) {
|
if (!channel.isConnected()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user