HashedWheelTimer is leaking threads, am I doing something wrong?
Virat Gohil
virat.gohil at gmail.com
Tue Nov 3 11:28:51 EST 2009
On Tue, Nov 3, 2009 at 9:51 PM, Garry Watkins <garry at dynafocus.com> wrote:
>
> Here is the pipeline factory code:
>
> public class PassThroughMasterPipelineFactory implements
> ChannelPipelineFactory {
> private short unitId;
> private Properties properties;
> private ClientBootstrap bootStrap;
>
> public PassThroughMasterPipelineFactory(short unitId, Properties
> properties, ClientBootstrap bootStrap) {
> this.unitId = unitId;
> this.properties = properties;
> this.bootStrap = bootStrap;
> }
>
> public ChannelPipeline getPipeline() throws Exception {
> ChannelPipeline pipeline = pipeline();
>
> // pipeline.addLast("logger", new
> LoggingHandler(InternalLogLevel.INFO, false));
>
> Timer timer = new HashedWheelTimer();
> pipeline.addLast("reconnect", new PLCDisconnectHandler(bootStrap,
> timer));
> pipeline.addLast("timeout", new IdleStateHandler(timer, 5, 10, 0));
>
> UnitronicsLengthFieldBasedDecoder tcpFramer = new
> UnitronicsLengthFieldBasedDecoder();
> pipeline.addLast("tcpFramer", tcpFramer);
>
> pipeline.addLast("tcpCodec", new TCPFrameCodec());
>
> PLCStateMachine stateMachine = new PassThroughStateMachine(unitId);
> stateMachine.initializeScheduler(properties);
> pipeline.addLast("handler", new
> PLCStateMachineHandler(stateMachine));
>
> pipeline.addLast("test", new RequestStatisticHandler());
>
> return pipeline;
> }
>
> }
>
>
> Garry Watkins wrote:
>>
>> I have a reconnect handler that handles closed channels and it will try to
>> connect up after 10 seconds. Every time that it opens the connection back
>> up it creates a new thread. I am not sure if it is the wheel timer is
>> causing the leak or if there is something else. I am willing to try and
>> debug this if I can get a pointer in the right direction.
>>
>> Here is what my code looks like:
>>
>> @ChannelPipelineCoverage("one")
>> public class PLCDisconnectHandler extends SimpleChannelUpstreamHandler
>> {
>> private static final Log LOG =
>> LogFactory.getLog(PLCDisconnectHandler.class);
>>
>> final ClientBootstrap bootstrap;
>> private final Timer timer;
>>
>> public PLCDisconnectHandler(ClientBootstrap bootstrap, Timer timer) {
>> this.bootstrap = bootstrap;
>> this.timer = timer;
>> }
>>
>> @Override
>> public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent
>> e) throws Exception
>> {
>> LOG.error("channelOpen");
>>
>> super.channelOpen(ctx, e);
>> }
>>
>> @Override
>> public void channelConnected(ChannelHandlerContext ctx,
>> ChannelStateEvent e) throws Exception {
>> LOG.error("channelConnected: " +
>> ctx.getChannel().getRemoteAddress().toString());
>>
>> super.channelConnected(ctx, e);
>> }
>>
>> @Override
>> public void channelDisconnected(ChannelHandlerContext ctx,
>> ChannelStateEvent e) throws Exception
>> {
>> LOG.error("Channel disconnected: " +
>> ctx.getChannel().getRemoteAddress().toString());
>>
>> super.channelDisconnected(ctx, e);
>> }
>>
>> @Override
>> public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent
>> e) {
>> LOG.error("channelClosed");
>>
>> timer.newTimeout(new TimerTask() {
>> public void run(Timeout timeout) throws Exception {
>> timeout.cancel();
>> bootstrap.connect();
>> }
>> }, 10, TimeUnit.SECONDS);
>> }
>>
>> @Override
>> public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent
>> e) throws Exception {
>> if (e.getCause() instanceof ConnectException){
>> ctx.getChannel().close();
>> }
>> }
>> }
>>
>> TIA
>> Garry
>>
>
> --
> View this message in context: http://n2.nabble.com/HashedWheelTimer-is-leaking-threads-am-I-doing-something-wrong-tp3939379p3939502.html
> Sent from the Netty User Group mailing list archive at Nabble.com.
> _______________________________________________
> netty-users mailing list
> netty-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/netty-users
>
Hmm,
1. This is the reasons for leaks
> public ChannelPipeline getPipeline() throws Exception {
> Timer timer = new HashedWheelTimer();
> pipeline.addLast("reconnect", new PLCDisconnectHandler(bootStrap,
> timer));
> pipeline.addLast("timeout", new IdleStateHandler(timer, 5, 10, 0));
You dont actually need a new instance for every pipeline, I suggest
that you create a single instance of timer and share it across all
channels as follows:
public class PassThroughMasterPipelineFactory implements
ChannelPipelineFactory {
private short unitId;
private Properties properties;
private ClientBootstrap bootStrap;
private Timer timer;
public PassThroughMasterPipelineFactory(short unitId, Properties
properties, ClientBootstrap bootStrap) {
this.unitId = unitId;
this.properties = properties;
this.bootStrap = bootStrap;
this.timer =new HashedWheelTimer();
}
public ChannelPipeline getPipeline() throws Exception {
pipeline.addLast("reconnect", new
PLCDisconnectHandler(bootStrap, timer));
pipeline.addLast("timeout", new IdleStateHandler(timer, 5, 10, 0));
}
And second:
>> timer.newTimeout(new TimerTask() {
>> public void run(Timeout timeout) throws Exception {
>> timeout.cancel();
>> bootstrap.connect();
>> }
>> }, 10, TimeUnit.SECONDS);
It basically creates a new thread every time a connection is closed.
Thanks,
Virat
More information about the netty-users
mailing list