Skip to content

Commit aabd920

Browse files
simonpahleshepelyuk
authored andcommitted
fix: cancel BackgroundRefresh on config reload
This commit mitigates a thread leak that occurs when a config instantiating the plugin is reloaded. The plugin's `BackgroundRefresh` goroutine will now be canceled when the plugin is instantiated with the same name, which should only occur when the config is reloaded. Closes #67
1 parent 872685b commit aabd920

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

jwt.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import (
2727
"time"
2828
)
2929

30+
// map of cancel functions for background refresh. whe a new configuration is loaded, the old background refresh with the same name is cancelled
31+
var backgroundRefreshCancel map[string]context.CancelFunc = make(map[string]context.CancelFunc)
32+
3033
// Config the plugin configuration.
3134
type Config struct {
3235
OpaUrl string
@@ -77,8 +80,10 @@ type JwtPlugin struct {
7780
jwtCookieKey string
7881
jwtQueryKey string
7982

83+
name string
8084
keysLock sync.RWMutex
8185
forceRefreshCmd chan chan<- struct{}
86+
cancelCtx context.Context
8287
}
8388

8489
// LogEvent contains a single log entry
@@ -169,7 +174,7 @@ type Response struct {
169174
}
170175

171176
// New creates a new plugin
172-
func New(_ context.Context, next http.Handler, config *Config, _ string) (http.Handler, error) {
177+
func New(ctx context.Context, next http.Handler, config *Config, pluginName string) (http.Handler, error) {
173178
jwtPlugin := &JwtPlugin{
174179
httpClient: &http.Client{},
175180
next: next,
@@ -188,6 +193,7 @@ func New(_ context.Context, next http.Handler, config *Config, _ string) (http.H
188193
opaHttpStatusField: config.OpaHttpStatusField,
189194
jwtCookieKey: config.JwtCookieKey,
190195
jwtQueryKey: config.JwtQueryKey,
196+
name: pluginName,
191197
}
192198
if len(config.Keys) > 0 {
193199
if err := jwtPlugin.ParseKeys(config.Keys); err != nil {
@@ -197,6 +203,13 @@ func New(_ context.Context, next http.Handler, config *Config, _ string) (http.H
197203
if config.ForceRefreshKeys {
198204
jwtPlugin.forceRefreshCmd = make(chan chan<- struct{})
199205
}
206+
if backgroundRefreshCancel[pluginName] != nil {
207+
logInfo(fmt.Sprintf("Cancel BackgroundRefresh %s", pluginName)).print()
208+
backgroundRefreshCancel[pluginName]()
209+
}
210+
cancel, cancelFunc := context.WithCancel(ctx)
211+
backgroundRefreshCancel[pluginName] = cancelFunc
212+
jwtPlugin.cancelCtx = cancel
200213
go jwtPlugin.BackgroundRefresh()
201214
}
202215
}
@@ -210,6 +223,9 @@ func (jwtPlugin *JwtPlugin) BackgroundRefresh() {
210223
case keysFetchedChan := <-jwtPlugin.forceRefreshCmd:
211224
jwtPlugin.FetchKeys()
212225
keysFetchedChan <- struct{}{}
226+
case <-jwtPlugin.cancelCtx.Done():
227+
logInfo(fmt.Sprintf("Quit BackgroundRefresh for %s", jwtPlugin.name)).print()
228+
return
213229
case <-time.After(15 * time.Minute):
214230
jwtPlugin.FetchKeys()
215231
}

0 commit comments

Comments
 (0)