error propagation in gob/encoder.

R=rsc
CC=golang-dev
https://golang.org/cl/165048
This commit is contained in:
Rob Pike 2009-12-03 17:12:57 -08:00
parent bc3e34759c
commit fcc4dd6d64

View File

@ -213,7 +213,14 @@ func NewEncoder(w io.Writer) *Encoder {
} }
func (enc *Encoder) badType(rt reflect.Type) { 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. // Send the data item preceded by a unsigned count of its length.
@ -232,7 +239,10 @@ func (enc *Encoder) send() {
// Now the data. // Now the data.
enc.state.b.Read(enc.buf[countLen:total]); enc.state.b.Read(enc.buf[countLen:total]);
// Write the data. // 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) { func (enc *Encoder) sendType(origt reflect.Type) {
@ -270,7 +280,7 @@ func (enc *Encoder) sendType(origt reflect.Type) {
info, err := getTypeInfo(rt); info, err := getTypeInfo(rt);
typeLock.Unlock(); typeLock.Unlock();
if err != nil { if err != nil {
enc.state.err = err; enc.setError(err);
return; return;
} }
// Send the pair (-id, type) // Send the pair (-id, type)
@ -279,6 +289,9 @@ func (enc *Encoder) sendType(origt reflect.Type) {
// Type: // Type:
encode(enc.state.b, info.wire); encode(enc.state.b, info.wire);
enc.send(); enc.send();
if enc.state.err != nil {
return
}
// Remember we've sent this type. // Remember we've sent this type.
enc.sent[rt] = info.id; 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, // Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first. // guaranteeing that all necessary type information has been transmitted first.
func (enc *Encoder) Encode(e interface{}) os.Error { func (enc *Encoder) Encode(e interface{}) os.Error {
if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 { // Make sure we're single-threaded through here, so multiple
panicln("Encoder: buffer not empty") // goroutines can share an encoder.
} enc.mutex.Lock();
defer enc.mutex.Unlock();
enc.state.err = nil;
rt, _ := indirect(reflect.Typeof(e)); rt, _ := indirect(reflect.Typeof(e));
// Must be a struct // Must be a struct
if _, ok := rt.(*reflect.StructType); !ok { if _, ok := rt.(*reflect.StructType); !ok {
@ -309,10 +325,11 @@ func (enc *Encoder) Encode(e interface{}) os.Error {
return enc.state.err; return enc.state.err;
} }
// Sanity check only: encoder should never come in with data present.
// Make sure we're single-threaded through here. if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 {
enc.mutex.Lock(); enc.state.err = os.ErrorString("encoder: buffer not empty");
defer enc.mutex.Unlock(); return enc.state.err;
}
// Make sure the type is known to the other side. // Make sure the type is known to the other side.
// First, have we already sent this type? // First, have we already sent this type?
@ -320,7 +337,6 @@ func (enc *Encoder) Encode(e interface{}) os.Error {
// No, so send it. // No, so send it.
enc.sendType(rt); enc.sendType(rt);
if enc.state.err != nil { if enc.state.err != nil {
enc.state.b.Reset();
enc.countState.b.Reset(); enc.countState.b.Reset();
return enc.state.err; return enc.state.err;
} }