Skip to content

Commit

Permalink
bug fix: log over-written in twoStageRsyncProvider
Browse files Browse the repository at this point in the history
solve more DATA RACE problem
  • Loading branch information
z4yx committed May 30, 2018
1 parent c5bb172 commit 0fdb07d
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 16 deletions.
13 changes: 10 additions & 3 deletions worker/base_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,16 @@ func (p *baseProvider) Docker() *dockerHook {
return p.docker
}

func (p *baseProvider) prepareLogFile() error {
func (p *baseProvider) prepareLogFile(append bool) error {
if p.LogFile() == "/dev/null" {
p.cmd.SetLogFile(nil)
return nil
}
logFile, err := os.OpenFile(p.LogFile(), os.O_WRONLY|os.O_CREATE, 0644)
appendMode := 0
if append {
appendMode = os.O_APPEND
}
logFile, err := os.OpenFile(p.LogFile(), os.O_WRONLY|os.O_CREATE|appendMode, 0644)
if err != nil {
logger.Errorf("Error opening logfile %s: %s", p.LogFile(), err.Error())
return err
Expand All @@ -138,19 +142,22 @@ func (p *baseProvider) IsRunning() bool {

func (p *baseProvider) Wait() error {
defer func() {
logger.Debugf("set isRunning to false: %s", p.Name())
p.isRunning.Store(false)
}()
logger.Debugf("calling Wait: %s", p.Name())
return p.cmd.Wait()
}

func (p *baseProvider) Terminate() error {
p.Lock()
defer p.Unlock()
logger.Debugf("terminating provider: %s", p.Name())
if !p.IsRunning() {
return nil
}

err := p.cmd.Terminate()
p.isRunning.Store(false)

return err
}
10 changes: 9 additions & 1 deletion worker/cmd_provider.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package worker

import (
"errors"
"time"

"github.com/anmitsu/go-shlex"
Expand Down Expand Up @@ -60,6 +61,13 @@ func (p *cmdProvider) Run() error {
}

func (p *cmdProvider) Start() error {
p.Lock()
defer p.Unlock()

if p.IsRunning() {
return errors.New("provider is currently running")
}

env := map[string]string{
"TUNASYNC_MIRROR_NAME": p.Name(),
"TUNASYNC_WORKING_DIR": p.WorkingDir(),
Expand All @@ -71,7 +79,7 @@ func (p *cmdProvider) Start() error {
env[k] = v
}
p.cmd = newCmdJob(p, p.command, p.WorkingDir(), env)
if err := p.prepareLogFile(); err != nil {
if err := p.prepareLogFile(false); err != nil {
return err
}

Expand Down
6 changes: 3 additions & 3 deletions worker/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"sync"
"sync/atomic"
"time"

tunasync "github.com/tuna/tunasync/internal"
)
Expand Down Expand Up @@ -154,9 +155,7 @@ func (m *mirrorJob) Run(managerChan chan<- jobMessage, semaphore chan empty) err
syncDone := make(chan error, 1)
go func() {
err := provider.Run()
if !stopASAP {
syncDone <- err
}
syncDone <- err
}()

select {
Expand Down Expand Up @@ -248,6 +247,7 @@ func (m *mirrorJob) Run(managerChan chan<- jobMessage, semaphore chan empty) err
m.SetState(stateReady)
close(kill)
<-jobDone
time.Sleep(time.Second) // Restart may fail if the process was not exited yet
continue
case jobStart:
m.SetState(stateReady)
Expand Down
11 changes: 7 additions & 4 deletions worker/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ exit 0
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
So(err, ShouldBeNil)

targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
expectedOutput := fmt.Sprintf(
"syncing to %s\n"+
"%s\n"+
"Done\n",
provider.WorkingDir(),
targetDir,
fmt.Sprintf(
"-aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
"--delete --delete-after --delay-updates --safe-links "+
Expand Down Expand Up @@ -144,11 +145,12 @@ exit 0
err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
So(err, ShouldBeNil)

targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
expectedOutput := fmt.Sprintf(
"syncing to %s\n"+
"%s\n"+
"Done\n",
provider.WorkingDir(),
targetDir,
fmt.Sprintf(
"%s %s -aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
"--delete --delete-after --delay-updates --safe-links "+
Expand Down Expand Up @@ -306,21 +308,22 @@ exit 0
err = provider.Run()
So(err, ShouldBeNil)

targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
expectedOutput := fmt.Sprintf(
"syncing to %s\n"+
"%s\n"+
"Done\n"+
"syncing to %s\n"+
"%s\n"+
"Done\n",
provider.WorkingDir(),
targetDir,
fmt.Sprintf(
"-aHvh --no-o --no-g --stats --exclude .~tmp~/ --safe-links "+
"--timeout=120 --contimeout=120 --exclude dists/ -6 "+
"--exclude-from %s %s %s",
provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
),
provider.WorkingDir(),
targetDir,
fmt.Sprintf(
"-aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
"--delete --delete-after --delay-updates --safe-links "+
Expand Down
8 changes: 7 additions & 1 deletion worker/rsync_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ func (p *rsyncProvider) Run() error {
}

func (p *rsyncProvider) Start() error {
p.Lock()
defer p.Unlock()

if p.IsRunning() {
return errors.New("provider is currently running")
}

env := map[string]string{}
if p.username != "" {
Expand All @@ -94,7 +100,7 @@ func (p *rsyncProvider) Start() error {
command = append(command, p.upstreamURL, p.WorkingDir())

p.cmd = newCmdJob(p, command, p.WorkingDir(), env)
if err := p.prepareLogFile(); err != nil {
if err := p.prepareLogFile(false); err != nil {
return err
}

Expand Down
15 changes: 11 additions & 4 deletions worker/two_stage_rsync_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ func (p *twoStageRsyncProvider) Options(stage int) ([]string, error) {
}

func (p *twoStageRsyncProvider) Run() error {
defer p.Wait()
p.Lock()
defer p.Unlock()

if p.IsRunning() {
return errors.New("provider is currently running")
}

env := map[string]string{}
if p.username != "" {
Expand All @@ -129,17 +134,19 @@ func (p *twoStageRsyncProvider) Run() error {
command = append(command, p.upstreamURL, p.WorkingDir())

p.cmd = newCmdJob(p, command, p.WorkingDir(), env)
if err := p.prepareLogFile(); err != nil {
if err := p.prepareLogFile(stage > 1); err != nil {
return err
}

if err = p.cmd.Start(); err != nil {
return err
}
p.isRunning.Store(true)
logger.Debugf("set isRunning to true: %s", p.Name())

err = p.cmd.Wait()
p.isRunning.Store(false)
p.Unlock()
err = p.Wait()
p.Lock()
if err != nil {
return err
}
Expand Down

0 comments on commit 0fdb07d

Please sign in to comment.