Fix config corruption bug caused by parallel writes to the same tmp file to fix #47

This commit is contained in:
David Dworken 2022-12-11 19:15:29 -08:00
parent a269478273
commit b7533479a3
No known key found for this signature in database
2 changed files with 40 additions and 1 deletions

View File

@ -12,6 +12,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"testing"
"time"
@ -2290,6 +2291,43 @@ echo foo`)
compareGoldens(t, out, "testRemoveDuplicateRows-enabled-tquery")
}
func TestSetConfigNoCorruption(t *testing.T) {
// Setup
tester := zshTester{}
defer testutils.BackupAndRestore(t)()
installHishtory(t, tester, "")
// A test that tries writing a config many different times in parallel, and confirms there is no corruption
conf, err := hctx.GetConfig()
testutils.Check(t, err)
var doneWg sync.WaitGroup
for i := 0; i < 10; i++ {
doneWg.Add(1)
go func(i int) {
// Make a new config of a varied length
c := conf
c.LastSavedHistoryLine = strings.Repeat("A", i)
c.DeviceId = strings.Repeat("B", i*2)
c.HaveMissedUploads = (i % 2) == 0
// Write it
err := hctx.SetConfig(c)
if err != nil {
panic(err)
}
// Check that we can read
c2, err := hctx.GetConfig()
if err != nil {
panic(err)
}
if c2.UserSecret != c.UserSecret {
panic("user secret mismatch")
}
doneWg.Done()
}(i)
}
doneWg.Wait()
}
type deviceSet struct {
deviceMap *map[device]deviceOp
currentDevice *device

View File

@ -11,6 +11,7 @@ import (
"time"
"github.com/ddworken/hishtory/client/data"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
"gorm.io/gorm"
@ -237,7 +238,7 @@ func SetConfig(config ClientConfig) error {
return err
}
configPath := path.Join(homedir, data.HISHTORY_PATH, data.CONFIG_PATH)
stagedConfigPath := configPath + ".tmp"
stagedConfigPath := configPath + ".tmp-" + uuid.Must(uuid.NewRandom()).String()
err = os.WriteFile(stagedConfigPath, serializedConfig, 0o644)
if err != nil {
return fmt.Errorf("failed to write config: %v", err)