Close the server and all active connections. Server can be re-used after Close is done.
()
| 1186 | // Close the server and all active connections. Server can be re-used |
| 1187 | // after Close is done. |
| 1188 | func (s *Server) Close() error { |
| 1189 | s.mu.Lock() |
| 1190 | |
| 1191 | // Guard against multiple calls to Close and |
| 1192 | // accepting new connections during close. |
| 1193 | if s.closing != nil { |
| 1194 | closing := s.closing |
| 1195 | s.mu.Unlock() |
| 1196 | <-closing |
| 1197 | return xerrors.New("server is closed") |
| 1198 | } |
| 1199 | s.closing = make(chan struct{}) |
| 1200 | |
| 1201 | ctx := context.Background() |
| 1202 | |
| 1203 | s.logger.Debug(ctx, "closing server") |
| 1204 | |
| 1205 | // Stop accepting new connections. |
| 1206 | s.logger.Debug(ctx, "closing all active listeners", slog.F("count", len(s.listeners))) |
| 1207 | for l := range s.listeners { |
| 1208 | _ = l.Close() |
| 1209 | } |
| 1210 | |
| 1211 | // Close all active sessions to gracefully |
| 1212 | // terminate client connections. |
| 1213 | s.logger.Debug(ctx, "closing all active sessions", slog.F("count", len(s.sessions))) |
| 1214 | for ss := range s.sessions { |
| 1215 | // We call Close on the underlying channel here because we don't |
| 1216 | // want to send an exit status to the client (via Exit()). |
| 1217 | // Typically OpenSSH clients will return 255 as the exit status. |
| 1218 | _ = ss.Close() |
| 1219 | } |
| 1220 | s.logger.Debug(ctx, "closing all active connections", slog.F("count", len(s.conns))) |
| 1221 | for c := range s.conns { |
| 1222 | _ = c.Close() |
| 1223 | } |
| 1224 | |
| 1225 | for p := range s.processes { |
| 1226 | _ = cmdCancel(s.logger, p) |
| 1227 | } |
| 1228 | |
| 1229 | s.logger.Debug(ctx, "closing SSH server") |
| 1230 | err := s.srv.Close() |
| 1231 | |
| 1232 | s.mu.Unlock() |
| 1233 | |
| 1234 | s.logger.Debug(ctx, "closing X11 forwarding") |
| 1235 | _ = s.x11Forwarder.Close() |
| 1236 | |
| 1237 | s.logger.Debug(ctx, "waiting for all goroutines to exit") |
| 1238 | s.wg.Wait() // Wait for all goroutines to exit. |
| 1239 | |
| 1240 | s.mu.Lock() |
| 1241 | close(s.closing) |
| 1242 | s.closing = nil |
| 1243 | s.mu.Unlock() |
| 1244 | |
| 1245 | s.logger.Debug(ctx, "closing server done") |