Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/infrastructure/host/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"os"
"path/filepath"
"sync"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/envoygateway/config"
Expand Down Expand Up @@ -45,7 +46,7 @@ type Infra struct {
EnvoyGateway *egv1a1.EnvoyGateway

// proxyContextMap store the context of each running proxy by its name for lifecycle management.
proxyContextMap map[string]*proxyContext
proxyContextMap sync.Map

// TODO: remove this field once it supports the configurable homeDir
sdsConfigPath string
Expand Down Expand Up @@ -79,7 +80,6 @@ func NewInfra(runnerCtx context.Context, cfg *config.Server, logger logging.Logg
HomeDir: defaultHomeDir,
Logger: logger,
EnvoyGateway: cfg.EnvoyGateway,
proxyContextMap: make(map[string]*proxyContext),
sdsConfigPath: defaultLocalCertPathDir,
defaultEnvoyImage: egv1a1.DefaultEnvoyProxyImage,
Stdout: cfg.Stdout,
Expand Down
26 changes: 19 additions & 7 deletions internal/infrastructure/host/proxy_infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"path/filepath"
"regexp"
"strings"
"sync"

func_e "github.com/tetratelabs/func-e"
"github.com/tetratelabs/func-e/api"
Expand All @@ -34,9 +35,19 @@ type proxyContext struct {

// Close implements the Manager interface.
func (i *Infra) Close() error {
for name := range i.proxyContextMap {
i.stopEnvoy(name)
}
var wg sync.WaitGroup

// Stop any Envoy subprocesses in parallel
i.proxyContextMap.Range(func(key, value any) bool {
wg.Add(1)
go func(name string) {
defer wg.Done()
i.stopEnvoy(name)
}(key.(string))
return true
})

wg.Wait()
return nil
}

Expand All @@ -53,7 +64,7 @@ func (i *Infra) CreateOrUpdateProxyInfra(ctx context.Context, infra *ir.Infra) e
proxyInfra := infra.GetProxyInfra()
proxyName := utils.GetHashedName(proxyInfra.Name, 64)
// Return directly if the proxy is running.
if _, ok := i.proxyContextMap[proxyName]; ok {
if _, loaded := i.proxyContextMap.Load(proxyName); loaded {
return nil
}

Expand Down Expand Up @@ -91,7 +102,7 @@ func (i *Infra) CreateOrUpdateProxyInfra(ctx context.Context, infra *ir.Infra) e
func (i *Infra) runEnvoy(ctx context.Context, envoyVersion, name string, args []string) {
pCtx, cancel := context.WithCancel(ctx)
exit := make(chan struct{}, 1)
i.proxyContextMap[name] = &proxyContext{cancel: cancel, exit: exit}
i.proxyContextMap.Store(name, &proxyContext{cancel: cancel, exit: exit})
go func() {
// Run blocks until pCtx is done or the process exits where the latter doesn't happen when
// Envoy successfully starts up. So, this will not return until pCtx is done in practice.
Expand Down Expand Up @@ -124,11 +135,12 @@ func (i *Infra) DeleteProxyInfra(_ context.Context, infra *ir.Infra) error {

// stopEnvoy stops the Envoy process by its name. It will block until the process completely stopped.
func (i *Infra) stopEnvoy(proxyName string) {
if pCtx, ok := i.proxyContextMap[proxyName]; ok {
value, ok := i.proxyContextMap.LoadAndDelete(proxyName)
if ok {
pCtx := value.(*proxyContext)
pCtx.cancel() // Cancel causes the Envoy process to exit.
<-pCtx.exit // Wait for the Envoy process to completely exit.
close(pCtx.exit) // Close the channel to avoid leaking.
delete(i.proxyContextMap, proxyName)
}
}

Expand Down
Loading
Loading