summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvery Pennarun <apenwarr@gmail.com>2010-10-01 18:22:36 -0700
committerAvery Pennarun <apenwarr@gmail.com>2010-10-01 18:22:36 -0700
commitf6e6515a3cc3cf183efa5de3dc330a5ffa9d5032 (patch)
tree90a3af2caa7ae6552ca6862b9fc730c9f97e5a32
parent84376284db6199d4928797e5e8be4182449120f2 (diff)
Fix busy-waiting in two situations:
- If you tried to connect to a server that didn't exist, then disconnected the client during the 60-second connection timeout, the server would busy wait for 60 seconds. - If you connected to a server and then sent data, but then the server disconnected before reading all your data, the server would busy wait. (example: yes | telnet servername 80)
-rw-r--r--ssnet.py31
1 files changed, 26 insertions, 5 deletions
diff --git a/ssnet.py b/ssnet.py
index b8daf7d..7040f16 100644
--- a/ssnet.py
+++ b/ssnet.py
@@ -86,21 +86,30 @@ class SockWrapper:
debug1('%r: error was: %r\n' % (self, self.exc))
def __repr__(self):
- return 'SW:%s' % (self.peername,)
+ if self.rsock == self.wsock:
+ fds = '#%d' % self.rsock.fileno()
+ else:
+ fds = '#%d,%d' % (self.rsock.fileno(), self.wsock.fileno())
+ return 'SW%s:%s' % (fds, self.peername)
def seterr(self, e):
if not self.exc:
self.exc = e
def try_connect(self):
+ if self.connect_to and self.shut_write:
+ self.noread()
+ self.connect_to = None
if not self.connect_to:
return # already connected
self.rsock.setblocking(False)
+ debug3('%r: trying connect to %r\n' % (self, self.connect_to))
try:
self.rsock.connect(self.connect_to)
# connected successfully (Linux)
self.connect_to = None
except socket.error, e:
+ debug3('%r: connect result: %r\n' % (self, e))
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
pass # not connected yet
elif e.args[0] == errno.EISCONN:
@@ -176,7 +185,7 @@ class SockWrapper:
wrote = outwrap.write(self.buf[0])
self.buf[0] = self.buf[0][wrote:]
while self.buf and not self.buf[0]:
- self.buf[0:1] = []
+ self.buf.pop(0)
if not self.buf and self.shut_read:
outwrap.nowrite()
@@ -234,6 +243,12 @@ class Proxy(Handler):
self.wrap2.fill()
self.wrap1.copy_to(self.wrap2)
self.wrap2.copy_to(self.wrap1)
+ if self.wrap1.buf and self.wrap2.shut_write:
+ self.wrap1.buf = []
+ self.wrap1.noread()
+ if self.wrap2.buf and self.wrap1.shut_write:
+ self.wrap2.buf = []
+ self.wrap2.noread()
if (self.wrap1.shut_read and self.wrap2.shut_read and
not self.wrap1.buf and not self.wrap2.buf):
self.ok = False
@@ -457,6 +472,12 @@ def runonce(handlers, mux):
debug2(' Ready: %d r=%r w=%r x=%r\n'
% (len(handlers), _fds(r), _fds(w), _fds(x)))
ready = r+w+x
- for s in handlers:
- if list_contains_any(s.socks, ready):
- s.callback()
+ did = {}
+ for h in handlers:
+ for s in h.socks:
+ if s in ready:
+ h.callback()
+ did[s] = 1
+ for s in ready:
+ if not s in did:
+ raise Fatal('socket %r was not used by any handler' % s)