DrainTCP waits until every TCP connection in the server's netstack has fully closed, meaning the peer has acknowledged all sent data and the final FIN. It returns nil once drained, or ctx's error. The whole TCP stack runs inside this process, so exiting right after a [net.Conn] Close can lose the F
(ctx context.Context)
| 558 | // this side closed first instead parks in TIME-WAIT and would block |
| 559 | // DrainTCP until the TIME-WAIT timer fires. |
| 560 | func (s *Server) DrainTCP(ctx context.Context) error { |
| 561 | // Wait blocks until the endpoint is fully closed (EventHUp). |
| 562 | // Non-TCP endpoints return immediately. A waiter goroutine may |
| 563 | // outlive an early ctx cancellation; it exits with the process |
| 564 | // or when its endpoint eventually closes. |
| 565 | for _, ep := range tcpipStackOf(s.lb.ns).RegisteredEndpoints() { |
| 566 | done := make(chan struct{}) |
| 567 | go func() { |
| 568 | ep.Wait() |
| 569 | close(done) |
| 570 | }() |
| 571 | select { |
| 572 | case <-done: |
| 573 | case <-ctx.Done(): |
| 574 | return ctx.Err() |
| 575 | } |
| 576 | } |
| 577 | return nil |
| 578 | } |
| 579 | |
| 580 | // tcpipStackOf returns ns's unexported gVisor *stack.Stack. |
| 581 | // |
no test coverage detected