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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Runnable postTask = null;
|
||||||
try {
|
try {
|
||||||
doDeregister();
|
postTask = doDeregister();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.warn("Unexpected exception occurred while deregistering a channel.", t);
|
logger.warn("Unexpected exception occurred while deregistering a channel.", t);
|
||||||
} finally {
|
} finally {
|
||||||
@ -756,6 +757,10 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
// close() calls deregister() again - no need to fire channelUnregistered.
|
// close() calls deregister() again - no need to fire channelUnregistered.
|
||||||
promise.setSuccess();
|
promise.setSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (postTask != null) {
|
||||||
|
postTask.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eventLoop().execute(new Runnable() {
|
eventLoop().execute(new Runnable() {
|
||||||
@ -973,11 +978,12 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deregister the {@link Channel} from its {@link EventLoop}.
|
* 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
|
* Sub-classes may override this method
|
||||||
*/
|
*/
|
||||||
protected void doDeregister() throws Exception {
|
protected Runnable doDeregister() throws Exception {
|
||||||
// NOOP
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,8 +225,13 @@ public abstract class AbstractEmbeddedChannel<O> extends AbstractChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doDeregister() throws Exception {
|
protected Runnable doDeregister() throws Exception {
|
||||||
// NOOP
|
return new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
runPendingTasks();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,8 +26,8 @@ import io.netty.channel.ChannelPipeline;
|
|||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.channel.DefaultChannelConfig;
|
import io.netty.channel.DefaultChannelConfig;
|
||||||
import io.netty.channel.EventLoop;
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
|
||||||
import io.netty.channel.SingleThreadEventLoop;
|
import io.netty.channel.SingleThreadEventLoop;
|
||||||
|
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.channels.AlreadyConnectedException;
|
import java.nio.channels.AlreadyConnectedException;
|
||||||
@ -201,11 +201,12 @@ public class LocalChannel extends AbstractChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doDeregister() throws Exception {
|
protected Runnable doDeregister() throws Exception {
|
||||||
if (isOpen()) {
|
if (isOpen()) {
|
||||||
unsafe().close(unsafe().voidFuture());
|
unsafe().close(unsafe().voidFuture());
|
||||||
}
|
}
|
||||||
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,8 +22,8 @@ import io.netty.channel.ChannelPipeline;
|
|||||||
import io.netty.channel.DefaultChannelConfig;
|
import io.netty.channel.DefaultChannelConfig;
|
||||||
import io.netty.channel.EventLoop;
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.channel.ServerChannel;
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
|
||||||
import io.netty.channel.SingleThreadEventLoop;
|
import io.netty.channel.SingleThreadEventLoop;
|
||||||
|
import io.netty.util.concurrent.SingleThreadEventExecutor;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
@ -126,8 +126,9 @@ public class LocalServerChannel extends AbstractServerChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doDeregister() throws Exception {
|
protected Runnable doDeregister() throws Exception {
|
||||||
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -273,8 +273,9 @@ public abstract class AbstractNioChannel extends AbstractChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doDeregister() throws Exception {
|
protected Runnable doDeregister() throws Exception {
|
||||||
eventLoop().cancel(selectionKey());
|
eventLoop().cancel(selectionKey());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user