Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Not A Problem
-
2.0.17
-
None
-
None
-
mina in ApacheDS
Description
I'm using ApacheDS, I found this problem and am not sure if it's a mina issue or an ApacheDS issue.
AbstractPollingIoProcessor#read looks like this:
private void read(S session) { IoSessionConfig config = session.getConfig(); int bufferSize = config.getReadBufferSize(); IoBuffer buf = IoBuffer.allocate(bufferSize); final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation(); try { /* omitted */ if (ret < 0) { IoFilterChain filterChain = session.getFilterChain(); filterChain.fireInputClosed(); } } catch (Exception e) { if ((e instanceof IOException) && (!(e instanceof PortUnreachableException) || !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass()) || ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable())) { scheduleRemove(session); } IoFilterChain filterChain = session.getFilterChain(); filterChain.fireExceptionCaught(e); } }
When an exception occurs with an LDAP connection, e.g. Connection reset by peer, catch block is entered and ExcpetionCaught gets fired:
filterChain.fireExceptionCaught(e);
The session is thus closed by LdapProtocolHandler#exceptionCaught:
public void exceptionCaught( IoSession session, Throwable cause ) { if ( cause.getCause() instanceof ResponseCarryingMessageException ) { ResponseCarryingMessageException rcme = ( ResponseCarryingMessageException ) cause.getCause(); if ( rcme.getResponse() != null ) { session.write( rcme.getResponse() ); return; } } LOG.warn( "Unexpected exception forcing session to close: sending disconnect notice to client.", cause ); session.write( NoticeOfDisconnect.PROTOCOLERROR ); LdapSession ldapSession = this.ldapServer.getLdapSessionManager().removeLdapSession( session ); cleanUpSession( ldapSession ); session.close( true ); }
Although this session is scheduled for removal, due to its state being closing, AbstractPollingIoProcessor#removeSessions does nothing about this session:
case CLOSING: // Skip if channel is already closed // In any case, remove the session from the queue removedSessions++; break;
Consequence is that this session is kept forever in IoServiceListenerSupport.managedSessions, and as its size grows, this ConcurrentMap can take up quite a large amount of memory.