Fix the concurrent map writes

This commit is contained in:
2025-03-28 11:33:36 +01:00
parent ebb07854cc
commit 04cedf5ece

63
main.go
View File

@@ -21,14 +21,14 @@ type GlobalStats struct {
TotalModifications int TotalModifications int
ProcessedFiles int ProcessedFiles int
FailedFiles int FailedFiles int
ModificationsPerCommand map[string]int ModificationsPerCommand sync.Map
} }
var ( var (
repo *git.Repository repo *git.Repository
worktree *git.Worktree worktree *git.Worktree
stats GlobalStats = GlobalStats{ stats GlobalStats = GlobalStats{
ModificationsPerCommand: make(map[string]int), ModificationsPerCommand: sync.Map{},
} }
) )
@@ -54,46 +54,6 @@ func main() {
fmt.Fprintf(os.Stderr, " Glob patterns are supported for file selection (*.xml, data/**.xml, etc.)\n") fmt.Fprintf(os.Stderr, " Glob patterns are supported for file selection (*.xml, data/**.xml, etc.)\n")
} }
// TODO: Fix bed shitting when doing *.yml in barotrauma directory // TODO: Fix bed shitting when doing *.yml in barotrauma directory
// TODO: Fix disaster:
// fatal error: concurrent map writes
//
// goroutine 243 [running]:
// internal/runtime/maps.fatal({0x8b9c77?, 0xc003399ce8?})
// C:/Users/Administrator/scoop/apps/go/current/src/runtime/panic.go:1058 +0x18
// main.main.func2({0x0?, 0x0?, 0x0?})
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/main.go:137 +0x31d
// modify/logger.SafeGoWithArgs.func1()
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/panic_handler.go:31 +0x43
// created by modify/logger.SafeGoWithArgs in goroutine 1
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/panic_handler.go:29 +0x86
//
// goroutine 1 [chan send]:
// main.main()
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/main.go:107 +0x5aa
//
// goroutine 547 [sync.Mutex.Lock]:
// internal/sync.runtime_SemacquireMutex(0x0?, 0x5b?, 0x0?)
// C:/Users/Administrator/scoop/apps/go/current/src/runtime/sema.go:95 +0x25
// internal/sync.(*Mutex).lockSlow(0xc0000a2240)
// C:/Users/Administrator/scoop/apps/go/current/src/internal/sync/mutex.go:149 +0x15d
// internal/sync.(*Mutex).Lock(...)
// C:/Users/Administrator/scoop/apps/go/current/src/internal/sync/mutex.go:70
// sync.(*Mutex).Lock(...)
// C:/Users/Administrator/scoop/apps/go/current/src/sync/mutex.go:46
// modify/logger.(*Logger).log(0xc0000a2240, 0x1, {0x8bf8ab, 0x1e}, {0xc007049d08, 0x1, 0x1})
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/logger.go:321 +0x9d
// modify/logger.(*Logger).Warning(...)
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/logger.go:335
// modify/logger.Warning({0x8bf8ab?, 0x5c?}, {0xc004d87d08?, 0xc006b85ae0?, 0x53f3b9?})
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/logger.go:373 +0x87
// modify/processor.ProcessRegex({0xc004025000, 0x1f0}, {{0xc00026c450, 0xa}, {0xc000015bd0, 0x4b}, {0xc000261c00, 0xf4}, {0xc000282110, 0x1, ...}, ...})
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/processor/regex.go:64 +0x5c5
// main.main.func2({0x0?, 0x0?, 0x0?})
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/main.go:128 +0x471
// modify/logger.SafeGoWithArgs.func1()
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/panic_handler.go:31 +0x43
// created by modify/logger.SafeGoWithArgs in goroutine 1
// C:/Users/Administrator/Seafile/Projects-Go/GoProjects/modifier/logger/panic_handler.go:29 +0x86
flag.Parse() flag.Parse()
args := flag.Args() args := flag.Args()
@@ -178,7 +138,11 @@ func main() {
// It is not guranteed that all the commands will be executed... // It is not guranteed that all the commands will be executed...
// TODO: Make this better // TODO: Make this better
// We'd have to pass the map to executemodifications or something... // We'd have to pass the map to executemodifications or something...
stats.ModificationsPerCommand[command.Name] += len(commands) count, ok := stats.ModificationsPerCommand.Load(command.Name)
if !ok {
count = 0
}
stats.ModificationsPerCommand.Store(command.Name, count.(int)+len(commands))
} }
if len(modifications) == 0 { if len(modifications) == 0 {
@@ -261,15 +225,16 @@ func main() {
stats.TotalModifications, stats.ProcessedFiles, stats.ProcessedFiles+stats.FailedFiles) stats.TotalModifications, stats.ProcessedFiles, stats.ProcessedFiles+stats.FailedFiles)
fmt.Printf("Operation complete! Modified %d values in %d/%d files\n", fmt.Printf("Operation complete! Modified %d values in %d/%d files\n",
stats.TotalModifications, stats.ProcessedFiles, stats.ProcessedFiles+stats.FailedFiles) stats.TotalModifications, stats.ProcessedFiles, stats.ProcessedFiles+stats.FailedFiles)
sortedCommands := make([]string, 0, len(stats.ModificationsPerCommand)) sortedCommands := []string{}
for command := range stats.ModificationsPerCommand { stats.ModificationsPerCommand.Range(func(key, value interface{}) bool {
sortedCommands = append(sortedCommands, command) sortedCommands = append(sortedCommands, key.(string))
} return true
})
sort.Strings(sortedCommands) sort.Strings(sortedCommands)
for _, command := range sortedCommands { for _, command := range sortedCommands {
count := stats.ModificationsPerCommand[command] count, _ := stats.ModificationsPerCommand.Load(command)
if count > 0 { if count.(int) > 0 {
logger.Info("\tCommand %q made %d modifications", command, count) logger.Info("\tCommand %q made %d modifications", command, count)
} else { } else {
logger.Warning("\tCommand %q made no modifications", command) logger.Warning("\tCommand %q made no modifications", command)