From: Sergey Matveev Date: Sat, 23 Sep 2023 14:13:59 +0000 (+0300) Subject: Prevent possible race when building target twice X-Git-Tag: v1.31.0~2 X-Git-Url: http://www.git.cypherpunks.ru/?p=goredo.git;a=commitdiff_plain;h=8e1c9b41428b4c988a05644ca2e9f9c3b0a7d65e Prevent possible race when building target twice --- diff --git a/doc/news.texi b/doc/news.texi index d519c7d..fcd0d75 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -2,6 +2,13 @@ @cindex news @unnumbered News +@anchor{Release 1_31_0} +@section Release 1.31.0 +@itemize +@item + Fixed possible race when target can be built more than once. +@end itemize + @anchor{Release 1_30_0} @section Release 1.30.0 @itemize diff --git a/ifchange.go b/ifchange.go index 4a43872..401574d 100644 --- a/ifchange.go +++ b/ifchange.go @@ -109,7 +109,7 @@ func buildDependants(tgts []string) map[string]struct{} { tracef(CDebug, "building %d alwayses: %v", len(seen), seen) errs := make(chan error, len(seen)) for tgt := range seen { - if err := runScript(tgt, errs, false); err != nil { + if err := runScript(tgt, errs, false, false); err != nil { tracef(CErr, "always run error: %s, skipping dependants", err) return nil } @@ -155,7 +155,7 @@ RebuildDeps: if !ood { continue } - if err := runScript(tgt, errs, false); err != nil { + if err := runScript(tgt, errs, false, false); err != nil { tracef(CErr, "dependant error: %s, skipping dependants", err) return nil } @@ -225,7 +225,7 @@ func ifchange(tgts []string, forced, traced bool) (bool, error) { tracef(CDebug, "%s is source, not redoing", tgt) continue } - if err = runScript(tgt, errs, traced); err != nil { + if err = runScript(tgt, errs, forced, traced); err != nil { return false, err } jobs++ diff --git a/main.go b/main.go index 634ca8f..8c95d84 100644 --- a/main.go +++ b/main.go @@ -298,7 +298,7 @@ func main() { } } - if cmdName == CmdNameRedo || cmdName == CmdNameRedoIfchange { + if cmdName == CmdNameRedo { statusInit() } diff --git a/run.go b/run.go index 2e5dbf5..7ee4637 100644 --- a/run.go +++ b/run.go @@ -184,7 +184,7 @@ func syncDir(dir string) error { return err } -func runScript(tgtOrig string, errs chan error, traced bool) error { +func runScript(tgtOrig string, errs chan error, forced, traced bool) error { cwd, tgt := cwdAndTgt(tgtOrig) redoDir := path.Join(cwd, RedoDir) if err := mkdirs(redoDir); err != nil { @@ -281,6 +281,19 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { return nil } + // Check if it was already built in parallel + if !forced { + if fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)); err == nil { + depInfo, err := depRead(fdDep) + fdDep.Close() + if err == nil && depInfo.build == BuildUUID { + lockRelease() + errs <- nil + return nil + } + } + } + // Check if target is not modified externally modified, inodePrev, hshPrev, err := isModified(cwd, redoDir, tgt) if err != nil { diff --git a/usage.go b/usage.go index e67077f..6e43b57 100644 --- a/usage.go +++ b/usage.go @@ -24,7 +24,7 @@ import ( ) const ( - Version = "1.30.0" + Version = "1.31.0" Warranty = `Copyright (C) 2020-2023 Sergey Matveev This program is free software: you can redistribute it and/or modify