Skip to content

Commit bed865f

Browse files
egonelbreFontinalis
authored andcommitted
Fix data race in Execute (#459)
* Fix data race in Execute * ensure goroutine doesn't hang * fix rebase error
1 parent 2b0b734 commit bed865f

File tree

3 files changed

+16
-31
lines changed

3 files changed

+16
-31
lines changed

executor.go

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,18 @@ func Execute(p ExecuteParams) (result *Result) {
4646
addExtensionResults(&p, result)
4747
}()
4848

49-
resultChannel := make(chan *Result)
50-
result = &Result{
51-
Extensions: map[string]interface{}{},
52-
}
49+
resultChannel := make(chan *Result, 2)
50+
51+
go func() {
52+
result := &Result{}
5353

54-
go func(out chan<- *Result, done <-chan struct{}) {
5554
defer func() {
5655
if err := recover(); err != nil {
57-
result.AppendErrors(gqlerrors.FormatError(err.(error)))
58-
}
59-
select {
60-
case out <- result:
61-
case <-done:
56+
result.Errors = append(result.Errors, gqlerrors.FormatError(err.(error)))
6257
}
58+
resultChannel <- result
6359
}()
60+
6461
exeContext, err := buildExecutionContext(buildExecutionCtxParams{
6562
Schema: p.Schema,
6663
Root: p.Root,
@@ -72,26 +69,26 @@ func Execute(p ExecuteParams) (result *Result) {
7269
})
7370

7471
if err != nil {
75-
result.AppendErrors(gqlerrors.FormatError(err))
72+
result.Errors = append(result.Errors, gqlerrors.FormatError(err.(error)))
73+
resultChannel <- result
7674
return
7775
}
7876

79-
result = executeOperation(executeOperationParams{
77+
resultChannel <- executeOperation(executeOperationParams{
8078
ExecutionContext: exeContext,
8179
Root: p.Root,
8280
Operation: exeContext.Operation,
8381
})
84-
85-
}(resultChannel, ctx.Done())
82+
}()
8683

8784
select {
8885
case <-ctx.Done():
89-
result.AppendErrors(gqlerrors.FormatError(ctx.Err()))
86+
result := &Result{}
87+
result.Errors = append(result.Errors, gqlerrors.FormatError(ctx.Err()))
88+
return result
9089
case r := <-resultChannel:
91-
result = r
90+
return r
9291
}
93-
94-
return
9592
}
9693

9794
type buildExecutionCtxParams struct {

extensions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func addExtensionResults(p *ExecuteParams, result *Result) {
236236
func() {
237237
defer func() {
238238
if r := recover(); r != nil {
239-
result.AppendErrors(gqlerrors.FormatError(fmt.Errorf("%s.GetResult: %v", ext.Name(), r.(error))))
239+
result.Errors = append(result.Errors, gqlerrors.FormatError(fmt.Errorf("%s.GetResult: %v", ext.Name(), r.(error))))
240240
}
241241
}()
242242
if ext.HasResult() {

types.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package graphql
22

33
import (
4-
"sync"
5-
64
"github.com/graphql-go/graphql/gqlerrors"
75
)
86

@@ -13,19 +11,9 @@ type Result struct {
1311
Data interface{} `json:"data"`
1412
Errors []gqlerrors.FormattedError `json:"errors,omitempty"`
1513
Extensions map[string]interface{} `json:"extensions,omitempty"`
16-
17-
errorsLock sync.Mutex
1814
}
1915

2016
// HasErrors just a simple function to help you decide if the result has errors or not
2117
func (r *Result) HasErrors() bool {
2218
return len(r.Errors) > 0
2319
}
24-
25-
// AppendErrors is the thread-safe way to append error(s) to Result.Errors.
26-
func (r *Result) AppendErrors(errs ...gqlerrors.FormattedError) {
27-
r.errorsLock.Lock()
28-
defer r.errorsLock.Unlock()
29-
30-
r.Errors = append(r.Errors, errs...)
31-
}

0 commit comments

Comments
 (0)