Parcourir la source

[1359] plug reference leak in Logger_performOutput(). This is not a complete
fix although it works for almost all cases in practice. I made it first
because it's simple. In subsequent commits I'll revise it to a more complete
fix.

JINMEI Tatuya il y a 13 ans
Parent
commit
3f93372ba9
2 fichiers modifiés avec 26 ajouts et 0 suppressions
  1. 3 0
      src/lib/python/isc/log/log.cc
  2. 23 0
      src/lib/python/isc/log/tests/log_test.py

+ 3 - 0
src/lib/python/isc/log/log.cc

@@ -529,6 +529,7 @@ Logger_performOutput(Function function, PyObject* args, bool dbgLevel) {
             return (NULL);
         }
         string mid(objectToStr(midO, false));
+        Py_DECREF(midO);
         long dbg(0);
         if (dbgLevel) {
             PyObject *dbgO(PySequence_GetItem(args, 0));
@@ -536,6 +537,7 @@ Logger_performOutput(Function function, PyObject* args, bool dbgLevel) {
                 return (NULL);
             }
             dbg = PyLong_AsLong(dbgO);
+            Py_DECREF(dbgO);
             if (PyErr_Occurred()) {
                 return (NULL);
             }
@@ -554,6 +556,7 @@ Logger_performOutput(Function function, PyObject* args, bool dbgLevel) {
                 return (NULL);
             }
             formatter = formatter.arg(objectToStr(param, true));
+            Py_DECREF(param);
         }
         Py_RETURN_NONE;
     }

+ 23 - 0
src/lib/python/isc/log/tests/log_test.py

@@ -17,6 +17,7 @@
 import isc.log
 import unittest
 import json
+import sys
 import bind10_config
 from isc.config.ccsession import path_search
 
@@ -169,5 +170,27 @@ class Logger(unittest.TestCase):
         logger = isc.log.Logger("child")
         self.assertEqual(logger.DBGLVL_COMMAND, 10)
 
+    def test_param_reference(self):
+        """
+        Check whether passing a parameter to a logger causes a reference leak.
+        """
+        MSG = isc.log.create_message('TEST_MESSAGE', '%1')
+        class LogParam:
+            def __str__(self):
+                return 'LogParam'
+        logger = isc.log.Logger("child")
+        param = LogParam()
+        orig_msgrefcnt = sys.getrefcount(param)
+        orig_idrefcnt = sys.getrefcount(MSG)
+        logger.info(MSG, param);
+        self.assertEqual(sys.getrefcount(MSG), orig_idrefcnt)
+        self.assertEqual(sys.getrefcount(param), orig_msgrefcnt)
+
+        # intentionally pass an invalid type for debug level.  It will
+        # result in TypeError.  The passed object still shouldn't leak a
+        # reference.
+        self.assertRaises(TypeError, logger.debug, param, MSG, param)
+        self.assertEqual(sys.getrefcount(param), orig_msgrefcnt)
+
 if __name__ == '__main__':
     unittest.main()