From 5edd8deb637b45a711b0d1e8261a4c8cd3ea736e Mon Sep 17 00:00:00 2001
From: Jack Robison <jackrobison@lbry.io>
Date: Mon, 18 Jun 2018 14:54:16 -0400
Subject: [PATCH 1/2] fix blob client protocol not tearing itself down properly
 after a failure

---
 CHANGELOG.md                          |  1 +
 lbrynet/core/client/BlobRequester.py  |  7 +++----
 lbrynet/core/client/ClientProtocol.py | 15 ++++++++-------
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ccdbb4fe..eacafb2ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ at anytime.
   * reflector server incorrectly responding as if it has all the blobs for a stream that was only partially uploaded to it
   * `publish` raising a database error when updating a claim that we don't have a file for (https://github.com/lbryio/lbry/issues/1165)
   * approximations of bid when cast from float to Decimal during publish
+  * blob client protocol not tearing itself down properly after a failure (https://github.com/lbryio/lbry/issues/950)
 
 ### Deprecated
   *
diff --git a/lbrynet/core/client/BlobRequester.py b/lbrynet/core/client/BlobRequester.py
index 42db42423..852942138 100644
--- a/lbrynet/core/client/BlobRequester.py
+++ b/lbrynet/core/client/BlobRequester.py
@@ -227,7 +227,7 @@ class RequestHelper(object):
 
     def _request_failed(self, reason, request_type):
         if reason.check(DownloadCanceledError, RequestCanceledError, ConnectionAborted,
-                        ConnectionClosedBeforeResponseError):
+                        ConnectionClosedBeforeResponseError, ValueError):
             return
         if reason.check(NoResponseError):
             self.requestor._incompatible_peers.append(self.peer)
@@ -238,8 +238,6 @@ class RequestHelper(object):
             self.peer.update_score(-10.0)
         else:
             self.peer.update_score(-2.0)
-        if reason.check(ConnectionClosedBeforeResponseError):
-            return
         return reason
 
     def get_rate(self):
@@ -289,7 +287,8 @@ def _handle_incoming_blob(response_dict, peer, request):
 
 
 def _handle_download_error(err, peer, blob_to_download):
-    if not err.check(DownloadCanceledError, PriceDisagreementError, RequestCanceledError):
+    if not err.check(DownloadCanceledError, PriceDisagreementError, RequestCanceledError,
+                     ConnectionClosedBeforeResponseError):
         log.warning("An error occurred while downloading %s from %s. Error: %s",
                     blob_to_download.blob_hash, str(peer), err.getTraceback())
     if err.check(PriceDisagreementError):
diff --git a/lbrynet/core/client/ClientProtocol.py b/lbrynet/core/client/ClientProtocol.py
index 72024f7c7..64aab1e28 100644
--- a/lbrynet/core/client/ClientProtocol.py
+++ b/lbrynet/core/client/ClientProtocol.py
@@ -105,7 +105,7 @@ class ClientProtocol(Protocol, TimeoutMixin):
                                                         self._handle_response_error)
             return d
         else:
-            raise ValueError("There is already a blob download request active")
+            return defer.fail(ValueError("There is already a blob download request active"))
 
     def cancel_requests(self):
         self.connection_closing = True
@@ -125,9 +125,8 @@ class ClientProtocol(Protocol, TimeoutMixin):
     ######### Internal request handling #########
 
     def _handle_request_error(self, err):
-        log.error(
-            "An unexpected error occurred creating or sending a request to %s. Error message: %s",
-            self.peer, err.getTraceback())
+        log.error("An unexpected error occurred creating or sending a request to %s. %s: %s",
+                  self.peer, err.type, err.message)
         self.transport.loseConnection()
 
     def _ask_for_request(self):
@@ -176,7 +175,8 @@ class ClientProtocol(Protocol, TimeoutMixin):
 
     def _handle_response_error(self, err):
         # If an error gets to this point, log it and kill the connection.
-        if err.check(DownloadCanceledError, RequestCanceledError, error.ConnectionAborted):
+        if err.check(DownloadCanceledError, RequestCanceledError, error.ConnectionAborted,
+                     ConnectionClosedBeforeResponseError):
             # TODO: (wish-list) it seems silly to close the connection over this, and it shouldn't
             # TODO: always be this way. it's done this way now because the client has no other way
             # TODO: of telling the server it wants the download to stop. It would be great if the
@@ -184,14 +184,15 @@ class ClientProtocol(Protocol, TimeoutMixin):
             log.info("Closing the connection to %s because the download of blob %s was canceled",
                      self.peer, self._blob_download_request.blob)
             result = None
-        elif not err.check(MisbehavingPeerError, ConnectionClosedBeforeResponseError):
+        elif err.check(MisbehavingPeerError):
             log.warning("The connection to %s is closing due to: %s", self.peer, err)
             result = err
         else:
             log.error("The connection to %s is closing due to an unexpected error: %s",
                       self.peer, err)
             result = err
-
+        self._blob_download_request = None
+        self._downloading_blob = False
         self.transport.loseConnection()
         return result
 

From 1615ca0ebd0c0770e4686851edd1a0e474428498 Mon Sep 17 00:00:00 2001
From: Jack Robison <jackrobison@lbry.io>
Date: Mon, 18 Jun 2018 16:45:42 -0400
Subject: [PATCH 2/2] fix appveyor

---
 .appveyor.yml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.appveyor.yml b/.appveyor.yml
index a1d4dc448..fdb1fad9a 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,5 +1,9 @@
 version: 1.0.{build}
 
+branches:
+  only:
+    master
+
 environment:
   GH_TOKEN:
     secure: LiI5jyuHUw6XbH4kC3gP1HX4P/v4rwD/gCNtaFhQu2AvJz1/1wALkp5ECnIxRySN