Skip to content

Commit 9e9d1f4

Browse files
Dean KarnDean Karn
authored andcommitted
Merge pull request #1 from joeybloggs/v1
Fix recovery race condition.
2 parents 6128cf7 + b3a5afb commit 9e9d1f4

File tree

5 files changed

+27
-18
lines changed

5 files changed

+27
-18
lines changed

README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func main() {
8181

8282
for result := range p.Results() {
8383

84-
err, ok := result.(error)
84+
err, ok := result.(*pool.ErrRecovery)
8585
if ok {
8686
// there was some sort of panic that
8787
// was recovered, in this scenario
@@ -139,8 +139,8 @@ func main() {
139139

140140
for result := range p.Results() {
141141
switch result.(type) {
142-
case error:
143-
err := result.(error)
142+
case *pool.ErrRecovery:
143+
err := result.(*pool.ErrRecovery)
144144
// do what you want with error or cancel the pool here p.Cancel()
145145
fmt.Println(err)
146146
default:
@@ -158,11 +158,10 @@ Benchmarks
158158
```go
159159
$ go test -cpu=4 -bench=. -benchmem=true
160160
PASS
161-
BenchmarkSmallRun-4 1 3009120497 ns/op 3360 B/op 65 allocs/op
162-
BenchmarkSmallCancel-4 1 2003173598 ns/op 3696 B/op 81 allocs/op
163-
BenchmarkLargeCancel-4 1 2001222531 ns/op 106784 B/op 3028 allocs/op
164-
BenchmarkOverconsumeLargeRun-4 1 4004509778 ns/op 36528 B/op 661 allocs/op
165-
ok github.com/joeybloggs/pool 14.230s
161+
BenchmarkSmallRun-4 1 3000201819 ns/op 2272 B/op 58 allocs/op
162+
BenchmarkSmallCancel-4 1 2002207036 ns/op 2928 B/op 79 allocs/op
163+
BenchmarkLargeCancel-4 1 2000774880 ns/op 106656 B/op 3026 allocs/op
164+
BenchmarkOverconsumeLargeRun-4 1 4003364358 ns/op 29872 B/op 557 allocs/op
166165
```
167166
To put these benchmarks in perspective:
168167

examples/error/error.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ func main() {
3333

3434
for result := range p.Results() {
3535
switch result.(type) {
36-
case error:
37-
err := result.(error)
36+
case *pool.ErrRecovery:
37+
err := result.(*pool.ErrRecovery)
3838
// do what you want with error or cancel the pool here p.Cancel()
3939
fmt.Println(err)
4040
default:

examples/struct/struct.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func main() {
4343

4444
for result := range p.Results() {
4545

46-
err, ok := result.(error)
46+
err, ok := result.(*pool.ErrRecovery)
4747
if ok {
4848
// there was some sort of panic that
4949
// was recovered, in this scenario

pool.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package pool
22

33
import (
4-
"errors"
54
"fmt"
6-
"log"
75
"reflect"
86
"runtime"
97
"sync"
@@ -13,6 +11,14 @@ const (
1311
errRecoveryString = "recovering from panic: %+v\nStack Trace:\n %s"
1412
)
1513

14+
type ErrRecovery struct {
15+
s string
16+
}
17+
18+
func (e *ErrRecovery) Error() string {
19+
return e.s
20+
}
21+
1622
// Pool Contains all information for the pool instance
1723
type Pool struct {
1824
jobs chan *Job
@@ -65,10 +71,12 @@ func NewPool(consumers int, jobs int) *Pool {
6571
if err := recover(); err != nil {
6672
trace := make([]byte, 1<<16)
6773
n := runtime.Stack(trace, true)
68-
err := errors.New(fmt.Sprintf(errRecoveryString, err, trace[:n]))
69-
log.Println(err)
70-
p.results <- err
74+
rerr := &ErrRecovery{
75+
s: fmt.Sprintf(errRecoveryString, err, trace[:n]),
76+
}
77+
p.results <- rerr
7178
p.Cancel()
79+
p.wg.Done()
7280
}
7381
}(p)
7482

@@ -78,8 +86,9 @@ func NewPool(consumers int, jobs int) *Pool {
7886
if reflect.ValueOf(j).IsNil() {
7987
return
8088
}
81-
defer p.wg.Done()
89+
8290
j.fn(j)
91+
p.wg.Done()
8392
case <-p.cancel:
8493
return
8594
}

pool_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,10 @@ func TestPanicRecovery(t *testing.T) {
132132
var count int
133133

134134
for result := range pool.Results() {
135-
_, ok := result.(error)
135+
err, ok := result.(*ErrRecovery)
136136
if ok {
137137
count++
138+
err.Error()
138139
}
139140
}
140141

0 commit comments

Comments
 (0)