rpcServer: ensure we don't get blocked on bidirectional payment errors

This commit fixes a potential issue in the bidirectional sendPayment
case, where multiple goroutines could be sending on an errChan with
buffer 1. Instead we select on default as well, as it is enough to
handle the first error that was received.
This commit is contained in:
Johan T. Halseth 2018-11-02 11:33:01 +01:00
parent f20f29696a
commit c49ba0c5cb
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

View File

@ -3707,10 +3707,12 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
errChan <- nil errChan <- nil
return return
} else if err != nil { } else if err != nil {
rpcsLog.Errorf("Failed receiving from "+
"stream: %v", err)
select { select {
case errChan <- err: case errChan <- err:
case <-reqQuit: default:
return
} }
return return
} }
@ -3728,18 +3730,22 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
PaymentError: err.Error(), PaymentError: err.Error(),
PaymentHash: payIntent.rHash[:], PaymentHash: payIntent.rHash[:],
}); err != nil { }); err != nil {
rpcsLog.Errorf("Failed "+
"sending on "+
"stream: %v", err)
select { select {
case errChan <- err: case errChan <- err:
case <-reqQuit: default:
return
} }
return
} }
continue continue
} }
// If the payment was well formed, then we'll // If the payment was well formed, then we'll
// send to the dispatch goroutine, or exit, // send to the dispatch goroutine, or exit,
// which ever comes first // which ever comes first.
select { select {
case payChan <- &payIntent: case payChan <- &payIntent:
case <-reqQuit: case <-reqQuit:
@ -3751,6 +3757,9 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
for { for {
select { select {
// If we encounter and error either during sending or
// receiving, we return directly, closing the stream.
case err := <-errChan: case err := <-errChan:
return err return err
@ -3779,7 +3788,13 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
// payment, then we'll return the error to the // payment, then we'll return the error to the
// user, and terminate. // user, and terminate.
case saveErr != nil: case saveErr != nil:
errChan <- saveErr rpcsLog.Errorf("Failed dispatching "+
"payment intent: %v", saveErr)
select {
case errChan <- saveErr:
default:
}
return return
// If we receive payment error than, instead of // If we receive payment error than, instead of
@ -3791,7 +3806,14 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
PaymentHash: payIntent.rHash[:], PaymentHash: payIntent.rHash[:],
}) })
if err != nil { if err != nil {
errChan <- err rpcsLog.Errorf("Failed "+
"sending error "+
"response: %v", err)
select {
case errChan <- err:
default:
}
} }
return return
} }
@ -3811,7 +3833,13 @@ func (r *rpcServer) sendPayment(stream *paymentStream) error {
PaymentRoute: marshalledRouted, PaymentRoute: marshalledRouted,
}) })
if err != nil { if err != nil {
errChan <- err rpcsLog.Errorf("Failed sending "+
"response: %v", err)
select {
case errChan <- err:
default:
}
return return
} }
}() }()