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 AtomicInteger writeBufferSize = new AtomicInteger();
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;
int currentWriteIndex;
@ -160,7 +172,7 @@ abstract class NioSocketChannel extends AbstractChannel
int newWriteBufferSize = writeBufferSize.addAndGet(
-((ChannelBuffer) e.getMessage()).readableBytes());
if (newWriteBufferSize <= getConfig().getWriteBufferLowWaterMark()) {
mightNeedToNotifyUnwritability = true;
exceededHighWaterMark = true;
}
}
return e;

View File

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