Asyncore fixes
- better handling of WSA* checks on non-windows systems - handle EBADF on Windows/select - better timeouts / loop lengths in main asyncore loop and spawning new connections - remove InvThread prints
This commit is contained in:
parent
74f1a74a8c
commit
a5c1b0c529
|
@ -102,12 +102,6 @@ def _fixSocket():
|
|||
if sys.platform.startswith('linux'):
|
||||
socket.SO_BINDTODEVICE = 25
|
||||
|
||||
if not sys.platform.startswith('win'):
|
||||
errno.WSAEWOULDBLOCK = errno.EWOULDBLOCK
|
||||
errno.WSAENETUNREACH = errno.ENETUNREACH
|
||||
errno.WSAECONNREFUSED = errno.ECONNREFUSED
|
||||
errno.WSAEHOSTUNREACH = errno.EHOSTUNREACH
|
||||
|
||||
if not sys.platform.startswith('win'):
|
||||
return
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
|||
errorcode
|
||||
try:
|
||||
from errno import WSAEWOULDBLOCK
|
||||
except:
|
||||
pass
|
||||
except (ImportError, AttributeError):
|
||||
WSAEWOULDBLOCK = EWOULDBLOCK
|
||||
|
||||
from ssl import SSLError, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
|
||||
|
||||
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
||||
|
@ -199,6 +200,9 @@ def select_poller(timeout=0.0, map=None):
|
|||
r, w, e = select.select(r, w, e, timeout)
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except socket.error as err:
|
||||
if err.args[0] in (EBADF):
|
||||
return
|
||||
|
||||
for fd in random.sample(r, len(r)):
|
||||
obj = map.get(fd)
|
||||
|
@ -369,12 +373,18 @@ def loop(timeout=30.0, use_poll=False, map=None, count=None,
|
|||
# then poll
|
||||
poller(timeout, map)
|
||||
else:
|
||||
timeout /= count
|
||||
if timeout == 0:
|
||||
deadline = 0
|
||||
else:
|
||||
deadline = time.time() + timeout
|
||||
while map and count > 0:
|
||||
# fill buckets first
|
||||
update_sent()
|
||||
update_received()
|
||||
poller(timeout, map)
|
||||
subtimeout = deadline - time.time()
|
||||
if subtimeout <= 0:
|
||||
break
|
||||
poller(subtimeout, map)
|
||||
# then poll
|
||||
count = count - 1
|
||||
|
||||
|
@ -555,10 +565,8 @@ class dispatcher:
|
|||
else:
|
||||
raise
|
||||
except socket.error as why:
|
||||
if why.args[0] in (EAGAIN, EWOULDBLOCK) or \
|
||||
(sys.platform.startswith('win') and \
|
||||
err.errno == WSAEWOULDBLOCK):
|
||||
return 0
|
||||
if why.args[0] in (EAGAIN, EWOULDBLOCK, WSAEWOULDBLOCK):
|
||||
return 0
|
||||
elif why.args[0] in _DISCONNECTED:
|
||||
self.handle_close()
|
||||
return 0
|
||||
|
@ -582,10 +590,8 @@ class dispatcher:
|
|||
raise
|
||||
except socket.error as why:
|
||||
# winsock sometimes raises ENOTCONN
|
||||
if why.args[0] in (EAGAIN, EWOULDBLOCK) or \
|
||||
(sys.platform.startswith('win') and \
|
||||
err.errno == WSAEWOULDBLOCK):
|
||||
return b''
|
||||
if why.args[0] in (EAGAIN, EWOULDBLOCK, WSAEWOULDBLOCK):
|
||||
return b''
|
||||
if why.args[0] in _DISCONNECTED:
|
||||
self.handle_close()
|
||||
return b''
|
||||
|
|
|
@ -19,6 +19,7 @@ import state
|
|||
|
||||
@Singleton
|
||||
class BMConnectionPool(object):
|
||||
|
||||
def __init__(self):
|
||||
asyncore.set_rates(
|
||||
BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate") * 1024,
|
||||
|
@ -28,6 +29,8 @@ class BMConnectionPool(object):
|
|||
self.listeningSockets = {}
|
||||
self.udpSockets = {}
|
||||
self.streams = []
|
||||
self.lastSpawned = 0
|
||||
self.spawnWait = 0.3
|
||||
|
||||
self.bootstrapped = False
|
||||
|
||||
|
@ -146,6 +149,8 @@ class BMConnectionPool(object):
|
|||
if e.errno == errno.ENETUNREACH:
|
||||
continue
|
||||
|
||||
self.lastSpawned = time.time()
|
||||
|
||||
if acceptConnections and len(self.listeningSockets) == 0:
|
||||
self.startListening()
|
||||
logger.info('Listening for incoming connections.')
|
||||
|
@ -169,7 +174,10 @@ class BMConnectionPool(object):
|
|||
|
||||
# while len(asyncore.socket_map) > 0 and state.shutdown == 0:
|
||||
# print "loop, state = %s" % (proxy.state)
|
||||
asyncore.loop(timeout=2.0, count=1)
|
||||
loopTime = float(self.spawnWait)
|
||||
if self.lastSpawned < time.time() - self.spawnWait:
|
||||
loopTime = 1.0
|
||||
asyncore.loop(timeout=loopTime, count=10)
|
||||
|
||||
for i in self.inboundConnections.values() + self.outboundConnections.values():
|
||||
minTx = time.time() - 20
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from binascii import hexlify
|
||||
import collections
|
||||
import Queue
|
||||
import random
|
||||
|
@ -35,6 +36,7 @@ class InvThread(threading.Thread, StoppableThread):
|
|||
try:
|
||||
(stream, hash) = invQueue.get(False)
|
||||
self.holdHash (stream, hash)
|
||||
#print "Holding hash %i, %s" % (stream, hexlify(hash))
|
||||
except Queue.Empty:
|
||||
break
|
||||
|
||||
|
@ -50,6 +52,7 @@ class InvThread(threading.Thread, StoppableThread):
|
|||
except KeyError:
|
||||
continue
|
||||
if len(hashes) > 0:
|
||||
#print "sending inv of %i" % (len(hashes))
|
||||
connection.writeQueue.put(protocol.CreatePacket('inv', addresses.encodeVarint(len(hashes)) + b"".join(hashes)))
|
||||
self.collectionOfInvs[iterator] = {}
|
||||
iterator += 1
|
||||
|
|
Reference in New Issue
Block a user