@@ -21,6 +21,7 @@ import (
21
21
"fmt"
22
22
"reflect"
23
23
"runtime"
24
+ "sync"
24
25
"sync/atomic"
25
26
26
27
"github.com/ethereum/go-ethereum/log"
@@ -143,14 +144,15 @@ func hasOption(option CodecOption, options []CodecOption) bool {
143
144
// requests until the codec returns an error when reading a request (in most cases
144
145
// an EOF). It executes requests in parallel when singleShot is false.
145
146
func (s * Server ) serveRequest (codec ServerCodec , singleShot bool , options CodecOption ) error {
147
+ var pend sync.WaitGroup
148
+
146
149
defer func () {
147
150
if err := recover (); err != nil {
148
151
const size = 64 << 10
149
152
buf := make ([]byte , size )
150
153
buf = buf [:runtime .Stack (buf , false )]
151
154
log .Error (fmt .Sprint (string (buf )))
152
155
}
153
-
154
156
s .codecsMu .Lock ()
155
157
s .codecs .Remove (codec )
156
158
s .codecsMu .Unlock ()
@@ -179,8 +181,13 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
179
181
for atomic .LoadInt32 (& s .run ) == 1 {
180
182
reqs , batch , err := s .readRequest (codec )
181
183
if err != nil {
182
- log .Debug (fmt .Sprintf ("read error %v\n " , err ))
183
- codec .Write (codec .CreateErrorResponse (nil , err ))
184
+ // If a parsing error occurred, send an error
185
+ if err .Error () != "EOF" {
186
+ log .Debug (fmt .Sprintf ("read error %v\n " , err ))
187
+ codec .Write (codec .CreateErrorResponse (nil , err ))
188
+ }
189
+ // Error or end of stream, wait for requests and tear down
190
+ pend .Wait ()
184
191
return nil
185
192
}
186
193
@@ -199,20 +206,27 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
199
206
}
200
207
return nil
201
208
}
202
-
203
- if singleShot && batch {
204
- s .execBatch (ctx , codec , reqs )
205
- return nil
206
- } else if singleShot && ! batch {
207
- s .exec (ctx , codec , reqs [0 ])
209
+ // If a single shot request is executing, run and return immediately
210
+ if singleShot {
211
+ if batch {
212
+ s .execBatch (ctx , codec , reqs )
213
+ } else {
214
+ s .exec (ctx , codec , reqs [0 ])
215
+ }
208
216
return nil
209
- } else if ! singleShot && batch {
210
- go s .execBatch (ctx , codec , reqs )
211
- } else {
212
- go s .exec (ctx , codec , reqs [0 ])
213
217
}
214
- }
218
+ // For multi-shot connections, start a goroutine to serve and loop back
219
+ pend .Add (1 )
215
220
221
+ go func (reqs []* serverRequest , batch bool ) {
222
+ defer pend .Done ()
223
+ if batch {
224
+ s .execBatch (ctx , codec , reqs )
225
+ } else {
226
+ s .exec (ctx , codec , reqs [0 ])
227
+ }
228
+ }(reqs , batch )
229
+ }
216
230
return nil
217
231
}
218
232
0 commit comments