Fixed|SimpleChannelPool.close() should only return after complete. (#7927)
Motivation: We need to ensure we only return from close() after all work is done as otherwise we may close the EventExecutor before we dispatched everything. Modifications: Correctly wait on operations to complete before return. Result: Fixes https://github.com/netty/netty/issues/7901.
This commit is contained in:
parent
88f0586a7e
commit
583fc272f2
@ -20,6 +20,7 @@ import io.netty.channel.Channel;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.FutureListener;
|
||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.ObjectUtil;
|
||||
import io.netty.util.internal.ThrowableUtil;
|
||||
@ -437,27 +438,43 @@ public class FixedChannelPool extends SimpleChannelPool {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
for (;;) {
|
||||
AcquireTask task = pendingAcquireQueue.poll();
|
||||
if (task == null) {
|
||||
break;
|
||||
}
|
||||
ScheduledFuture<?> f = task.timeoutFuture;
|
||||
if (f != null) {
|
||||
f.cancel(false);
|
||||
}
|
||||
task.promise.setFailure(new ClosedChannelException());
|
||||
}
|
||||
acquiredChannelCount = 0;
|
||||
pendingAcquireCount = 0;
|
||||
if (executor.inEventLoop()) {
|
||||
close0();
|
||||
} else {
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
close0();
|
||||
}
|
||||
}).awaitUninterruptibly();
|
||||
}
|
||||
}
|
||||
|
||||
private void close0() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
for (;;) {
|
||||
AcquireTask task = pendingAcquireQueue.poll();
|
||||
if (task == null) {
|
||||
break;
|
||||
}
|
||||
ScheduledFuture<?> f = task.timeoutFuture;
|
||||
if (f != null) {
|
||||
f.cancel(false);
|
||||
}
|
||||
task.promise.setFailure(new ClosedChannelException());
|
||||
}
|
||||
acquiredChannelCount = 0;
|
||||
pendingAcquireCount = 0;
|
||||
|
||||
// Ensure we dispatch this on another Thread as close0 will be called from the EventExecutor and we need
|
||||
// to ensure we will not block in a EventExecutor.
|
||||
GlobalEventExecutor.INSTANCE.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FixedChannelPool.super.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +394,8 @@ public class SimpleChannelPool implements ChannelPool {
|
||||
if (channel == null) {
|
||||
break;
|
||||
}
|
||||
channel.close();
|
||||
// Just ignore any errors that are reported back from close().
|
||||
channel.close().awaitUninterruptibly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user