diff options
author | Rob Pike <r@golang.org> | 2009-12-03 17:12:57 -0800 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2009-12-03 17:12:57 -0800 |
commit | fcc4dd6d64817fd19bdd48f45a786a8532953f03 (patch) | |
tree | 979a7b4fb9ab61748a6d83879275102dc7661b41 | |
parent | bc3e34759c7d3f6625df9dd5ded40f6404c91324 (diff) | |
download | go-fcc4dd6d64817fd19bdd48f45a786a8532953f03.tar.gz go-fcc4dd6d64817fd19bdd48f45a786a8532953f03.zip |
error propagation in gob/encoder.
R=rsc
CC=golang-dev
https://golang.org/cl/165048
-rw-r--r-- | src/pkg/gob/encoder.go | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go index 548326c704..3be455210e 100644 --- a/src/pkg/gob/encoder.go +++ b/src/pkg/gob/encoder.go @@ -213,7 +213,14 @@ func NewEncoder(w io.Writer) *Encoder { } func (enc *Encoder) badType(rt reflect.Type) { - enc.state.err = os.ErrorString("gob: can't encode type " + rt.String()) + enc.setError(os.ErrorString("gob: can't encode type " + rt.String())) +} + +func (enc *Encoder) setError(err os.Error) { + if enc.state.err == nil { // remember the first. + enc.state.err = err + } + enc.state.b.Reset(); } // Send the data item preceded by a unsigned count of its length. @@ -232,7 +239,10 @@ func (enc *Encoder) send() { // Now the data. enc.state.b.Read(enc.buf[countLen:total]); // Write the data. - enc.w.Write(enc.buf[0:total]); + _, err := enc.w.Write(enc.buf[0:total]); + if err != nil { + enc.setError(err) + } } func (enc *Encoder) sendType(origt reflect.Type) { @@ -270,7 +280,7 @@ func (enc *Encoder) sendType(origt reflect.Type) { info, err := getTypeInfo(rt); typeLock.Unlock(); if err != nil { - enc.state.err = err; + enc.setError(err); return; } // Send the pair (-id, type) @@ -279,6 +289,9 @@ func (enc *Encoder) sendType(origt reflect.Type) { // Type: encode(enc.state.b, info.wire); enc.send(); + if enc.state.err != nil { + return + } // Remember we've sent this type. enc.sent[rt] = info.id; @@ -299,9 +312,12 @@ func (enc *Encoder) sendType(origt reflect.Type) { // Encode transmits the data item represented by the empty interface value, // guaranteeing that all necessary type information has been transmitted first. func (enc *Encoder) Encode(e interface{}) os.Error { - if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 { - panicln("Encoder: buffer not empty") - } + // Make sure we're single-threaded through here, so multiple + // goroutines can share an encoder. + enc.mutex.Lock(); + defer enc.mutex.Unlock(); + + enc.state.err = nil; rt, _ := indirect(reflect.Typeof(e)); // Must be a struct if _, ok := rt.(*reflect.StructType); !ok { @@ -309,10 +325,11 @@ func (enc *Encoder) Encode(e interface{}) os.Error { return enc.state.err; } - - // Make sure we're single-threaded through here. - enc.mutex.Lock(); - defer enc.mutex.Unlock(); + // Sanity check only: encoder should never come in with data present. + if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 { + enc.state.err = os.ErrorString("encoder: buffer not empty"); + return enc.state.err; + } // Make sure the type is known to the other side. // First, have we already sent this type? @@ -320,7 +337,6 @@ func (enc *Encoder) Encode(e interface{}) os.Error { // No, so send it. enc.sendType(rt); if enc.state.err != nil { - enc.state.b.Reset(); enc.countState.b.Reset(); return enc.state.err; } |