Fix memory leak in AbstractEmbeddedChannel
- Allow a transport implementation to perform an arbitrary task when a channel has been deregistered completely
This commit is contained in:
parent
d2b137649d
commit
70a51bcd8d
@ -741,8 +741,9 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable postTask = null;
|
||||
try {
|
||||
doDeregister();
|
||||
postTask = doDeregister();
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Unexpected exception occurred while deregistering a channel.", t);
|
||||
} finally {
|
||||
@ -756,6 +757,10 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
||||
// close() calls deregister() again - no need to fire channelUnregistered.
|
||||
promise.setSuccess();
|
||||
}
|
||||
|
||||
if (postTask != null) {
|
||||
postTask.run();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eventLoop().execute(new Runnable() {
|
||||
@ -973,11 +978,12 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
||||
|
||||
/**
|
||||
* Deregister the {@link Channel} from its {@link EventLoop}.
|
||||
* You can return a {@link Runnable} which will be run as post-task of the registration process.
|
||||
*
|
||||
* Sub-classes may override this method
|
||||
*/
|
||||
protected void doDeregister() throws Exception {
|
||||
// NOOP
|
||||
protected Runnable doDeregister() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,8 +225,13 @@ public abstract class AbstractEmbeddedChannel<O> extends AbstractChannel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDeregister() throws Exception {
|
||||
// NOOP
|
||||
protected Runnable doDeregister() throws Exception {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runPendingTasks();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,8 +26,8 @@ import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.DefaultChannelConfig;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||
import io.netty.channel.SingleThreadEventLoop;
|
||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
@ -201,11 +201,12 @@ public class LocalChannel extends AbstractChannel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDeregister() throws Exception {
|
||||
protected Runnable doDeregister() throws Exception {
|
||||
if (isOpen()) {
|
||||
unsafe().close(unsafe().voidFuture());
|
||||
}
|
||||
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,8 +22,8 @@ import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.DefaultChannelConfig;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.ServerChannel;
|
||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||
import io.netty.channel.SingleThreadEventLoop;
|
||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@ -126,8 +126,9 @@ public class LocalServerChannel extends AbstractServerChannel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDeregister() throws Exception {
|
||||
protected Runnable doDeregister() throws Exception {
|
||||
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -273,8 +273,9 @@ public abstract class AbstractNioChannel extends AbstractChannel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDeregister() throws Exception {
|
||||
protected Runnable doDeregister() throws Exception {
|
||||
eventLoop().cancel(selectionKey());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user