From 1d496a030e7e97dcc8de6649b9bba854f307a999 Mon Sep 17 00:00:00 2001 From: Michal Fojtik Date: Wed, 25 Mar 2015 11:42:44 +0100 Subject: [PATCH] Suppress 'use of closed network connection' error in iowatcher Signed-off-by: Michal Fojtik --- pkg/client/request.go | 23 +++------------------ pkg/util/http.go | 46 ++++++++++++++++++++++++++++++++++++++++++ pkg/watch/iowatcher.go | 7 ++++++- 3 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 pkg/util/http.go diff --git a/pkg/client/request.go b/pkg/client/request.go index c55bd82c5d..2b7aa61051 100644 --- a/pkg/client/request.go +++ b/pkg/client/request.go @@ -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. diff --git a/pkg/util/http.go b/pkg/util/http.go new file mode 100644 index 0000000000..c65e54277f --- /dev/null +++ b/pkg/util/http.go @@ -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 +} diff --git a/pkg/watch/iowatcher.go b/pkg/watch/iowatcher.go index e00a6a806c..d268f60dc2 100644 --- a/pkg/watch/iowatcher.go +++ b/pkg/watch/iowatcher.go @@ -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 }