From 87009ab40a905b6f7d267f71434fda2a32725c57 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 3 Feb 2021 22:36:38 +0100 Subject: [PATCH] Reduce data races (#14549) * Add race conditions into test * Fix Race in GetManager() * DataAsync() use error chan * just log no chan * finish --- modules/git/blob_nogogit.go | 10 ++++++---- modules/process/manager.go | 5 +++-- modules/process/manager_test.go | 9 +++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/git/blob_nogogit.go b/modules/git/blob_nogogit.go index 401b17286..731f7d06e 100644 --- a/modules/git/blob_nogogit.go +++ b/modules/git/blob_nogogit.go @@ -11,6 +11,8 @@ import ( "io" "strconv" "strings" + + gitea_log "code.gitea.io/gitea/modules/log" ) // Blob represents a Git object. @@ -27,13 +29,13 @@ type Blob struct { // Calling the Close function on the result will discard all unread output. func (b *Blob) DataAsync() (io.ReadCloser, error) { stdoutReader, stdoutWriter := io.Pipe() - var err error go func() { stderr := &strings.Builder{} - err = NewCommand("cat-file", "--batch").RunInDirFullPipeline(b.repoPath, stdoutWriter, stderr, strings.NewReader(b.ID.String()+"\n")) + err := NewCommand("cat-file", "--batch").RunInDirFullPipeline(b.repoPath, stdoutWriter, stderr, strings.NewReader(b.ID.String()+"\n")) if err != nil { err = ConcatenateError(err, stderr.String()) + gitea_log.Error("Blob.DataAsync Error: %v", err) _ = stdoutWriter.CloseWithError(err) } else { _ = stdoutWriter.Close() @@ -50,8 +52,8 @@ func (b *Blob) DataAsync() (io.ReadCloser, error) { return &LimitedReaderCloser{ R: bufReader, C: stdoutReader, - N: int64(size), - }, err + N: size, + }, nil } // Size returns the uncompressed size of the blob diff --git a/modules/process/manager.go b/modules/process/manager.go index 27ed1d496..9d57f4eb7 100644 --- a/modules/process/manager.go +++ b/modules/process/manager.go @@ -25,6 +25,7 @@ var ( // ErrExecTimeout represent a timeout error ErrExecTimeout = errors.New("Process execution timeout") manager *Manager + managerInit sync.Once // DefaultContext is the default context to run processing commands in DefaultContext = context.Background() @@ -48,11 +49,11 @@ type Manager struct { // GetManager returns a Manager and initializes one as singleton if there's none yet func GetManager() *Manager { - if manager == nil { + managerInit.Do(func() { manager = &Manager{ processes: make(map[int64]*Process), } - } + }) return manager } diff --git a/modules/process/manager_test.go b/modules/process/manager_test.go index 42f4b0c04..a515fc32c 100644 --- a/modules/process/manager_test.go +++ b/modules/process/manager_test.go @@ -12,6 +12,15 @@ import ( "github.com/stretchr/testify/assert" ) +func TestGetManager(t *testing.T) { + go func() { + // test race protection + _ = GetManager() + }() + pm := GetManager() + assert.NotNil(t, pm) +} + func TestManager_Add(t *testing.T) { pm := Manager{processes: make(map[int64]*Process)}