Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit aa92ace

Browse files
authored
Merge pull request #94 from juanjux/fix/leak2
Memleaks and other fixes
2 parents 6419d41 + 432f0db commit aa92ace

File tree

5 files changed

+56
-36
lines changed

5 files changed

+56
-36
lines changed

bblfsh/memtracker.cc

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,20 @@ void MemTracker::TrackItem(PyObject *o)
1616
}
1717
}
1818

19-
void MemTracker::TrackStr(PyObject *o)
20-
{
21-
if (inFilter_) {
22-
filterStrAllocs_.push_back(o);
23-
} else {
24-
iterStrAllocs_[currentIter_].push_back(o);
25-
}
26-
}
27-
2819
void MemTracker::DisposeMem()
2920
{
3021
if (inFilter_) {
31-
for (auto &i : filterStrAllocs_) {
32-
Py_XDECREF(i);
33-
i = nullptr;
34-
}
3522
for (auto &i : filterItemAllocs_) {
36-
Py_XDECREF(i);
37-
i = nullptr;
23+
Py_CLEAR(i);
3824
}
25+
filterItemAllocs_.clear();
26+
filterItemAllocs_.shrink_to_fit();
3927
} else {
40-
for (auto &i : iterStrAllocs_[currentIter_]) {
41-
Py_XDECREF(i);
42-
i = nullptr;
43-
}
4428
for (auto &i : iterItemAllocs_[currentIter_]) {
45-
Py_XDECREF(i);
46-
i = nullptr;
29+
Py_CLEAR(i);
4730
}
31+
iterItemAllocs_[currentIter_].clear();
32+
iterItemAllocs_.erase(currentIter_);
4833
ClearCurrentIterator();
4934
}
5035
}

bblfsh/memtracker.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ class MemTracker {
1111
bool inFilter_ = false;
1212

1313
std::unordered_map<UastIterator*, std::vector<PyObject*>> iterItemAllocs_;
14-
std::unordered_map<UastIterator*, std::vector<PyObject*>> iterStrAllocs_;
1514
std::vector<PyObject*> filterItemAllocs_;
16-
std::vector<PyObject*> filterStrAllocs_;
1715

1816
public:
1917
UastIterator *CurrentIterator();
@@ -23,6 +21,5 @@ class MemTracker {
2321
void EnterFilter();
2422
void ExitFilter();
2523
void TrackItem(PyObject *ref);
26-
void TrackStr(PyObject *ref);
2724
void DisposeMem();
2825
};

bblfsh/pyuast.cc

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
MemTracker memTracker;
1212

1313
// Used to store references to the Pyobjects instanced in String() and
14-
// ItemAt() methods. Those can't be DECREF'ed to 0 because libuast uses the
14+
// ItemAt() methods. Those can't be DECREF'ed to 0 because libuast uses them
1515
// so we pass ownership to these lists and free them at the end of filter()
1616

1717
static PyObject *Attribute(const void *node, const char *prop) {
@@ -29,7 +29,7 @@ static const char *String(const void *node, const char *prop) {
2929
PyObject *o = Attribute(node, prop);
3030
if (o != NULL) {
3131
retval = PyUnicode_AsUTF8(o);
32-
memTracker.TrackStr(o);
32+
memTracker.TrackItem(o);
3333
}
3434
return retval;
3535
}
@@ -39,6 +39,7 @@ static size_t Size(const void *node, const char *prop) {
3939
PyObject *o = Attribute(node, prop);
4040
if (o != NULL) {
4141
retval = PySequence_Size(o);
42+
Py_DECREF(o);
4243
}
4344

4445
return retval;
@@ -69,21 +70,37 @@ static size_t ChildrenSize(const void *node) {
6970

7071
static void *ChildAt(const void *node, int index) {
7172
PyObject *children = AttributeValue(node, "children");
72-
return children ? ItemAt(children, index) : NULL;
73+
void *retval = nullptr;
74+
if (children) {
75+
retval = ItemAt(children, index);
76+
Py_DECREF(children);
77+
}
78+
79+
return retval;
7380
}
7481

7582
static size_t RolesSize(const void *node) {
7683
return Size(node, "roles");
7784
}
7885

7986
static uint16_t RoleAt(const void *node, int index) {
87+
uint16_t retval = 0;
8088
PyObject *roles = AttributeValue(node, "roles");
81-
return roles ? (uint16_t)PyLong_AsUnsignedLong(ItemAt(roles, index)) : 0;
89+
if (roles) {
90+
retval = (uint16_t)PyLong_AsUnsignedLong(ItemAt(roles, index));
91+
Py_DECREF(roles);
92+
}
93+
return retval;
8294
}
8395

8496
static size_t PropertiesSize(const void *node) {
97+
size_t retval = 0;
8598
PyObject *properties = AttributeValue(node, "properties");
86-
return properties ? PyMapping_Size(properties) : 0;
99+
if (properties) {
100+
retval = PyMapping_Size(properties);
101+
Py_DECREF(properties);
102+
}
103+
return retval;
87104
}
88105

89106
static const char *PropertyKeyAt(const void *node, int index) {
@@ -94,6 +111,7 @@ static const char *PropertyKeyAt(const void *node, int index) {
94111

95112
const char *retval = NULL;
96113
PyObject *keys = PyMapping_Keys(properties);
114+
Py_DECREF(properties);
97115
if (keys != NULL) {
98116
retval = PyUnicode_AsUTF8(ItemAt(keys, index));
99117
Py_DECREF(keys);
@@ -103,7 +121,11 @@ static const char *PropertyKeyAt(const void *node, int index) {
103121

104122
static const char *PropertyValueAt(const void *node, int index) {
105123
PyObject *properties = AttributeValue(node, "properties");
106-
if (!properties || !PyMapping_Check(properties)) {
124+
if (!properties)
125+
return NULL;
126+
127+
if (!PyMapping_Check(properties)) {
128+
Py_DECREF(properties);
107129
return NULL;
108130
}
109131

@@ -113,6 +135,7 @@ static const char *PropertyValueAt(const void *node, int index) {
113135
retval = PyUnicode_AsUTF8(ItemAt(values, index));
114136
Py_DECREF(values);
115137
}
138+
Py_DECREF(properties);
116139
return retval;
117140
}
118141

@@ -123,7 +146,14 @@ static uint32_t PositionValue(const void* node, const char *prop, const char *fi
123146
}
124147

125148
PyObject *offset = AttributeValue(position, field);
126-
return offset ? (uint32_t)PyLong_AsUnsignedLong(offset) : 0;
149+
Py_DECREF(position);
150+
uint32_t retval = 0;
151+
152+
if (offset) {
153+
retval = (uint32_t)PyLong_AsUnsignedLong(offset);
154+
Py_DECREF(offset);
155+
}
156+
return retval;
127157
}
128158

129159
/////////////////////////////////////
@@ -337,6 +367,7 @@ static PyObject *PyFilter(PyObject *self, PyObject *args)
337367
cleanupFilter();
338368
return NULL;
339369
}
370+
340371
size_t len = NodesSize(nodes);
341372
PyObject *list = PyList_New(len);
342373

bblfsh/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def testManyFilters(self):
252252

253253
import resource
254254
before = resource.getrusage(resource.RUSAGE_SELF)
255-
for _ in range(100):
255+
for _ in range(500):
256256
filter(root, "//*[@roleIdentifier]")
257257
after = resource.getrusage(resource.RUSAGE_SELF)
258258

setup.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import os
2-
import subprocess
32
import sys
43

54
from setuptools import setup, find_packages, Extension
65
from setuptools.command.build_ext import build_ext
76

8-
VERSION = "2.9.6"
7+
VERSION = "2.9.10"
98
LIBUAST_VERSION = "v1.9.1"
109
SDK_VERSION = "v1.8.0"
1110
SDK_MAJOR = SDK_VERSION.split('.')[0]
1211
PYTHON = "python3"
1312

13+
# For debugging libuast-client interactions, set to True in production!
14+
GET_LIBUAST = True
15+
if not GET_LIBUAST:
16+
print('WARNING: not retrieving libuast, using local version')
17+
1418
os.environ["CC"] = "g++"
1519
os.environ["CXX"] = "g++"
1620
libraries = ['xml2']
@@ -69,6 +73,9 @@ def createInits():
6973

7074

7175
def getLibuast():
76+
if not GET_LIBUAST:
77+
return
78+
7279
runc("curl -SL https://github.com/bblfsh/libuast/releases/download/{LIBUAST_VERSION}/"
7380
"libuast-{LIBUAST_VERSION}.tar.gz | tar xz")
7481
runc("mv libuast-{LIBUAST_VERSION} libuast")
@@ -108,7 +115,8 @@ def clean():
108115
runc("rm -rf gopkg.in")
109116
runc("rm -rf bblfsh/github")
110117
runc("rm -rf bblfsh/gopkg")
111-
runc("rm -rf bblfsh/libuast")
118+
if GET_LIBUAST:
119+
runc("rm -rf bblfsh/libuast")
112120

113121

114122
def main():
@@ -153,7 +161,6 @@ def main():
153161
"Intended Audience :: Developers",
154162
"License :: OSI Approved :: Apache Software License",
155163
"Operating System :: POSIX",
156-
"Programming Language :: Python :: 2.7",
157164
"Programming Language :: Python :: 3.4",
158165
"Programming Language :: Python :: 3.5",
159166
"Programming Language :: Python :: 3.6",

0 commit comments

Comments
 (0)