Skip to content

Commit

Permalink
acquire semaphore in separate goroutine not to stop current goroutine
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Jun 6, 2024
1 parent 8e57053 commit 970cc31
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 60 deletions.
4 changes: 3 additions & 1 deletion process.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ func newConcurrentProcess(par int) *concurrentProcess {
}

func (proc *concurrentProcess) run(eg *errgroup.Group, exec *cmdExecution, callback func([]byte, error) error) {
proc.sema.Acquire(proc.ctx, 1)
proc.wg.Add(1)
eg.Go(func() error {
defer proc.wg.Done()
if err := proc.sema.Acquire(proc.ctx, 1); err != nil {
return nil
}
stdout, err := exec.run()
proc.sema.Release(1)
return callback(stdout, err)
Expand Down
59 changes: 0 additions & 59 deletions process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"runtime"
"strings"
"sync"
"sync/atomic" // Note: atomic.Bool was added at Go 1.19
"testing"
"time"
Expand Down Expand Up @@ -35,64 +34,6 @@ func testSkipIfNoCommand(t *testing.T, p *concurrentProcess, cmd string) *extern
return c
}

func TestProcessRunProcessSerial(t *testing.T) {
p := newConcurrentProcess(1)
ret := []string{}
mu := sync.Mutex{}
starts := []time.Time{}
ends := []time.Time{}
numProcs := 3
echo := testSkipIfNoCommand(t, p, "echo")

for i := 0; i < numProcs; i++ {
in := fmt.Sprintf("message %d", i)
echo.run([]string{in}, "", func(b []byte, err error) error {
mu.Lock()
defer mu.Unlock()

starts = append(starts, time.Now())
defer func() {
ends = append(ends, time.Now())
}()

if err != nil {
t.Error(err)
return err
}

ret = append(ret, string(b))
return nil
})
}

if err := echo.wait(); err != nil {
t.Fatal(err)
}
p.wait()

if len(ret) != numProcs {
t.Fatalf("wanted %d outputs but got %#v", numProcs, ret)
}

// Check error messages
for i := 0; i < numProcs; i++ {
e := fmt.Sprintf("message %d", i)
if !strings.HasPrefix(ret[i], e) {
t.Fatalf("ret[%d] does not start with %q: %#v", i, e, ret)
}
}

starts = starts[1:]
ends = ends[:len(ends)-1]

for i, s := range starts {
e := ends[i]
if s.Before(e) {
t.Errorf("Command #%d started at %s before previous command #%d ends at %s", i+1, s, i, e)
}
}
}

func TestProcessRunConcurrently(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this test is flaky on Windows")
Expand Down

0 comments on commit 970cc31

Please sign in to comment.