mirror of
https://github.com/ddworken/hishtory.git
synced 2025-05-01 04:44:36 +02:00
Fix config corruption bug caused by parallel writes to the same tmp file to fix #47
This commit is contained in:
parent
a269478273
commit
b7533479a3
@ -12,6 +12,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -2290,6 +2291,43 @@ echo foo`)
|
|||||||
compareGoldens(t, out, "testRemoveDuplicateRows-enabled-tquery")
|
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 {
|
type deviceSet struct {
|
||||||
deviceMap *map[device]deviceOp
|
deviceMap *map[device]deviceOp
|
||||||
currentDevice *device
|
currentDevice *device
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ddworken/hishtory/client/data"
|
"github.com/ddworken/hishtory/client/data"
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -237,7 +238,7 @@ func SetConfig(config ClientConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
configPath := path.Join(homedir, data.HISHTORY_PATH, data.CONFIG_PATH)
|
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)
|
err = os.WriteFile(stagedConfigPath, serializedConfig, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write config: %v", err)
|
return fmt.Errorf("failed to write config: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user