Fixed stack overflow error

This commit is contained in:
Trustin Lee 2008-11-28 06:45:16 +00:00
parent 38943f3d23
commit 4e7852e29e
2 changed files with 40 additions and 18 deletions

View File

@ -59,8 +59,20 @@ abstract class NioSocketChannel extends AbstractChannel
final Runnable writeTask = new WriteTask(); final Runnable writeTask = new WriteTask();
final AtomicInteger writeBufferSize = new AtomicInteger(); final AtomicInteger writeBufferSize = new AtomicInteger();
final Queue<MessageEvent> writeBuffer = new WriteBuffer(); final Queue<MessageEvent> writeBuffer = new WriteBuffer();
boolean wasWritable;
boolean mightNeedToNotifyUnwritability; /** Previous return value of isWritable() */
boolean oldWritable;
/**
* Set to true if the amount of data in the writeBuffer exceeds
* the high water mark, as specified in NioSocketChannelConfig.
*/
boolean exceededHighWaterMark;
/**
* true if and only if NioWorker is firing an event which might cause
* infinite recursion.
*/
boolean firingEvent;
MessageEvent currentWriteEvent; MessageEvent currentWriteEvent;
int currentWriteIndex; int currentWriteIndex;
@ -160,7 +172,7 @@ abstract class NioSocketChannel extends AbstractChannel
int newWriteBufferSize = writeBufferSize.addAndGet( int newWriteBufferSize = writeBufferSize.addAndGet(
-((ChannelBuffer) e.getMessage()).readableBytes()); -((ChannelBuffer) e.getMessage()).readableBytes());
if (newWriteBufferSize <= getConfig().getWriteBufferLowWaterMark()) { if (newWriteBufferSize <= getConfig().getWriteBufferLowWaterMark()) {
mightNeedToNotifyUnwritability = true; exceededHighWaterMark = true;
} }
} }
return e; return e;

View File

@ -479,25 +479,35 @@ class NioWorker implements Runnable {
private static void fireChannelInterestChangedIfNecessary( private static void fireChannelInterestChangedIfNecessary(
NioSocketChannel channel, boolean open) { NioSocketChannel channel, boolean open) {
int interestOps = channel.getRawInterestOps(); if (channel.firingEvent) {
boolean wasWritable = channel.wasWritable; // Prevent StackOverflowError.
boolean writable = channel.wasWritable = open? channel.isWritable() : false; return;
if (wasWritable) { }
if (writable) {
if (channel.mightNeedToNotifyUnwritability) { channel.firingEvent = true;
channel.mightNeedToNotifyUnwritability = false; try {
int interestOps = channel.getRawInterestOps();
boolean wasWritable = channel.oldWritable;
boolean writable = channel.oldWritable = open? channel.isWritable() : false;
if (wasWritable) {
if (writable) {
if (channel.exceededHighWaterMark) {
channel.exceededHighWaterMark = false;
fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE);
fireChannelInterestChanged(channel, interestOps & ~Channel.OP_WRITE);
}
} else {
fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE); fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE);
fireChannelInterestChanged(channel, interestOps & ~Channel.OP_WRITE);
} }
} else { } else {
fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE); if (writable) {
} fireChannelInterestChanged(channel, interestOps & ~Channel.OP_WRITE);
} else { } else {
if (writable) { fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE);
fireChannelInterestChanged(channel, interestOps & ~Channel.OP_WRITE); }
} else {
fireChannelInterestChanged(channel, interestOps | Channel.OP_WRITE);
} }
} finally {
channel.firingEvent = false;
} }
} }