diff --git a/dhcp/server.go b/dhcp/server.go index 42dc982..1697788 100644 --- a/dhcp/server.go +++ b/dhcp/server.go @@ -49,7 +49,7 @@ type Server struct { offers *pendingOffers lifecycleMu sync.Mutex // serializes multi-structure lease, route, and pool transitions - linkIndex int // cached kernel interface index for route operations + linkIndex int } // New creates a DHCP server. IPs are the allocatable pool (excluding gateway). @@ -107,34 +107,30 @@ func (s *Server) Run(ctx context.Context) error { controlErrCh = control.serve(runCtx) } + var controlErr error select { case <-ctx.Done(): - _ = conn.Close() - cancelRun() - if control != nil { - if err := <-controlErrCh; err != nil { - return fmt.Errorf("stop control server: %w", err) - } - } - // held until exit: a handler still queued must not start a transaction the process cannot finish - s.lifecycleMu.Lock() - logger.Info(ctx, "DHCP server stopped") - return nil case err := <-errCh: cancelRun() return fmt.Errorf("DHCP server: %w", err) - case err := <-controlErrCh: - _ = conn.Close() - cancelRun() - if err == nil { - if ctx.Err() != nil { - logger.Info(ctx, "DHCP server stopped") - return nil - } - return errors.New("control server stopped unexpectedly") + case controlErr = <-controlErrCh: + controlErrCh = nil + if controlErr == nil && ctx.Err() == nil { + controlErr = errors.New("stopped unexpectedly") } - return fmt.Errorf("control server: %w", err) } + _ = conn.Close() + cancelRun() + if controlErrCh != nil { + controlErr = <-controlErrCh + } + if controlErr != nil { + return fmt.Errorf("control server: %w", controlErr) + } + // held until exit: a handler still queued must not start a transaction the process cannot finish + s.lifecycleMu.Lock() + logger.Info(ctx, "DHCP server stopped") + return nil } // PoolAvailable returns the number of unallocated pool IPs, read per metrics scrape. diff --git a/platform/volcengine/eni.go b/platform/volcengine/eni.go index c26f9ab..1c0c56e 100644 --- a/platform/volcengine/eni.go +++ b/platform/volcengine/eni.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "slices" "strconv" "time" @@ -100,12 +101,7 @@ func deleteOrphanENI(ctx context.Context, eniID string) { } func selectReusableENIs(enis []networkInterface, count int) []networkInterface { - var reusable []networkInterface - for _, e := range enis { - if e.Type != eniTypePrimary { - reusable = append(reusable, e) - } - } + reusable := slices.DeleteFunc(slices.Clone(enis), func(e networkInterface) bool { return e.Type == eniTypePrimary }) return reusable[:min(len(reusable), count)] }