[ https://issues.apache.org/jira/browse/DIRMINA-1076?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16375915#comment-16375915 ]
Jonathan Valliere commented on DIRMINA-1076: -------------------------------------------- In the previous post, I mentioned the possibility of totally removing the {{nSession}} state. *Option 3* Completely removes the {{nSession}} state because it is corruptible. Relies entirely on {{selector.keys().size()}} for the state. This is actually the most simple of all the alternatives as it requires no new atomic mechanisms. Only drawback is that it might take longer to {{dispose()}} the {{IoProcessor}} due the extra {{select()}} cycle that must occur to update the session count. {code:java} diff --git a/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor.java b/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor.java index 79885fa..c807bf1 100644 --- a/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor.java +++ b/mina-core/src/main/java/org/apache/mina/core/polling/AbstractPollingIoProcessor.java @@ -240,6 +240,13 @@ * @return {@link Iterator} of {@link IoSession} */ protected abstract Iterator<S> allSessions(); + + /** + * Get the number of {@Link IoSession} polled by this {@Link IoProcessor} + * + * @return the number of sessions attached to this {@Link IoProcessor} + */ + protected abstract int allSessionsCount(); /** * Get an {@link Iterator} for the list of {@link IoSession} found selected @@ -596,7 +603,6 @@ public void run() { assert processorRef.get() == this; - int nSessions = 0; lastIdleCheckTime = System.currentTimeMillis(); int nbTries = 10; @@ -641,9 +647,31 @@ } else { nbTries = 10; } - + // Manage newly created session first - nSessions += handleNewSessions(); + if(handleNewSessions() == 0) { + // Get a chance to exit the infinite loop if there are no + // more sessions on this Processor + if (allSessionsCount() == 0) { + processorRef.set(null); + + if (newSessions.isEmpty() && isSelectorEmpty()) { + // newSessions.add() precedes startupProcessor + assert processorRef.get() != this; + break; + } + + assert processorRef.get() != this; + + if (!processorRef.compareAndSet(null, this)) { + // startupProcessor won race, so must exit processor + assert processorRef.get() != this; + break; + } + + assert processorRef.get() == this; + } + } updateTrafficMask(); @@ -654,39 +682,17 @@ // the MDCFilter test... process(); } - + // Write the pending requests long currentTime = System.currentTimeMillis(); flush(currentTime); - - // And manage removed sessions - nSessions -= removeSessions(); - + // Last, not least, send Idle events to the idle sessions notifyIdleSessions(currentTime); - - // Get a chance to exit the infinite loop if there are no - // more sessions on this Processor - if (nSessions == 0) { - processorRef.set(null); - - if (newSessions.isEmpty() && isSelectorEmpty()) { - // newSessions.add() precedes startupProcessor - assert processorRef.get() != this; - break; - } - - assert processorRef.get() != this; - - if (!processorRef.compareAndSet(null, this)) { - // startupProcessor won race, so must exit processor - assert processorRef.get() != this; - break; - } - - assert processorRef.get() == this; - } - + + // And manage removed sessions + removeSessions(); + // Disconnect all sessions immediately if disposal has been // requested so that we exit this loop eventually. if (isDisposing()) { @@ -702,9 +708,7 @@ } } - if (hasKeys) { - wakeup(); - } + wakeup(); } } catch (ClosedSelectorException cse) { // If the selector has been closed, we can exit the loop diff --git a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java index 3b0fa40..9948d7a 100644 --- a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java +++ b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java @@ -159,6 +159,12 @@ selectorLock.readLock().unlock(); } } + + @Override + protected int allSessionsCount() + { + return selector.keys().size(); + } @SuppressWarnings("synthetic-access") @Override diff --git a/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessorTest.java b/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessorTest.java index 379f55b..f289aaf 100644 --- a/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessorTest.java +++ b/mina-core/src/test/java/org/apache/mina/transport/socket/nio/PollingIoProcessorTest.java @@ -61,6 +61,11 @@ protected Iterator<NioSession> allSessions() { return proc.allSessions(); } + + @Override + protected int allSessionsCount() { + return proc.allSessionsCount(); + } @Override protected void destroy(NioSession session) throws Exception { {code} > Leaking NioProcessors/NioSocketConnectors hanging in call to dispose > -------------------------------------------------------------------- > > Key: DIRMINA-1076 > URL: https://issues.apache.org/jira/browse/DIRMINA-1076 > Project: MINA > Issue Type: Bug > Affects Versions: 2.0.16 > Reporter: Christoph John > Assignee: Jonathan Valliere > Priority: Major > Attachments: mina-dispose-hang.txt, mina-test-log.txt, > mina-test-patch.txt > > > Follow-up to mailing list discussion. > I was now able to reproduce the problem with a MINA test. Or let's say I did > the brute-force approach by re-running one test in an endless loop. > I have attached a patch of AbstractIoServiceTest (against > [https://github.com/apache/mina/tree/2.0]) and a stack trace. After a few > loops the test is stuck. You can see a lot of threads hanging in dispose() > and the test is stuck when it tries to dispose the acceptor. > > What is a little strange is that the javadoc says that > connector.dispose(TRUE) should not be called from an IoFutureListener, but in > the test it is done anyway. However, changing the parameter to FALSE does not > help either. > > Is there anything that can be done to prevent this hang? -- This message was sent by Atlassian JIRA (v7.6.3#76005)