diff options
author | Bert JW Regeer <xistence@0x58.com> | 2019-03-28 10:05:17 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-28 10:05:17 -0600 |
commit | 47942f829edff2b1d608cd2d1ec46b2fbc37955f (patch) | |
tree | 5f3bdd8f49474f99eea4a96946f5e34fd74ed40e | |
parent | bdda44a54d9c7dcb60f57685d05b327dc6b6d002 (diff) | |
parent | c501a5bdce0d79af0251dff9952cde6a3fecf3bf (diff) | |
download | waitress-47942f829edff2b1d608cd2d1ec46b2fbc37955f.tar.gz |
Merge pull request #239 from Pylons/close-outbufs
fix potential race condition when a socket closes unexpectedly
-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) |