-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hang caused by certain errors in processUnaryRPC
#3713
Labels
Comments
Can you please provide a minimal example or set of instruction that reproduces the error? |
GarrettGutierrez1
assigned GarrettGutierrez1 and smoelius and unassigned GarrettGutierrez1
Jul 16, 2020
Please try this (these instructions are based on: https://grpc.io/docs/languages/go/quickstart/):
package main
import (
"bufio"
"context"
"fmt"
"log"
"net/http"
"os"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
reader := bufio.NewReader(os.Stdin)
req, err := http.ReadRequest(reader)
if err != nil {
fmt.Printf("err = %#v\n", err)
return
}
var resp = responseWriter{header: make(http.Header)}
s.ServeHTTP(resp, req)
fmt.Printf("resp = %#v\n", resp)
}
type responseWriter struct {
header http.Header
statusCode int
}
// Header ...
func (resp responseWriter) Header() http.Header {
return resp.header
}
// Write ...
func (resp responseWriter) Write(data []byte) (int, error) {
return len(data), nil
}
// WriteHeader ...
func (resp responseWriter) WriteHeader(statusCode int) {
resp.statusCode = statusCode
}
// Flush ...
func (resp responseWriter) Flush() {}
var _ http.ResponseWriter = (*responseWriter)(nil)
var _ http.Flusher = (*responseWriter)(nil)
echo '504f5354202f68656c6c6f776f726c642e477265657465722f5361794865
6c6c6f20485454502f322e300d0a486f73743a206c6f63616c686f73740d
0a436f6e74656e742d547970653a206170706c69636174696f6e2f677270
630d0a0d0a' | xxd -r -p | go run main.go The program should hang. Please let me know if this does not work, or if anything is unclear. |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Please see the FAQ in our main README.md, then answer the questions below before
submitting your issue.
What version of gRPC are you using?
v1.27.0
What version of Go are you using (
go version
)?go version go1.14.4 linux/amd64
What operating system (Linux, Windows, …) and version?
Ubuntu 18.04.4 LTS
What did you do?
Fuzzed a gRPC service. The service hangs in this
select
:grpc-go/internal/transport/handler_server.go
Lines 398 to 403 in a89bee7
The reason appears to be that
ok
is false in this conditional inprocessUnaryRPC
:grpc-go/server.go
Lines 990 to 994 in a89bee7
Because
ok
is false,WriteStatus
is not called. So the transportt
is not closed. So the secondselect
condition never fires.On the other hand,
processUnaryRPC
returns with an error, so the firstselect
never fires either.Changing the
ok
took || true
makes the hang go away.Values of
err
that can cause this problem include&errors.errorString{s:"unexpected EOF"}
andtransport.ConnectionError{Desc:"http: unexpected EOF reading trailer", temp:true, err:(*errors.errorString)(0x...)}
.Here is a partial stack trace leading to the
select
:And here is a partial stack trace leading to the conditional:
What did you expect to see?
A response indicating that an error occurred.
What did you see instead?
A hang.
The text was updated successfully, but these errors were encountered: