code: func (a *Agent) Close() error {
  	a.closeMutex.Lock()
  	defer a.closeMutex.Unlock()
  	if a.GetStatus() == constants.StatusClosed {
  		return constants.ErrCloseClosedSession
  	}
  	a.SetStatus(constants.StatusClosed)
  
  	logger.Log.Debugf("Session closed, ID=%d, UID=%d, IP=%s",
  		a.Session.ID(), a.Session.UID(), a.conn.RemoteAddr())
  
  	// prevent closing closed channel
  	select {
  	case <-a.chDie:
  		// expect
  	default:
  		close(a.chStopWrite)
  		close(a.chStopHeartbeat)
  		close(a.chDie)
  		onSessionClosed(a.Session)
  	}
  
  	metrics.ReportNumberOfConnectedClients(a.metricsReporters, session.SessionCount)
  
  	return a.conn.Close()
  }
docs: // Close closes the agent, cleans inner state and closes low-level connection.
  // Any blocked Read or Write operations will be unblocked and return errors.