Suppress 'use of closed network connection' error in iowatcher

Signed-off-by: Michal Fojtik <mfojtik@redhat.com>
pull/6/head
Michal Fojtik 2015-03-25 11:42:44 +01:00
parent 159a58ddfb
commit 1d496a030e
3 changed files with 55 additions and 21 deletions

View File

@ -511,7 +511,9 @@ func (r *Request) Watch() (watch.Interface, error) {
}
resp, err := client.Do(req)
if err != nil {
if isProbableEOF(err) {
// The watch stream mechanism handles many common partial data errors, so closed
// connections can be retried in many cases.
if util.IsProbableEOF(err) {
return watch.NewEmptyWatch(), nil
}
return nil, err
@ -525,25 +527,6 @@ func (r *Request) Watch() (watch.Interface, error) {
return watch.NewStreamWatcher(watchjson.NewDecoder(resp.Body, r.codec)), nil
}
// isProbableEOF returns true if the given error resembles a connection termination
// scenario that would justify assuming that the watch is empty. The watch stream
// mechanism handles many common partial data errors, so closed connections can be
// retried in many cases.
func isProbableEOF(err error) bool {
if uerr, ok := err.(*url.Error); ok {
err = uerr.Err
}
switch {
case err == io.EOF:
return true
case err.Error() == "http: can't write HTTP request on broken connection":
return true
case strings.Contains(err.Error(), "connection reset by peer"):
return true
}
return false
}
// Stream formats and executes the request, and offers streaming of the response.
// Returns io.ReadCloser which could be used for streaming of the response, or an error
// Any non-2xx http status code causes an error. If we get a non-2xx code, we try to convert the body into an APIStatus object.

46
pkg/util/http.go Normal file
View File

@ -0,0 +1,46 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"io"
"net/url"
"strings"
)
// IsProbableEOF returns true if the given error resembles a connection termination
// scenario that would justify assuming that the watch is empty.
// These errors are what the Go http stack returns back to us which are general
// connection closure errors (strongly correlated) and callers that need to
// differentiate probable errors in connection behavior between normal "this is
// disconnected" should use the method.
func IsProbableEOF(err error) bool {
if uerr, ok := err.(*url.Error); ok {
err = uerr.Err
}
switch {
case err == io.EOF:
return true
case err.Error() == "http: can't write HTTP request on broken connection":
return true
case strings.Contains(err.Error(), "connection reset by peer"):
return true
case strings.Contains(strings.ToLower(err.Error()), "use of closed network connection"):
return true
}
return false
}

View File

@ -101,7 +101,12 @@ func (sw *StreamWatcher) receive() {
case io.ErrUnexpectedEOF:
glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
default:
glog.Errorf("Unable to decode an event from the watch stream: %v", err)
msg := "Unable to decode an event from the watch stream: %v"
if util.IsProbableEOF(err) {
glog.V(5).Infof(msg, err)
} else {
glog.Errorf(msg, err)
}
}
return
}