Skip to content
Snippets Groups Projects
Commit 080e3f1c authored by Alessio Caiazza's avatar Alessio Caiazza Committed by Alessio Caiazza
Browse files

Fix race condition in single runner

parent 934a92ea
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/tevino/abool"
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common" "gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
"gitlab.com/gitlab-org/gitlab-ci-multi-runner/network" "gitlab.com/gitlab-org/gitlab-ci-multi-runner/network"
"os/signal" "os/signal"
...@@ -20,16 +21,16 @@ type RunSingleCommand struct { ...@@ -20,16 +21,16 @@ type RunSingleCommand struct {
lastBuild time.Time lastBuild time.Time
runForever bool runForever bool
MaxBuilds int `long:"max-builds" description:"How many builds to process before exiting"` MaxBuilds int `long:"max-builds" description:"How many builds to process before exiting"`
finished bool finished *abool.AtomicBool
} }
func waitForInterrupts(finished *bool, abortSignal chan os.Signal, doneSignal chan int) { func waitForInterrupts(finished *abool.AtomicBool, abortSignal chan os.Signal, doneSignal chan int) {
signals := make(chan os.Signal) signals := make(chan os.Signal)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) signal.Notify(signals, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
interrupt := <-signals interrupt := <-signals
if finished != nil { if finished != nil {
*finished = true finished.Set()
} }
// request stop, but wait for force exit // request stop, but wait for force exit
...@@ -108,11 +109,11 @@ func (r *RunSingleCommand) processBuild(data common.ExecutorData, abortSignal ch ...@@ -108,11 +109,11 @@ func (r *RunSingleCommand) processBuild(data common.ExecutorData, abortSignal ch
func (r *RunSingleCommand) checkFinishedConditions() { func (r *RunSingleCommand) checkFinishedConditions() {
if r.MaxBuilds < 1 && !r.runForever { if r.MaxBuilds < 1 && !r.runForever {
log.Println("This runner has processed its build limit, so now exiting") log.Println("This runner has processed its build limit, so now exiting")
r.finished = true r.finished.Set()
} }
if r.WaitTimeout > 0 && int(time.Since(r.lastBuild).Seconds()) > r.WaitTimeout { if r.WaitTimeout > 0 && int(time.Since(r.lastBuild).Seconds()) > r.WaitTimeout {
log.Println("This runner has not received a job in", r.WaitTimeout, "seconds, so now exiting") log.Println("This runner has not received a job in", r.WaitTimeout, "seconds, so now exiting")
r.finished = true r.finished.Set()
} }
return return
} }
...@@ -135,16 +136,16 @@ func (r *RunSingleCommand) Execute(c *cli.Context) { ...@@ -135,16 +136,16 @@ func (r *RunSingleCommand) Execute(c *cli.Context) {
log.Println("Starting runner for", r.URL, "with token", r.ShortDescription(), "...") log.Println("Starting runner for", r.URL, "with token", r.ShortDescription(), "...")
r.finished = false r.finished = abool.New()
abortSignal := make(chan os.Signal) abortSignal := make(chan os.Signal)
doneSignal := make(chan int, 1) doneSignal := make(chan int, 1)
r.runForever = r.MaxBuilds == 0 r.runForever = r.MaxBuilds == 0
go waitForInterrupts(&r.finished, abortSignal, doneSignal) go waitForInterrupts(r.finished, abortSignal, doneSignal)
r.lastBuild = time.Now() r.lastBuild = time.Now()
for !r.finished { for !r.finished.IsSet() {
data, err := executorProvider.Acquire(&r.RunnerConfig) data, err := executorProvider.Acquire(&r.RunnerConfig)
if err != nil { if err != nil {
log.Warningln("Executor update:", err) log.Warningln("Executor update:", err)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment