-
Notifications
You must be signed in to change notification settings - Fork 14
Conversation
} | ||
|
||
type smartResults map[string]interface{} | ||
|
||
// CollectMetrics returns metrics from smart | ||
func (sc *SmartCollector) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricType, error) { | ||
err := sc.setProcDevPath(mts[0]) |
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.
For functions that are callbacks/handlers (potentially executed in separate goroutines) it's safer to execute code modifying non-local variables in a mutex. Good pattern for such initialization function is to use initialized bool
field of the object and when it's true skip init, in other case it should proceed regularly and make this field true at the end.
I've added single comment about thread safety, but besides that everyting LGTM. |
@lmroz thanks for catching this potential issue. I have added your suggestion in my latest commit "copying" it from cpu collector code |
@obourdon It's not exactly the solution I'd like to see (operations on regular variables are not atomic, unlikely in case of Here is example for other plugin that shows solution I'd expect:
It comes from nova plugin https://github.com/intelsdi-x/snap-plugin-collector-nova/blob/master/novaplugin/plugin.go |
@lmroz, the emon plugin is private with no plans to open it. That said the On Wed, Aug 17, 2016 at 7:37 AM Łukasz Mróz notifications@github.com
|
@lmroz many thanks for making this very precise. The question I now have is: "should this code be also implemented in all other plugins where the same kind of code is already implemented (CPU) as well as other pending PRs ???" Thanks for your comments |
@jcooklin I realized it just after posting so changed snippet to another plugin (I hope it's not disclosing much) :/ @obourdon I think that code should be present in any plugin that does some kind of lazy initialization in callbacks/handlers (the only way possible to do initalization based on config). |
@lmroz thanks for the detailed snippet, very clear. Could you please review the new submission to see if it fits your expectations ? |
} | ||
|
||
type smartResults map[string]interface{} | ||
|
||
// CollectMetrics returns metrics from smart | ||
func (sc *SmartCollector) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricType, error) { | ||
if !sc.initialized { |
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.
You should have that check done also under Lock. Having lock just during initialization prevents data corruption during initialization (like concurrent write to complex data structure like map
), but does not prevent double initialization (that might lead to incorrect initialization, but hopefully not in this case). This line might be kept if also added in setProcDevPath
. Then you'll have double checked lock pattern (https://en.wikipedia.org/wiki/Double-checked_locking ). Sorry for being that strict, but:
- Even if now it's not causing problem it might do in future
- Snippets from already existing plugins are copied to new ones, so we should use best known practice for such cases
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.
@lmroz no pb at all, fully agree that it is better to do it right at the soonest.
Current modification on its way for new review
@lmroz I hope the latest code is more in sync with your expectations. The boolean check is now located within the lock code in accordance to your example here |
You can now run this plugin within a Docker container
Note however that the container must have the privileged mode activated and /proc and /dev of host must be mounted as volumes in the container.
Example: