Fixed another race condition which occurs when OP_WRITE and OP_READ flags are set/cleared at the same time

This commit is contained in:
Trustin Lee 2008-10-01 08:42:26 +00:00
parent cfa6794292
commit 8d5d8fd172
2 changed files with 106 additions and 95 deletions

View File

@ -50,9 +50,11 @@ abstract class NioSocketChannel extends AbstractChannel
final SocketChannel socket; final SocketChannel socket;
private final NioSocketChannelConfig config; private final NioSocketChannelConfig config;
final Object interestOpsLock = new Object();
final Object writeLock = new Object();
final AtomicBoolean writeTaskInTaskQueue = new AtomicBoolean(); final AtomicBoolean writeTaskInTaskQueue = new AtomicBoolean();
final Runnable writeTask = new WriteTask(); final Runnable writeTask = new WriteTask();
final Object writeLock = new Object();
final Queue<MessageEvent> writeBuffer = new LinkedTransferQueue<MessageEvent>(); final Queue<MessageEvent> writeBuffer = new LinkedTransferQueue<MessageEvent>();
MessageEvent currentWriteEvent; MessageEvent currentWriteEvent;
int currentWriteIndex; int currentWriteIndex;

View File

@ -569,6 +569,10 @@ class NioWorker implements Runnable {
} }
int interestOps; int interestOps;
boolean changed = false; boolean changed = false;
// interestOps can change at any time and at any thread.
// Acquire a lock to avoid possible race condition.
synchronized (channel.interestOpsLock) {
if (opWrite) { if (opWrite) {
if (!mightNeedWakeup) { if (!mightNeedWakeup) {
interestOps = channel.getInterestOps(); interestOps = channel.getInterestOps();
@ -668,6 +672,7 @@ class NioWorker implements Runnable {
} }
} }
} }
}
if (changed) { if (changed) {
channel.setInterestOpsNow(interestOps); channel.setInterestOpsNow(interestOps);
@ -763,12 +768,15 @@ class NioWorker implements Runnable {
fireExceptionCaught(channel, cause); fireExceptionCaught(channel, cause);
} }
boolean changed = false;
try {
// interestOps can change at any time and at any thread.
// Acquire a lock to avoid possible race condition.
synchronized (channel.interestOpsLock) {
// Override OP_WRITE flag - a user cannot change this flag. // Override OP_WRITE flag - a user cannot change this flag.
interestOps &= ~Channel.OP_WRITE; interestOps &= ~Channel.OP_WRITE;
interestOps |= channel.getInterestOps() & Channel.OP_WRITE; interestOps |= channel.getInterestOps() & Channel.OP_WRITE;
boolean changed = false;
try {
switch (CONSTRAINT_LEVEL) { switch (CONSTRAINT_LEVEL) {
case 0: case 0:
if (channel.getInterestOps() != interestOps) { if (channel.getInterestOps() != interestOps) {
@ -803,6 +811,7 @@ class NioWorker implements Runnable {
default: default:
throw new Error(); throw new Error();
} }
}
future.setSuccess(); future.setSuccess();
if (changed) { if (changed) {