From 88e424a0f91d46b0b00931d95ba1f174478c222d Mon Sep 17 00:00:00 2001 From: Umberto Baldi <34278123+umbynos@users.noreply.github.com> Date: Fri, 29 Jan 2021 16:58:18 +0100 Subject: [PATCH] [EDITOR-512] Fix concurrent map read and map write (#585) * update doc * add read write mutex synchronization to installed map --- docs/tools.md | 4 +++- tools/download.go | 6 ++++++ tools/tools.go | 21 ++++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/tools.md b/docs/tools.md index 35be570c9..93ac8e3f8 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -10,7 +10,8 @@ ```go type Tools struct { Directory string - IndexURL string + IndexURL string + LastRefresh time.Time Logger log.StdLogger } ``` @@ -20,6 +21,7 @@ to download a tool from the arduino servers. - *Directory* contains the location where the tools are downloaded. - *IndexURL* contains the url where the tools description is contained. +- *LastRefresh* contains the last update time - *Logger* is a StdLogger used for reporting debug and info messages - *installed* contains a map of the tools and their exact location diff --git a/tools/download.go b/tools/download.go index c5fa4f31f..6c9ced87b 100644 --- a/tools/download.go +++ b/tools/download.go @@ -193,10 +193,14 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { // Check if it already exists if behaviour == "keep" { + t.mutex.RLock() location, ok := t.installed[key] + t.mutex.RUnlock() if ok && pathExists(location) { // overwrite the default tool with this one + t.mutex.Lock() t.installed[correctTool.Name] = location + t.mutex.Unlock() t.Logger("The tool is already present on the system") return t.writeMap() } @@ -267,8 +271,10 @@ func (t *Tools) Download(pack, name, version, behaviour string) error { // Update the tool map t.Logger("Updating map with location " + location) + t.mutex.Lock() t.installed[name] = location t.installed[name+"-"+correctTool.Version] = location + t.mutex.Unlock() return t.writeMap() } diff --git a/tools/tools.go b/tools/tools.go index 2884325da..88ef425ea 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -9,6 +9,7 @@ import ( "path" "path/filepath" "strings" + "sync" "time" "github.com/xrash/smetrics" @@ -35,21 +36,30 @@ type Tools struct { LastRefresh time.Time Logger func(msg string) installed map[string]string + mutex sync.RWMutex } // Init creates the Installed map and populates it from a file in .arduino-create func (t *Tools) Init(APIlevel string) { createDir(t.Directory) + t.mutex.Lock() t.installed = make(map[string]string) + t.mutex.Unlock() t.readMap() + t.mutex.RLock() if t.installed["apilevel"] != APIlevel { + t.mutex.RUnlock() // wipe the folder and reinitialize the data os.RemoveAll(t.Directory) createDir(t.Directory) + t.mutex.Lock() t.installed = make(map[string]string) t.installed["apilevel"] = APIlevel + t.mutex.Unlock() t.writeMap() t.readMap() + } else { + t.mutex.RUnlock() } } @@ -62,13 +72,17 @@ func (t *Tools) GetLocation(command string) (string, error) { var ok bool // Load installed + t.mutex.RLock() fmt.Println(t.installed) + t.mutex.RUnlock() err := t.readMap() if err != nil { return "", err } + t.mutex.RLock() + defer t.mutex.RUnlock() fmt.Println(t.installed) // use string similarity to resolve a runtime var with a "similar" map element @@ -82,12 +96,14 @@ func (t *Tools) GetLocation(command string) (string, error) { } } } - return filepath.ToSlash(location), nil } +// writeMap() writes installed map to the json file "installed.json" func (t *Tools) writeMap() error { + t.mutex.RLock() b, err := json.Marshal(t.installed) + t.mutex.RUnlock() if err != nil { return err } @@ -95,12 +111,15 @@ func (t *Tools) writeMap() error { return ioutil.WriteFile(filePath, b, 0644) } +// readMap() reads the installed map from json file "installed.json" func (t *Tools) readMap() error { filePath := path.Join(dir(), "installed.json") b, err := ioutil.ReadFile(filePath) if err != nil { return err } + t.mutex.Lock() + defer t.mutex.Unlock() return json.Unmarshal(b, &t.installed) }