Uploaded image for project: 'MINA'
  1. MINA
  2. DIRMINA-1086

IoSessions closed by filterChain.fireExceptionCaught(e) are kept in memory

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Not A Problem
    • Affects Version/s: 2.0.17
    • Fix Version/s: None
    • Component/s: Core
    • Labels:
      None
    • Environment:
      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.

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              wenxiang.qiu Wenxiang Qiu
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: