SocketChannelFactory.releaseExternalResources causes an infinite loop if called from a Netty IO thread

Christian Migowski chrismfwrd at gmail.com
Tue Nov 23 07:55:11 EST 2010


Hi,


On Tue, Sep 28, 2010 at 8:16 PM, "이희승 (Trustin Lee)" <trustin at gmail.com> wrote:
> Sorry that I'm late.
>
> Yes, you are not supposed to call releaseExternalResource() from an I/O
> thread.  Let me update the documentation if it was not mentioned
> clearly.  Also, I'd like to modify releaseExternalResource() to throw an
> exception when it's called from an I/O thread to prevent the nasty busy
> loop.  WDYT?

will this be available in a Netty 3.2.x maintenance release is this
only planned for Netty 4? I was bitten by this too, would be nice if
it is more visible that you cannot call releaseExternalResources from
an I/O thread.

Btw. I was able to work around this issue by changing my "stop"
method, which is invoked from a messageReceived method when receiving
a "stop" command from

                    private void stop() {
                        channelGroup.close().addListener(new
ChannelGroupFutureListener() {
                            @Override
                            public void
operationComplete(ChannelGroupFuture future) throws Exception {
                                System.out.println("channelgroup close
complete");
                                bootstrap.releaseExternalResources();
                                System.out.println("bootstrap release
complete");
                            }
                        });
                    }


to

                    private void stop() {
                        channelGroup.close().addListener(new
ChannelGroupFutureListener() {
                            @Override
                            public void
operationComplete(ChannelGroupFuture future) throws Exception {
                                System.out.println("channelgroup close
complete");
                                //the listener is called from an I/O
worker which is causing a deathlock
                                new Thread() {
                                    public void run() {
                                        bootstrap.releaseExternalResources();
                                    }
                                }.start();

                                System.out.println("bootstrap release
complete");
                            }
                        });
                    }



Wouldn't that be an option for implementation directly in Netty too? I
mean, if not all channels are closed the newly created Thread for
releasing would also hang, but that would be also the case without the
thread, and with it this "do not call releaseExternalResources from an
IO Worker" would be solved, no?


regards,
christian!



> Thanks,
> Trustin
>
> tsuna wrote:
>> On Thu, Sep 2, 2010 at 10:11 AM, tsuna <tsunanet at gmail.com> wrote:
>>> Hi,
>>> I realized that when my app attempts to shut itself down from within a
>>> Netty IO thread, the code gets stuck in an infinite loop:
>>>
>>> Here are two (partial) stack traces from the same thread that's stuck
>>> and using 100% CPU (netty-3.2.1.Final):
>>>
>>> "New I/O client worker #1-4" prio=10 tid=0x00007f35e0032800 nid=0x2d5c
>>> runnable [0x0000000041866000]
>>>   java.lang.Thread.State: RUNNABLE
>>>        at java.lang.Throwable.fillInStackTrace(Native Method)
>>>        - locked <0x00007f373f735368> (a java.lang.InterruptedException)
>>>        at java.lang.Throwable.<init>(Throwable.java:181)
>>>        at java.lang.Exception.<init>(Exception.java:29)
>>>        at java.lang.InterruptedException.<init>(InterruptedException.java:38)
>>>        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1953)
>>>        at java.util.concurrent.ThreadPoolExecutor.awaitTermination(ThreadPoolExecutor.java:1253)
>>>        at org.jboss.netty.util.internal.ExecutorUtil.terminate(ExecutorUtil.java:87)
>>>        at org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.releaseExternalResources(NioClientSocketChannelFactory.java:143)
>>>
>>> "New I/O client worker #1-4" prio=10 tid=0x00007f35e0032800 nid=0x2d5c
>>> runnable [0x0000000041866000]
>>>   java.lang.Thread.State: RUNNABLE
>>>        at java.lang.Thread.interrupt0(Native Method)
>>>        at java.lang.Thread.interrupt(Thread.java:852)
>>>        at java.util.concurrent.ThreadPoolExecutor$Worker.interruptNow(ThreadPoolExecutor.java:855)
>>>        at java.util.concurrent.ThreadPoolExecutor.shutdownNow(ThreadPoolExecutor.java:1167)
>>>        at org.jboss.netty.util.internal.ExecutorUtil.terminate(ExecutorUtil.java:70)
>>>        at org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.releaseExternalResources(NioClientSocketChannelFactory.java:143)
>>>
>>> If I look in the code in ExecutorUtil.java, I see there's a for (;;) {
>>> } loop that attempts to shutdown the executor.  From the stack trace
>>> above, it seems that the code attempts calls awaitTermination(), which
>>> throws an InterruptedException, which is handled inside the for (;;) {
>>> } loop, and then retried, which throws again, etc.  Is this the
>>> intended behavior?  Or is it because I'm not supposed to call
>>> releaseExternalResources from within a Netty IO thread?
>>
>> Any idea anyone?
>>
>
>
> _______________________________________________
> netty-users mailing list
> netty-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/netty-users
>



More information about the netty-users mailing list