Just posting this for posterity, on something I used to track down
memory leaks related to python closures.
---
generator/Python.ml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/generator/Python.ml b/generator/Python.ml
index 4a96cf6..2ff17dd 100644
--- a/generator/Python.ml
+++ b/generator/Python.ml
@@ -578,9 +578,27 @@ let generate_python_methods_c () =
pr " PyObject *buf; /* Optional pointer to persistent buffer. */\n";
pr "};\n";
pr "\n";
+ pr "static size_t alloc_count;\n";
+ pr "void\n";
+ pr "dump_alloc_count (void)\n";
+ pr "{\n";
+ pr " char *cmd;\n";
+ pr " if (!alloc_count) return;\n";
+ pr " asprintf (&cmd, \"{ echo ' *** alloc_count:%%zu'; cat
/proc/%%d/cmdline; } > /dev/tty\",\n";
+ pr " alloc_count, getpid ());\n";
+ pr " system (cmd);\n";
+ pr " free (cmd);\n";
+ pr "}\n";
+ pr "\n";
pr "static struct user_data *\n";
pr "alloc_user_data (void)\n";
pr "{\n";
+ pr " static bool init;\n";
+ pr " if (!init) {\n";
+ pr " init = true;\n";
+ pr " atexit (dump_alloc_count);\n";
+ pr " }\n";
+ pr " alloc_count++;\n";
pr " struct user_data *data = calloc (1, sizeof *data);\n";
pr " if (data == NULL) {\n";
pr " PyErr_NoMemory ();\n";
@@ -594,6 +612,7 @@ let generate_python_methods_c () =
pr "{\n";
pr " struct user_data *data = user_data;\n";
pr "\n";
+ pr " alloc_count--;\n";
pr " if (data->fn != NULL)\n";
pr " Py_DECREF (data->fn);\n";
pr " if (data->buf != NULL)\n";
--
2.28.0