-
Notifications
You must be signed in to change notification settings - Fork 601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
release: use locking around lazy intialized state #6306
Changes from 2 commits
2abaacf
1e57482
5e5f1ab
f4f650d
9546590
f6f927d
f487fc4
2819bdd
f0b8f75
c689713
d91930d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ import ( | |
"path/filepath" | ||
"sort" | ||
"strings" | ||
"sync" | ||
|
||
"github.com/snapcore/snapd/strutil" | ||
) | ||
|
@@ -83,43 +84,59 @@ var ( | |
// appArmorParserError contains an error, if any, encountered when | ||
// discovering available parser features. | ||
appArmorParserError error | ||
|
||
appArmorProbeParserOnce sync.Once | ||
appArmorProbeKernelOnce sync.Once | ||
appArmorAssessOnce sync.Once | ||
|
||
appArmorProbeKernel = probeAppArmorKernelFeaturesOnce | ||
appArmorProbeParser = probeAppArmorParserFeaturesOnce | ||
appArmorAssess = assessAppArmorOnce | ||
) | ||
|
||
func assessAppArmorOnce() { | ||
appArmorAssessOnce.Do(assessAppArmor) | ||
} | ||
|
||
// AppArmorLevel quantifies how well apparmor is supported on the current | ||
// kernel. The computation is costly to perform. The result is cached internally. | ||
func AppArmorLevel() AppArmorLevelType { | ||
if appArmorLevel == UnknownAppArmor { | ||
assessAppArmor() | ||
} | ||
appArmorAssess() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a test that checks if the assessment is cached and actually done once? Since this extra There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked into this, in the end I reorganized things quite a bit, mostly because the Mock* functions below are complicated/long but didn't help fully with testing this. I'm pushing the new code now, with it commenting the Once.Do bits always make some test fail. |
||
return appArmorLevel | ||
} | ||
|
||
// AppArmorSummary describes how well apparmor is supported on the current | ||
// kernel. The computation is costly to perform. The result is cached | ||
// internally. | ||
func AppArmorSummary() string { | ||
if appArmorLevel == UnknownAppArmor { | ||
assessAppArmor() | ||
} | ||
appArmorAssess() | ||
return appArmorSummary | ||
} | ||
|
||
func probeAppArmorKernelFeaturesOnce() { | ||
appArmorProbeKernelOnce.Do(func() { | ||
appArmorKernelFeatures, appArmorKernelError = probeAppArmorKernelFeatures() | ||
}) | ||
} | ||
|
||
// AppArmorKernelFeatures returns a sorted list of apparmor features like | ||
// []string{"dbus", "network"}. The result is cached internally. | ||
func AppArmorKernelFeatures() ([]string, error) { | ||
if appArmorKernelFeatures == nil { | ||
appArmorKernelFeatures, appArmorKernelError = probeAppArmorKernelFeatures() | ||
} | ||
appArmorProbeKernel() | ||
return appArmorKernelFeatures, appArmorKernelError | ||
} | ||
|
||
func probeAppArmorParserFeaturesOnce() { | ||
appArmorProbeParserOnce.Do(func() { | ||
appArmorParserFeatures, appArmorParserError = probeAppArmorParserFeatures() | ||
}) | ||
} | ||
|
||
// AppArmorParserFeatures returns a sorted list of apparmor parser features | ||
// like []string{"unsafe", ...}. The computation is costly to perform. The | ||
// result is cached internally. | ||
func AppArmorParserFeatures() ([]string, error) { | ||
if appArmorParserFeatures == nil { | ||
appArmorParserFeatures, appArmorParserError = probeAppArmorParserFeatures() | ||
} | ||
appArmorProbeParser() | ||
return appArmorParserFeatures, appArmorParserError | ||
} | ||
|
||
|
@@ -149,19 +166,29 @@ func MockAppArmorLevel(level AppArmorLevelType) (restore func()) { | |
oldAppArmorKernelError := appArmorKernelError | ||
oldAppArmorParserFeatures := appArmorParserFeatures | ||
oldAppArmorParserError := appArmorParserError | ||
oldAppArmorProbeKernel := appArmorProbeKernel | ||
oldAppArmorProbeParser := appArmorProbeParser | ||
oldAppArmorAssess := appArmorAssess | ||
appArmorLevel = level | ||
appArmorSummary = fmt.Sprintf("mocked apparmor level: %s", level) | ||
appArmorKernelFeatures = []string{"mocked-kernel-feature"} | ||
appArmorKernelError = nil | ||
appArmorParserFeatures = []string{"mocked-parser-feature"} | ||
appArmorParserError = nil | ||
nop := func() {} | ||
appArmorProbeKernel = nop | ||
appArmorProbeParser = nop | ||
appArmorAssess = nop | ||
return func() { | ||
appArmorLevel = oldAppArmorLevel | ||
appArmorSummary = oldAppArmorSummary | ||
appArmorKernelFeatures = oldAppArmorKernelFeatures | ||
appArmorKernelError = oldAppArmorKernelError | ||
appArmorParserFeatures = oldAppArmorParserFeatures | ||
appArmorParserError = oldAppArmorParserError | ||
appArmorProbeKernel = oldAppArmorProbeKernel | ||
appArmorProbeParser = oldAppArmorProbeParser | ||
appArmorAssess = oldAppArmorAssess | ||
} | ||
} | ||
|
||
|
@@ -176,10 +203,17 @@ func MockAppArmorFeatures(kernelFeatures []string, kernelError error, parserFeat | |
oldAppArmorKernelError := appArmorKernelError | ||
oldAppArmorParserFeatures := appArmorParserFeatures | ||
oldAppArmorParserError := appArmorParserError | ||
oldAppArmorProbeKernel := appArmorProbeKernel | ||
oldAppArmorProbeParser := appArmorProbeParser | ||
oldAppArmorAssess := appArmorAssess | ||
appArmorKernelFeatures = kernelFeatures | ||
appArmorKernelError = kernelError | ||
appArmorParserFeatures = parserFeatures | ||
appArmorParserError = parserError | ||
nop := func() {} | ||
appArmorProbeKernel = nop | ||
appArmorProbeParser = nop | ||
appArmorAssess = nop | ||
if appArmorKernelFeatures != nil && appArmorParserFeatures != nil { | ||
assessAppArmor() | ||
} | ||
|
@@ -188,6 +222,9 @@ func MockAppArmorFeatures(kernelFeatures []string, kernelError error, parserFeat | |
appArmorKernelError = oldAppArmorKernelError | ||
appArmorParserFeatures = oldAppArmorParserFeatures | ||
appArmorParserError = oldAppArmorParserError | ||
appArmorProbeKernel = oldAppArmorProbeKernel | ||
appArmorProbeParser = oldAppArmorProbeParser | ||
appArmorAssess = oldAppArmorAssess | ||
if appArmorKernelFeatures != nil && appArmorParserFeatures != nil { | ||
assessAppArmor() | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
were the actual functions like assesAppArmor etc tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they are tested in a couple of places: