Fix PyUnknownFields memory leak (#7928)
Properly release internal data structure on deallocation. Fix #7301
This commit is contained in:
parent
492858351c
commit
99149badc0
@ -39,6 +39,12 @@ try:
|
||||
import unittest2 as unittest #PY26
|
||||
except ImportError:
|
||||
import unittest
|
||||
import sys
|
||||
try:
|
||||
import tracemalloc
|
||||
except ImportError:
|
||||
# Requires python 3.4+
|
||||
pass
|
||||
from google.protobuf import map_unittest_pb2
|
||||
from google.protobuf import unittest_mset_pb2
|
||||
from google.protobuf import unittest_pb2
|
||||
@ -312,6 +318,24 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
|
||||
self.assertIn('UnknownFields does not exist.',
|
||||
str(context.exception))
|
||||
|
||||
@unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4),
|
||||
'tracemalloc requires python 3.4+')
|
||||
def testUnknownFieldsNoMemoryLeak(self):
|
||||
# Call to UnknownFields must not leak memory
|
||||
nb_leaks = 1234
|
||||
def leaking_function():
|
||||
for _ in range(nb_leaks):
|
||||
self.empty_message.UnknownFields()
|
||||
tracemalloc.start()
|
||||
snapshot1 = tracemalloc.take_snapshot()
|
||||
leaking_function()
|
||||
snapshot2 = tracemalloc.take_snapshot()
|
||||
top_stats = snapshot2.compare_to(snapshot1, 'lineno')
|
||||
tracemalloc.stop()
|
||||
# There's no easy way to look for a precise leak source.
|
||||
# Rely on a "marker" count value while checking allocated memory.
|
||||
self.assertEqual([], [x for x in top_stats if x.count_diff == nb_leaks])
|
||||
|
||||
def testSubUnknownFields(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
message.optionalgroup.a = 123
|
||||
|
@ -142,6 +142,7 @@ static void Dealloc(PyObject* pself) {
|
||||
}
|
||||
Py_CLEAR(self->parent);
|
||||
self->~PyUnknownFields();
|
||||
Py_TYPE(pself)->tp_free(pself);
|
||||
}
|
||||
|
||||
static PySequenceMethods SqMethods = {
|
||||
|
Loading…
Reference in New Issue
Block a user