From 84524454d0ba77d299741c47bd0f5841ac3f66ce Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Aug 2017 18:12:58 +0200 Subject: [PATCH] bpo-31247: xmlrpc.server: break reference cycle (#3166) xmlrpc.server now explicitly breaks reference cycles when using sys.exc_info() in code handling exceptions. --- Lib/xmlrpc/server.py | 36 ++++++++++++------- .../2017-08-21-17-50-27.bpo-31247.8S3zJp.rst | 2 ++ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-08-21-17-50-27.bpo-31247.8S3zJp.rst diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index bb86fe6872a..88d0eec786b 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -270,10 +270,14 @@ class SimpleXMLRPCDispatcher: except: # report exception back to server exc_type, exc_value, exc_tb = sys.exc_info() - response = dumps( - Fault(1, "%s:%s" % (exc_type, exc_value)), - encoding=self.encoding, allow_none=self.allow_none, - ) + try: + response = dumps( + Fault(1, "%s:%s" % (exc_type, exc_value)), + encoding=self.encoding, allow_none=self.allow_none, + ) + finally: + # Break reference cycle + exc_type = exc_value = exc_tb = None return response.encode(self.encoding, 'xmlcharrefreplace') @@ -365,10 +369,14 @@ class SimpleXMLRPCDispatcher: ) except: exc_type, exc_value, exc_tb = sys.exc_info() - results.append( - {'faultCode' : 1, - 'faultString' : "%s:%s" % (exc_type, exc_value)} - ) + try: + results.append( + {'faultCode' : 1, + 'faultString' : "%s:%s" % (exc_type, exc_value)} + ) + finally: + # Break reference cycle + exc_type = exc_value = exc_tb = None return results def _dispatch(self, method, params): @@ -630,10 +638,14 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): # (each dispatcher should have handled their own # exceptions) exc_type, exc_value = sys.exc_info()[:2] - response = dumps( - Fault(1, "%s:%s" % (exc_type, exc_value)), - encoding=self.encoding, allow_none=self.allow_none) - response = response.encode(self.encoding, 'xmlcharrefreplace') + try: + response = dumps( + Fault(1, "%s:%s" % (exc_type, exc_value)), + encoding=self.encoding, allow_none=self.allow_none) + response = response.encode(self.encoding, 'xmlcharrefreplace') + finally: + # Break reference cycle + exc_type = exc_value = None return response class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): diff --git a/Misc/NEWS.d/next/Library/2017-08-21-17-50-27.bpo-31247.8S3zJp.rst b/Misc/NEWS.d/next/Library/2017-08-21-17-50-27.bpo-31247.8S3zJp.rst new file mode 100644 index 00000000000..6879384eb8f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-08-21-17-50-27.bpo-31247.8S3zJp.rst @@ -0,0 +1,2 @@ +xmlrpc.server now explicitly breaks reference cycles when using +sys.exc_info() in code handling exceptions.