From 7f35daddd2cabef2e7ffb6899e1a54ff8c0475c6 Mon Sep 17 00:00:00 2001 From: Zhaozhong Ni Date: Wed, 5 Dec 2018 15:01:41 -0800 Subject: sentry: support save / restore of TCP bind socket after shutdown. PiperOrigin-RevId: 224227677 Change-Id: I08b0e0c0574170556269900653e5bcf9e9e5c9c9 --- pkg/tcpip/transport/tcp/endpoint_state.go | 39 +++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'pkg/tcpip') diff --git a/pkg/tcpip/transport/tcp/endpoint_state.go b/pkg/tcpip/transport/tcp/endpoint_state.go index e32c73aae..4891c7941 100644 --- a/pkg/tcpip/transport/tcp/endpoint_state.go +++ b/pkg/tcpip/transport/tcp/endpoint_state.go @@ -92,8 +92,8 @@ func (e *endpoint) beforeSave() { panic("endpoint still has waiters upon save") } - if !((e.state == stateBound || e.state == stateListen) == e.isPortReserved) { - panic("endpoint port must and must only be reserved in bound or listen state") + if e.state != stateClosed && !((e.state == stateBound || e.state == stateListen) == e.isPortReserved) { + panic("endpoints which are not in the closed state must have a reserved port IFF they are in bound or listen state") } } @@ -102,15 +102,21 @@ func (e *endpoint) saveAcceptedChan() []*endpoint { if e.acceptedChan == nil { return nil } - close(e.acceptedChan) acceptedEndpoints := make([]*endpoint, len(e.acceptedChan), cap(e.acceptedChan)) - i := 0 - for ep := range e.acceptedChan { - acceptedEndpoints[i] = ep - i++ + for i := 0; i < len(acceptedEndpoints); i++ { + select { + case ep := <-e.acceptedChan: + acceptedEndpoints[i] = ep + default: + panic("endpoint acceptedChan buffer got consumed by background context") + } } - if i != len(acceptedEndpoints) { - panic("endpoint acceptedChan buffer got consumed by background context") + for i := 0; i < len(acceptedEndpoints); i++ { + select { + case e.acceptedChan <- acceptedEndpoints[i]: + default: + panic("endpoint acceptedChan buffer got populated by background context") + } } return acceptedEndpoints } @@ -235,7 +241,20 @@ func (e *endpoint) afterLoad() { bind() tcpip.AsyncLoading.Done() }() - case stateClosed, stateError: + case stateClosed: + if e.isPortReserved { + tcpip.AsyncLoading.Add(1) + go func() { + connectedLoading.Wait() + listenLoading.Wait() + connectingLoading.Wait() + bind() + e.state = stateClosed + tcpip.AsyncLoading.Done() + }() + } + fallthrough + case stateError: tcpip.DeleteDanglingEndpoint(e) } } -- cgit v1.2.3