Fix handling of unmapped configuration options

This commit is contained in:
Patrick Pacher 2022-09-05 15:02:12 +02:00
parent 900a654a4d
commit 34453d6989
No known key found for this signature in database
GPG key ID: E8CD2DA160925A6D
2 changed files with 39 additions and 1 deletions

View file

@ -11,6 +11,12 @@ import (
var (
optionsLock sync.RWMutex
options = make(map[string]*Option)
// unmappedValues holds a list of configuration values that have been
// read from the persistence layer but no option has been defined yet.
// This is mainly to support the plugin system of the Portmaster.
unmappedValuesLock sync.Mutex
unmappedValues map[string]interface{}
)
// ForEachOption calls fn for each defined option. If fn returns
@ -98,9 +104,29 @@ func Register(option *Option) error {
return fmt.Errorf("config: invalid default value: %w", vErr)
}
if err := loadUnmappedValue(option); err != nil {
return err
}
optionsLock.Lock()
defer optionsLock.Unlock()
options[option.Key] = option
return nil
}
func loadUnmappedValue(option *Option) error {
unmappedValuesLock.Lock()
defer unmappedValuesLock.Unlock()
if value, ok := unmappedValues[option.Key]; ok {
delete(unmappedValues, option.Key)
var vErr *ValidationError
option.activeValue, vErr = validateValue(option, value)
if vErr != nil {
return fmt.Errorf("config: invalid value: %w", vErr)
}
}
return nil
}

View file

@ -41,6 +41,11 @@ func signalChanges() {
func replaceConfig(newValues map[string]interface{}) []*ValidationError {
var validationErrors []*ValidationError
valuesCopy := make(map[string]interface{}, len(newValues))
for key, value := range newValues {
valuesCopy[key] = value
}
// RLock the options because we are not adding or removing
// options from the registration but rather only update the
// options value which is guarded by the option's lock itself
@ -48,7 +53,9 @@ func replaceConfig(newValues map[string]interface{}) []*ValidationError {
defer optionsLock.RUnlock()
for key, option := range options {
newValue, ok := newValues[key]
newValue, ok := valuesCopy[key]
delete(valuesCopy, key)
option.Lock()
option.activeValue = nil
@ -66,6 +73,11 @@ func replaceConfig(newValues map[string]interface{}) []*ValidationError {
option.Unlock()
}
unmappedValuesLock.Lock()
defer unmappedValuesLock.Unlock()
unmappedValues = valuesCopy
signalChanges()
return validationErrors