Skip to content

Commit

Permalink
Server shouldn't Fatalf in case it fails to encode. (#1251)
Browse files Browse the repository at this point in the history
* Server shouldn't Fatalf in case it fails to encode.

* golint

* post-review update
  • Loading branch information
MakMukhi committed Jun 1, 2017
1 parent 1e47334 commit d5bc85c
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 13 deletions.
2 changes: 1 addition & 1 deletion call.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func sendRequest(ctx context.Context, dopts dialOptions, compressor Compressor,
}
outBuf, err := encode(dopts.codec, args, compressor, cbuf, outPayload)
if err != nil {
return Errorf(codes.Internal, "grpc: %v", err)
return err
}
if c.maxSendMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)")
Expand Down
4 changes: 2 additions & 2 deletions rpc_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayl
// TODO(zhaoq): optimize to reduce memory alloc and copying.
b, err = c.Marshal(msg)
if err != nil {
return nil, err
return nil, Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
}
if outPayload != nil {
outPayload.Payload = msg
Expand All @@ -324,7 +324,7 @@ func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayl
}
if cp != nil {
if err := cp.Do(cbuf, b); err != nil {
return nil, err
return nil, Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error())
}
b = cbuf.Bytes()
}
Expand Down
10 changes: 2 additions & 8 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,14 +664,8 @@ func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Str
}
p, err := encode(s.opts.codec, msg, cp, cbuf, outPayload)
if err != nil {
// This typically indicates a fatal issue (e.g., memory
// corruption or hardware faults) the application program
// cannot handle.
//
// TODO(zhaoq): There exist other options also such as only closing the
// faulty stream locally and remotely (Other streams can keep going). Find
// the optimal option.
grpclog.Fatalf("grpc: Server failed to encode response %v", err)
grpclog.Println("grpc: server failed to encode response: ", err)
return err
}
if len(p) > s.opts.maxSendMessageSize {
return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(p), s.opts.maxSendMessageSize)
Expand Down
3 changes: 1 addition & 2 deletions stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
}
}()
if err != nil {
return Errorf(codes.Internal, "grpc: %v", err)
return err
}
if cs.c.maxSendMessageSize == nil {
return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)")
Expand Down Expand Up @@ -606,7 +606,6 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
}
}()
if err != nil {
err = Errorf(codes.Internal, "grpc: %v", err)
return err
}
if len(out) > ss.maxSendMessageSize {
Expand Down
44 changes: 44 additions & 0 deletions test/end2end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ type test struct {
clientInitialWindowSize int32
clientInitialConnWindowSize int32
perRPCCreds credentials.PerRPCCredentials
customCodec grpc.Codec

// srv and srvAddr are set once startServer is called.
srv *grpc.Server
Expand Down Expand Up @@ -4795,3 +4796,46 @@ func testPerRPCCredentialsViaDialOptionsAndCallOptions(t *testing.T, e env) {
t.Fatalf("Test failed. Reason: %v", err)
}
}

type errCodec struct {
noError bool
}

func (c *errCodec) Marshal(v interface{}) ([]byte, error) {
if c.noError {
return []byte{}, nil
}
return nil, fmt.Errorf("3987^12 + 4365^12 = 4472^12")
}

func (c *errCodec) Unmarshal(data []byte, v interface{}) error {
return nil
}

func (c *errCodec) String() string {
return "Fermat's near-miss."
}

func TestEncodeDoesntPanic(t *testing.T) {
defer leakCheck(t)()
for _, e := range listTestEnv() {
testEncodeDoesntPanic(t, e)
}
}

func testEncodeDoesntPanic(t *testing.T, e env) {
te := newTest(t, e)
erc := &errCodec{}
te.customCodec = erc
te.startServer(&testServer{security: e.security})
defer te.tearDown()
te.customCodec = nil
tc := testpb.NewTestServiceClient(te.clientConn())
// Failure case, should not panic.
tc.EmptyCall(context.Background(), &testpb.Empty{})
erc.noError = true
// Passing case.
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
t.Fatalf("EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
}

0 comments on commit d5bc85c

Please sign in to comment.