Skip to content

Commit cd5b785

Browse files
committed
net/rpc: shut down connection if gob has error
The nicest solution would be to buffer the message and only write it if it encodes correctly, but that adds considerable memory and CPU overhead for a very rare condition. Instead, we just shut down the connection if this happens. Fixes golang#7689. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/146670043
1 parent 85cdc49 commit cd5b785

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

src/net/rpc/server.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ type gobServerCodec struct {
395395
dec *gob.Decoder
396396
enc *gob.Encoder
397397
encBuf *bufio.Writer
398+
closed bool
398399
}
399400

400401
func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
@@ -407,15 +408,32 @@ func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
407408

408409
func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
409410
if err = c.enc.Encode(r); err != nil {
411+
if c.encBuf.Flush() == nil {
412+
// Gob couldn't encode the header. Should not happen, so if it does,
413+
// shut down the connection to signal that the connection is broken.
414+
log.Println("rpc: gob error encoding response:", err)
415+
c.Close()
416+
}
410417
return
411418
}
412419
if err = c.enc.Encode(body); err != nil {
420+
if c.encBuf.Flush() == nil {
421+
// Was a gob problem encoding the body but the header has been written.
422+
// Shut down the connection to signal that the connection is broken.
423+
log.Println("rpc: gob error encoding body:", err)
424+
c.Close()
425+
}
413426
return
414427
}
415428
return c.encBuf.Flush()
416429
}
417430

418431
func (c *gobServerCodec) Close() error {
432+
if c.closed {
433+
// Only call c.rwc.Close once; otherwise the semantics are undefined.
434+
return nil
435+
}
436+
c.closed = true
419437
return c.rwc.Close()
420438
}
421439

@@ -426,7 +444,12 @@ func (c *gobServerCodec) Close() error {
426444
// connection. To use an alternate codec, use ServeCodec.
427445
func (server *Server) ServeConn(conn io.ReadWriteCloser) {
428446
buf := bufio.NewWriter(conn)
429-
srv := &gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(buf), buf}
447+
srv := &gobServerCodec{
448+
rwc: conn,
449+
dec: gob.NewDecoder(conn),
450+
enc: gob.NewEncoder(buf),
451+
encBuf: buf,
452+
}
430453
server.ServeCodec(srv)
431454
}
432455

0 commit comments

Comments
 (0)