Skip to content

Commit c1bfe0f

Browse files
committed
Solve more memory issues in py_loader.
1 parent 18da8ad commit c1bfe0f

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

source/loaders/py_loader/include/py_loader/py_loader_func.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PY_LOADER_NO_EXPORT int py_loader_impl_func_type_init(void);
3535

3636
PY_LOADER_NO_EXPORT int py_loader_impl_func_check(PyObject *obj);
3737

38+
PY_LOADER_NO_EXPORT void *py_loader_impl_func_copy(PyObject *obj);
39+
3840
PY_LOADER_NO_EXPORT PyObject *py_loader_impl_func_new(loader_impl impl, loader_impl_py py_impl, value callback);
3941

4042
#ifdef __cplusplus

source/loaders/py_loader/source/py_loader_func.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ int py_loader_impl_func_check(PyObject *obj)
187187
return PyObject_TypeCheck(obj, &py_loader_impl_func_type);
188188
}
189189

190+
void *py_loader_impl_func_copy(PyObject *obj)
191+
{
192+
struct py_loader_impl_func_obj *wrapped = (struct py_loader_impl_func_obj *)obj;
193+
194+
if (wrapped == NULL)
195+
{
196+
return NULL;
197+
}
198+
199+
return metacall_value_copy(wrapped->callback);
200+
}
201+
190202
PyObject *py_loader_impl_func_new(loader_impl impl, loader_impl_py py_impl, value callback)
191203
{
192204
struct py_loader_impl_func_obj *wrapped = PyObject_New(struct py_loader_impl_func_obj, &py_loader_impl_func_type);

source/loaders/py_loader/source/py_loader_impl.c

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,49 +1064,38 @@ value py_loader_impl_capi_to_value(loader_impl impl, PyObject *obj, type_id id)
10641064
}
10651065
else if (id == TYPE_FUNCTION)
10661066
{
1067-
/* Check if we are passing our own hook to the callback */
1068-
#if 0 /* TODO: This optimization does not work properly (check metacall-node-port-test for implementing it) */
1069-
if (PyCFunction_Check(obj) && PyCFunction_GET_FUNCTION(obj) == py_loader_impl_function_type_invoke)
1067+
/* Check if we are passing our own hook to the callback */
1068+
if (py_loader_impl_func_check(obj))
10701069
{
1071-
PyObject *invoke_state_capsule = PyCFunction_GET_SELF(obj);
1072-
1073-
loader_impl_py_function_type_invoke_state invoke_state = PyCapsule_GetPointer(invoke_state_capsule, NULL);
1074-
1075-
value callback = value_type_copy(invoke_state->callback);
1076-
1077-
/* Move finalizers */
1078-
value_move(callback, invoke_state->callback);
1079-
1080-
Py_DecRef(invoke_state_capsule);
1081-
1082-
return callback;
1070+
return py_loader_impl_func_copy(obj);
10831071
}
1084-
#endif
1072+
else
1073+
{
1074+
loader_impl_py py_impl = loader_impl_get(impl);
1075+
size_t args_count = py_loader_impl_discover_callable_args_count(py_impl, obj);
1076+
loader_impl_py_function py_func = malloc(sizeof(struct loader_impl_py_function_type));
1077+
function f = NULL;
10851078

1086-
loader_impl_py py_impl = loader_impl_get(impl);
1087-
size_t args_count = py_loader_impl_discover_callable_args_count(py_impl, obj);
1088-
loader_impl_py_function py_func = malloc(sizeof(struct loader_impl_py_function_type));
1089-
function f = NULL;
1079+
if (py_func == NULL)
1080+
{
1081+
return NULL;
1082+
}
10901083

1091-
if (py_func == NULL)
1092-
{
1093-
return NULL;
1094-
}
1084+
Py_IncRef(obj);
1085+
py_func->func = obj;
1086+
py_func->impl = impl;
10951087

1096-
Py_IncRef(obj);
1097-
py_func->func = obj;
1098-
py_func->impl = impl;
1088+
f = function_create(NULL, args_count, py_func, &function_py_singleton);
10991089

1100-
f = function_create(NULL, args_count, py_func, &function_py_singleton);
1090+
if (py_loader_impl_discover_func(impl, obj, f) != 0)
1091+
{
1092+
function_destroy(f);
11011093

1102-
if (py_loader_impl_discover_func(impl, obj, f) != 0)
1103-
{
1104-
function_destroy(f);
1094+
return NULL;
1095+
}
11051096

1106-
return NULL;
1097+
return value_create_function(f);
11071098
}
1108-
1109-
return value_create_function(f);
11101099
}
11111100
else if (id == TYPE_NULL)
11121101
{
@@ -3797,6 +3786,20 @@ int py_loader_impl_discover_module(loader_impl impl, PyObject *module, context c
37973786
return 1;
37983787
}
37993788
}
3789+
else if (py_loader_impl_func_check(module_dict_val))
3790+
{
3791+
/* This special case for our own functions skips the introspection phase */
3792+
const char *func_name = PyUnicode_AsUTF8(module_dict_key);
3793+
scope sp = context_scope(ctx);
3794+
value v = py_loader_impl_func_copy(module_dict_val);
3795+
3796+
if (scope_define(sp, func_name, v) != 0)
3797+
{
3798+
py_loader_thread_release();
3799+
value_type_destroy(v);
3800+
return 1;
3801+
}
3802+
}
38003803
else if (PyCallable_Check(module_dict_val))
38013804
{
38023805
const char *func_name = PyUnicode_AsUTF8(module_dict_key);

0 commit comments

Comments
 (0)