Skip to content

Commit db7e335

Browse files
authored
[mypyc] Add cleanup at end of init function (python#10590)
This frees everything created in the generated initialization function so that we don't leak memory in the case of an error during initialization, as mentioned in python#10586 (review).
1 parent fe157d4 commit db7e335

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

mypyc/codegen/emitmodule.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
878878
declaration = 'PyObject *CPyInit_{}(void)'.format(exported_name(module_name))
879879
emitter.emit_lines(declaration,
880880
'{')
881+
emitter.emit_line('PyObject* modname = NULL;')
881882
# Store the module reference in a static and return it when necessary.
882883
# This is separate from the *global* reference to the module that will
883884
# be populated when it is imported by a compiled module. We want that
@@ -894,7 +895,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
894895
'if (unlikely({} == NULL))'.format(module_static),
895896
' goto fail;')
896897
emitter.emit_line(
897-
'PyObject *modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format(
898+
'modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format(
898899
module_static))
899900

900901
module_globals = emitter.static_name('globals', module_name)
@@ -903,9 +904,11 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
903904
' goto fail;')
904905

905906
# HACK: Manually instantiate generated classes here
907+
type_structs = [] # type: List[str]
906908
for cl in module.classes:
909+
type_struct = emitter.type_struct_name(cl)
910+
type_structs.append(type_struct)
907911
if cl.is_generated:
908-
type_struct = emitter.type_struct_name(cl)
909912
emitter.emit_lines(
910913
'{t} = (PyTypeObject *)CPyType_FromTemplate('
911914
'(PyObject *){t}_template, NULL, modname);'
@@ -922,8 +925,18 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
922925

923926
emitter.emit_line('return {};'.format(module_static))
924927
emitter.emit_lines('fail:',
925-
'{} = NULL;'.format(module_static),
926-
'return NULL;')
928+
'Py_CLEAR({});'.format(module_static),
929+
'Py_CLEAR(modname);')
930+
for name, typ in module.final_names:
931+
static_name = emitter.static_name(name, module_name)
932+
emitter.emit_dec_ref(static_name, typ, is_xdec=True)
933+
undef = emitter.c_undefined_value(typ)
934+
emitter.emit_line('{} = {};'.format(static_name, undef))
935+
# the type objects returned from CPyType_FromTemplate are all new references
936+
# so we have to decref them
937+
for t in type_structs:
938+
emitter.emit_line('Py_CLEAR({});'.format(t))
939+
emitter.emit_line('return NULL;')
927940
emitter.emit_line('}')
928941

929942
def generate_top_level_call(self, module: ModuleIR, emitter: Emitter) -> None:

0 commit comments

Comments
 (0)