[
https://issues.apache.org/jira/browse/DIRMINA-1021?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15028449#comment-15028449
]
Emmanuel Lecharny commented on DIRMINA-1021:
--------------------------------------------
Let's see what's happening when a session is closed because of an exception.
For instance, the {{AbstractPollingIoProcessor.writeBuffer()}} method call
{{close()}} when an exception occurs :
{code:title=writeBuffer()|borderStyle=solid}
private int writeBuffer(S session, WriteRequest req, boolean
hasFragmentation, int maxLength, long currentTime)
throws Exception {
...
if (buf.hasRemaining()) {
...
try {
localWrittenBytes = write(session, buf, length);
} catch (IOException ioe) {
// We have had an issue while trying to send data to the
// peer : let's close the session.
buf.free();
session.close(true);
destroy(session);
return 0;
}
...
{code}
(let's ignore the {{destroy(session)}} atm).
The {{session.close( true )}} execute this code :
{code:title=close()|borderStyle=solid}
public final CloseFuture close(boolean rightNow) {
if (!isClosing()) {
if (rightNow) {
synchronized (lock) {
if (isClosing()) {
return closeFuture;
}
closing = true;
}
getFilterChain().fireFilterClose();
return closeFuture;
}
return closeOnFlush();
} else {
return closeFuture;
}
}
{code}
The important part is {{getFilterChain().fireFilterClose()}}, which
implementation is :
{code:title=fireFilterClose()|borderStyle=solid}
public void fireFilterClose() {
callPreviousFilterClose(tail, session);
}
{code}
which calls :
{code:title=callPreviousFilterClose()|borderStyle=solid}
private void callPreviousFilterClose(Entry entry, IoSession session) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.filterClose(nextFilter, session);
} catch (Exception e) {
fireExceptionCaught(e);
} catch (Error e) {
fireExceptionCaught(e);
throw e;
}
}
{code}
which in turns call ultimately :
{code:title=HeadFilter.filterClose()|borderStyle=solid}
public void filterClose(NextFilter nextFilter, IoSession session)
throws Exception {
((AbstractIoSession) session).getProcessor().remove(session);
}
{code}
then :
{code:title=AbstractPollingIoProcessorremove()|borderStyle=solid}
public final void remove(S session) {
scheduleRemove(session);
startupProcessor();
}
private void scheduleRemove(S session) {
removingSessions.add(session);
}
{code}
At this point, closing a session is *not* enough. Either you wait on the
returned {{CloseFuture}} instance, or you actually destroy the session (which
is probably what is missing in your case).
> MINA-CORE does not remove sessions if exceptions occur while closing
> --------------------------------------------------------------------
>
> Key: DIRMINA-1021
> URL: https://issues.apache.org/jira/browse/DIRMINA-1021
> Project: MINA
> Issue Type: Bug
> Affects Versions: 2.0.8
> Environment: mina-ssh 0.14.0
> mina-core 2.0.8
> Multiple OSes / Java configurations:
> * Mac OS X El Capitan on Java 8 (1.8.0_60)
> * CentOS 6.4 on Java 8 (1.8.0_60)
> * CentOS 6.5 on Java 8 (1.8.0_20-b26).
> Reporter: Doug Kelly
> Attachments: attempt-removing-sessions-closing.patch
>
>
> MINA SSHD isn't removing sessions when using the MINA/NIO backend if an
> exception as received as the session is closing (such as a connection reset
> is received with data still in the write buffer). When this case happens, it
> seems that {{NioProcessor.getState}} returns the state as {{CLOSING}} (I'm
> assuming since the underlying channel is now closed), which means that the
> {{AbstractPollingIoProcessor.removeSessions()}} won't ever prune the session,
> since a {{CLOSING}} state is simply ignored. The result is a resource leak
> over time, since these sessions are never pruned (it's a slow leak, since
> entering this condition is racy – on my workstation, I can produce it through
> randomly interrupting connections anywhere from 1/6 to 1/10th of the time).
> (This may either be major or critical; reprioritize as necessary.)
> I specifically see this error with Gerrit 2.10.4 and Gerrit 2.11.5 (using
> mina-sshd 0.14.0 / mina-core 2.0.8), and it looks like the code path is
> unchanged in mina-sshd 1.0.0 / mina-core 2.0.9. I was unsure if this is
> specifically a bug in mina-core or, if it's something unique to mina-sshd. My
> local development system runs Mac OS X El Capitan on Java 8 (1.8.0_60), but
> I've also seen this on Linux (CentOS 6.4, again Java 1.8.0_60 and CentOS 6.5
> on Java 1.8.0_20-b26).
> The fix may be as simple as attempting to remove the session if {{OPENED}} or
> {{CLOSING}}, but I'm unsure what side-effects this may have with other
> backends. I'll be happy to test it locally, but I'm fairly ignorant when it
> comes to MINA's code.
> The attached patch (to mina-core) seems to resolve the issue by following the
> reproduction case I have on the [Gerrit issue
> tracker|https://code.google.com/p/gerrit/issues/detail?id=3685].
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)