summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2019-03-27 23:38:16 -0500
committerMichael Merickel <michael@merickel.org>2019-03-27 23:43:24 -0500
commitc501a5bdce0d79af0251dff9952cde6a3fecf3bf (patch)
tree5f3bdd8f49474f99eea4a96946f5e34fd74ed40e
parentbdda44a54d9c7dcb60f57685d05b327dc6b6d002 (diff)
downloadwaitress-c501a5bdce0d79af0251dff9952cde6a3fecf3bf.tar.gz
fix potential race condition when a socket closes unexpectedlyclose-outbufs
-rw-r--r--CHANGES.txt5
-rw-r--r--waitress/channel.py21
2 files changed, 19 insertions, 7 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 3521864..1291f41 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,11 @@ Bugfixes
response when a client hangs up.
See https://github.com/Pylons/waitress/pull/238
+- When a client closes a socket unexpectedly there was potential for memory
+ leaks in which data was written to the buffers after they were closed,
+ causing them to reopen.
+ See https://github.com/Pylons/waitress/pull/239
+
1.2.1 (2019-01-25)
------------------
diff --git a/waitress/channel.py b/waitress/channel.py
index 6416725..6b80919 100644
--- a/waitress/channel.py
+++ b/waitress/channel.py
@@ -275,13 +275,16 @@ class HTTPChannel(wasyncore.dispatcher, object):
return False
def handle_close(self):
- for outbuf in self.outbufs:
- try:
- outbuf.close()
- except:
- self.logger.exception(
- 'Unknown exception while trying to close outbuf')
- self.connected = False
+ # avoid closing the outbufs while a task is potentially adding data
+ # to them in write_soon
+ with self.outbuf_lock:
+ for outbuf in self.outbufs:
+ try:
+ outbuf.close()
+ except:
+ self.logger.exception(
+ 'Unknown exception while trying to close outbuf')
+ self.connected = False
wasyncore.dispatcher.close(self)
def add_channel(self, map=None):
@@ -316,6 +319,10 @@ class HTTPChannel(wasyncore.dispatcher, object):
# the async mainloop might be popping data off outbuf; we can
# block here waiting for it because we're in a task thread
with self.outbuf_lock:
+ # check again after acquiring the lock to ensure we the
+ # outbufs are not closed
+ if not self.connected: # pragma: no cover
+ raise ClientDisconnected
if data.__class__ is ReadOnlyFileBasedBuffer:
# they used wsgi.file_wrapper
self.outbufs.append(data)