diff options
author | Michael Merickel <michael@merickel.org> | 2019-03-27 23:38:16 -0500 |
---|---|---|
committer | Michael Merickel <michael@merickel.org> | 2019-03-27 23:43:24 -0500 |
commit | c501a5bdce0d79af0251dff9952cde6a3fecf3bf (patch) | |
tree | 5f3bdd8f49474f99eea4a96946f5e34fd74ed40e | |
parent | bdda44a54d9c7dcb60f57685d05b327dc6b6d002 (diff) | |
download | waitress-c501a5bdce0d79af0251dff9952cde6a3fecf3bf.tar.gz |
fix potential race condition when a socket closes unexpectedlyclose-outbufs
-rw-r--r-- | CHANGES.txt | 5 | ||||
-rw-r--r-- | waitress/channel.py | 21 |
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) |