Skip to content

Commit

Permalink
Merge pull request shirou#951 from rmfitzpatrick/fix_virtualization_race
Browse files Browse the repository at this point in the history
Fix VirtualizationWithContext() race in linux
  • Loading branch information
shirou authored Oct 11, 2020
2 parents fe68b86 + 8046134 commit ad46664
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 18 deletions.
26 changes: 19 additions & 7 deletions host/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package host
import (
"fmt"
"os"
"sync"
"testing"

"github.com/shirou/gopsutil/internal/common"
Expand Down Expand Up @@ -144,13 +145,24 @@ func TestTemperatureStat_String(t *testing.T) {
}

func TestVirtualization(t *testing.T) {
system, role, err := Virtualization()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("Virtualization() failed, %v", err)
}

t.Logf("Virtualization(): %s, %s", system, role)
wg := sync.WaitGroup{}
testCount := 10
wg.Add(testCount)
for i := 0; i < testCount; i++ {
go func(j int) {
system, role, err := Virtualization()
wg.Done()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("Virtualization() failed, %v", err)
}

if j == 9 {
t.Logf("Virtualization(): %s, %s", system, role)
}
}(i)
}
wg.Wait()
}

func TestKernelVersion(t *testing.T) {
Expand Down
52 changes: 41 additions & 11 deletions internal/common/common_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"
)

Expand Down Expand Up @@ -110,16 +111,49 @@ func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}

var virtualizationCache map[string]string
type virtCache struct {
cache map[string]string
lock sync.Mutex
ok bool
}

func (v *virtCache) setValue(system, role string) {
v.lock.Lock()
defer v.lock.Unlock()
v.cache["system"] = system
v.cache["role"] = role
v.ok = true
}

func (v *virtCache) getValue() (string, string, bool) {
v.lock.Lock()
defer v.lock.Unlock()
return v.cache["system"], v.cache["role"], v.ok
}

var (
once sync.Once
virtualization *virtCache
)

func virtualizationCache() *virtCache {
once.Do(func() {
virtualization = &virtCache{
cache: make(map[string]string),
lock: sync.Mutex{},
ok: false,
}
})

return virtualization
}

func VirtualizationWithContext(ctx context.Context) (string, string, error) {
// if cached already, return from cache
if virtualizationCache != nil {
return virtualizationCache["system"], virtualizationCache["role"], nil
system, role, ok := virtualizationCache().getValue()
if ok {
return system, role, nil
}

var system string
var role string

filename := HostProc("xen")
if PathExists(filename) {
Expand Down Expand Up @@ -240,11 +274,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}

// before returning for the first time, cache the system and role
virtualizationCache = map[string]string{
"system": system,
"role": role,
}

virtualizationCache().setValue(system, role)
return system, role, nil
}

Expand Down

0 comments on commit ad46664

Please sign in to comment.