diff --git a/internal/arduino/builder/internal/compilation/database.go b/internal/arduino/builder/internal/compilation/database.go index 73441bc07bc..9498b5a9e81 100644 --- a/internal/arduino/builder/internal/compilation/database.go +++ b/internal/arduino/builder/internal/compilation/database.go @@ -19,6 +19,7 @@ import ( "encoding/json" "fmt" "os" + "sync" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" @@ -28,8 +29,9 @@ var tr = i18n.Tr // Database keeps track of all the compile commands run by the builder type Database struct { - Contents []Command - File *paths.Path + lock sync.Mutex + contents []Command + file *paths.Path } // Command keeps track of a single run of a compile command @@ -43,8 +45,8 @@ type Command struct { // NewDatabase creates an empty CompilationDatabase func NewDatabase(filename *paths.Path) *Database { return &Database{ - File: filename, - Contents: []Command{}, + file: filename, + contents: []Command{}, } } @@ -55,16 +57,18 @@ func LoadDatabase(file *paths.Path) (*Database, error) { return nil, err } res := NewDatabase(file) - return res, json.Unmarshal(f, &res.Contents) + return res, json.Unmarshal(f, &res.contents) } // SaveToFile save the CompilationDatabase to file as a clangd-compatible compile_commands.json, // see https://clang.llvm.org/docs/JSONCompilationDatabase.html func (db *Database) SaveToFile() { - if jsonContents, err := json.MarshalIndent(db.Contents, "", " "); err != nil { + db.lock.Lock() + defer db.lock.Unlock() + if jsonContents, err := json.MarshalIndent(db.contents, "", " "); err != nil { fmt.Println(tr("Error serializing compilation database: %s", err)) return - } else if err := db.File.WriteFile(jsonContents); err != nil { + } else if err := db.file.WriteFile(jsonContents); err != nil { fmt.Println(tr("Error writing compilation database: %s", err)) } } @@ -88,5 +92,7 @@ func (db *Database) Add(target *paths.Path, command *paths.Process) { File: target.String(), } - db.Contents = append(db.Contents, entry) + db.lock.Lock() + db.contents = append(db.contents, entry) + db.lock.Unlock() } diff --git a/internal/arduino/builder/internal/compilation/database_test.go b/internal/arduino/builder/internal/compilation/database_test.go index abe5b7b24b9..dde90738d91 100644 --- a/internal/arduino/builder/internal/compilation/database_test.go +++ b/internal/arduino/builder/internal/compilation/database_test.go @@ -36,11 +36,11 @@ func TestCompilationDatabase(t *testing.T) { db2, err := LoadDatabase(tmpfile) require.NoError(t, err) require.Equal(t, db, db2) - require.Len(t, db2.Contents, 1) - require.Equal(t, db2.Contents[0].File, "test") - require.Equal(t, db2.Contents[0].Command, "") - require.Equal(t, db2.Contents[0].Arguments, []string{"gcc", "arg1", "arg2"}) + require.Len(t, db2.contents, 1) + require.Equal(t, db2.contents[0].File, "test") + require.Equal(t, db2.contents[0].Command, "") + require.Equal(t, db2.contents[0].Arguments, []string{"gcc", "arg1", "arg2"}) cwd, err := paths.Getwd() require.NoError(t, err) - require.Equal(t, db2.Contents[0].Directory, cwd.String()) + require.Equal(t, db2.contents[0].Directory, cwd.String()) }