From 1e7c250a424db833944336d95988b8a81a3de725 Mon Sep 17 00:00:00 2001 From: Bob McElrath Date: Mon, 23 Jan 2017 14:53:55 -0500 Subject: [PATCH 1/3] Use epoll to detect bitcoind closing the connection --- bitcoin/rpc.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/bitcoin/rpc.py b/bitcoin/rpc.py index 0677c67b..446b6d42 100644 --- a/bitcoin/rpc.py +++ b/bitcoin/rpc.py @@ -37,6 +37,11 @@ import os import platform import sys +import socket +from socket import MSG_PEEK, MSG_DONTWAIT +import select +from select import EPOLLIN, EPOLLHUP + try: import urllib.parse as urlparse except ImportError: @@ -183,11 +188,19 @@ def __init__(self, self.__conn = httplib.HTTPConnection(self.__url.hostname, port=port, timeout=timeout) + self.ep = None def _call(self, service_name, *args): self.__id_count += 1 + if self.ep: + for (fd, ev) in self.ep.poll(0): + if ev & EPOLLHUP or (ev & EPOLLIN and \ + b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): + self.__conn.close() + self.ep.close() + self.ep = None postdata = json.dumps({'version': '1.1', 'method': service_name, 'params': args, @@ -197,6 +210,9 @@ def _call(self, service_name, *args): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) + if not self.ep: + self.ep = select.epoll() + self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) response = self._get_response() if response['error'] is not None: @@ -210,11 +226,21 @@ def _call(self, service_name, *args): def _batch(self, rpc_call_list): postdata = json.dumps(list(rpc_call_list)) + if self.ep: + for (fd, ev) in self.ep.poll(0): + if ev & EPOLLHUP or (ev & EPOLLIN and \ + b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): + self.__conn.close() + self.ep.close() + self.ep = None self.__conn.request('POST', self.__url.path, postdata, {'Host': self.__url.hostname, 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) + if not self.ep: + self.ep = select.epoll() + self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) return self._get_response() From 16e84b9271afda6d588b7e04ff5b139770ccb620 Mon Sep 17 00:00:00 2001 From: Stefan Le Noach Date: Thu, 2 Feb 2017 11:09:46 -0500 Subject: [PATCH 2/3] epoll fix --- bitcoin/rpc.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/bitcoin/rpc.py b/bitcoin/rpc.py index 446b6d42..b03967eb 100644 --- a/bitcoin/rpc.py +++ b/bitcoin/rpc.py @@ -38,9 +38,15 @@ import platform import sys import socket -from socket import MSG_PEEK, MSG_DONTWAIT -import select -from select import EPOLLIN, EPOLLHUP + +try: + from socket import MSG_PEEK, MSG_DONTWAIT + import select + from select import EPOLLIN, EPOLLHUP + EPOLL = True +except ImportError: + EPOLL = False + try: import urllib.parse as urlparse @@ -194,7 +200,7 @@ def __init__(self, def _call(self, service_name, *args): self.__id_count += 1 - if self.ep: + if self.ep and EPOLL: for (fd, ev) in self.ep.poll(0): if ev & EPOLLHUP or (ev & EPOLLIN and \ b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): @@ -210,7 +216,7 @@ def _call(self, service_name, *args): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) - if not self.ep: + if not self.ep and EPOLL: self.ep = select.epoll() self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) @@ -226,7 +232,7 @@ def _call(self, service_name, *args): def _batch(self, rpc_call_list): postdata = json.dumps(list(rpc_call_list)) - if self.ep: + if self.ep and EPOLL: for (fd, ev) in self.ep.poll(0): if ev & EPOLLHUP or (ev & EPOLLIN and \ b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): @@ -238,7 +244,7 @@ def _batch(self, rpc_call_list): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) - if not self.ep: + if not self.ep and EPOLL: self.ep = select.epoll() self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) From 995d7e0e8337d21195fe1d162b92b7a03bfabeba Mon Sep 17 00:00:00 2001 From: Stefan Le Noach Date: Thu, 2 Feb 2017 11:21:28 -0500 Subject: [PATCH 3/3] fix --- bitcoin/rpc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bitcoin/rpc.py b/bitcoin/rpc.py index b03967eb..dac89ea4 100644 --- a/bitcoin/rpc.py +++ b/bitcoin/rpc.py @@ -200,7 +200,7 @@ def __init__(self, def _call(self, service_name, *args): self.__id_count += 1 - if self.ep and EPOLL: + if EPOLL and self.ep: for (fd, ev) in self.ep.poll(0): if ev & EPOLLHUP or (ev & EPOLLIN and \ b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): @@ -216,7 +216,7 @@ def _call(self, service_name, *args): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) - if not self.ep and EPOLL: + if EPOLL and not self.ep: self.ep = select.epoll() self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) @@ -232,7 +232,7 @@ def _call(self, service_name, *args): def _batch(self, rpc_call_list): postdata = json.dumps(list(rpc_call_list)) - if self.ep and EPOLL: + if EPOLL and self.ep: for (fd, ev) in self.ep.poll(0): if ev & EPOLLHUP or (ev & EPOLLIN and \ b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): @@ -244,7 +244,7 @@ def _batch(self, rpc_call_list): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) - if not self.ep and EPOLL: + if EPOLL and not self.ep: self.ep = select.epoll() self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP)