Merge sudo_module_register_loghandler and sudo_module_set_default_loghandler.
We now create the LogHandler class for each interpreter in python_plugin_init() instead of just once in sudo_module_init(). This fixes the crash seen in Py_EndInterpreter() with Python 3.12 and significantly reduces the number of leaked objects tracked by MemorySanitizer.
This commit is contained in:
@@ -27,8 +27,6 @@
|
|||||||
# define PyObject_CallNoArgs(_o) PyObject_CallObject((_o), NULL)
|
# define PyObject_CallNoArgs(_o) PyObject_CallObject((_o), NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static PyObject *sudo_type_LogHandler;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_debug_plugin(unsigned int log_level, const char *log_message)
|
_debug_plugin(unsigned int log_level, const char *log_message)
|
||||||
{
|
{
|
||||||
@@ -127,74 +125,58 @@ static PyMethodDef _sudo_LogHandler_class_methods[] =
|
|||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function registers sudo.LogHandler class
|
// This function creates the sudo.LogHandler class and adds it
|
||||||
|
// to the root logger.
|
||||||
int
|
int
|
||||||
sudo_module_register_loghandler(PyObject *py_module)
|
sudo_module_set_default_loghandler()
|
||||||
{
|
{
|
||||||
debug_decl(sudo_module_register_loghandler, PYTHON_DEBUG_INTERNAL);
|
debug_decl(sudo_module_register_loghandler, PYTHON_DEBUG_INTERNAL);
|
||||||
|
|
||||||
PyObject *py_logging_module = NULL, *py_streamhandler = NULL;
|
PyObject *py_sudo, *py_logging_module = NULL, *py_logger = NULL,
|
||||||
|
*py_streamhandler = NULL, *py_class = NULL,
|
||||||
|
*py_loghandler = NULL, *py_result = NULL;
|
||||||
|
|
||||||
|
py_sudo = PyImport_ImportModule("sudo");
|
||||||
|
if (py_sudo == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
py_logging_module = PyImport_ImportModule("logging");
|
py_logging_module = PyImport_ImportModule("logging");
|
||||||
if (py_logging_module == NULL)
|
if (py_logging_module == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
// Get the root logger which all loggers descend from.
|
||||||
|
py_logger = PyObject_CallMethod(py_logging_module, "getLogger", NULL);
|
||||||
|
if (py_logger == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
py_streamhandler = PyObject_GetAttrString(py_logging_module, "StreamHandler");
|
py_streamhandler = PyObject_GetAttrString(py_logging_module, "StreamHandler");
|
||||||
if (py_streamhandler == NULL)
|
if (py_streamhandler == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
sudo_type_LogHandler = sudo_module_create_class("sudo.LogHandler",
|
// Create our own handler that is a sub-class of StreamHandler
|
||||||
|
py_class = sudo_module_create_class("sudo.LogHandler",
|
||||||
_sudo_LogHandler_class_methods, py_streamhandler);
|
_sudo_LogHandler_class_methods, py_streamhandler);
|
||||||
if (sudo_type_LogHandler == NULL)
|
if (py_class == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (PyModule_AddObject(py_module, "LogHandler", sudo_type_LogHandler) < 0) {
|
// PyModule_AddObject steals a reference to py_class on success
|
||||||
Py_CLEAR(sudo_type_LogHandler);
|
if (PyModule_AddObject(py_sudo, "LogHandler", py_class) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
Py_INCREF(py_class);
|
||||||
|
|
||||||
// PyModule_AddObject steals a reference to sudo_type_LogHandler on success
|
py_loghandler = PyObject_CallNoArgs(py_class);
|
||||||
Py_INCREF(sudo_type_LogHandler);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
Py_CLEAR(py_streamhandler);
|
|
||||||
Py_CLEAR(py_logging_module);
|
|
||||||
debug_return_int(PyErr_Occurred() ? SUDO_RC_ERROR : SUDO_RC_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This sets sudo.LogHandler as the default log handler:
|
|
||||||
// logging.getLogger().addHandler(sudo.LogHandler())
|
|
||||||
int
|
|
||||||
sudo_module_set_default_loghandler(void)
|
|
||||||
{
|
|
||||||
debug_decl(sudo_module_set_default_loghandler, PYTHON_DEBUG_INTERNAL);
|
|
||||||
|
|
||||||
PyObject *py_loghandler = NULL, *py_logging_module = NULL,
|
|
||||||
*py_logger = NULL, *py_result = NULL;
|
|
||||||
|
|
||||||
py_loghandler = PyObject_CallNoArgs(sudo_type_LogHandler);
|
|
||||||
if (py_loghandler == NULL)
|
if (py_loghandler == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
py_logging_module = PyImport_ImportModule("logging");
|
|
||||||
if (py_logging_module == NULL)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
py_logger = PyObject_CallMethod(py_logging_module, "getLogger", NULL);
|
|
||||||
if (py_logger == NULL)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
py_result = PyObject_CallMethod(py_logger, "addHandler", "O", py_loghandler);
|
py_result = PyObject_CallMethod(py_logger, "addHandler", "O", py_loghandler);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
Py_CLEAR(py_result);
|
Py_CLEAR(py_result);
|
||||||
|
Py_CLEAR(py_loghandler);
|
||||||
|
Py_CLEAR(py_class);
|
||||||
|
Py_CLEAR(py_streamhandler);
|
||||||
Py_CLEAR(py_logger);
|
Py_CLEAR(py_logger);
|
||||||
Py_CLEAR(py_logging_module);
|
Py_CLEAR(py_logging_module);
|
||||||
#if 0
|
Py_CLEAR(py_sudo);
|
||||||
// XXX - If we don't leak py_loghandler here we may get a crash in
|
|
||||||
// Py_EndInterpreter() on Python 3.12.
|
|
||||||
Py_CLEAR(py_loghandler);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debug_return_int(PyErr_Occurred() ? SUDO_RC_ERROR : SUDO_RC_OK);
|
debug_return_int(PyErr_Occurred() ? SUDO_RC_ERROR : SUDO_RC_OK);
|
||||||
}
|
}
|
||||||
|
@@ -542,8 +542,9 @@ python_plugin_init(struct PluginContext *plugin_ctx, char * const plugin_options
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sudo_module_set_default_loghandler() < 0)
|
if (sudo_module_set_default_loghandler() != SUDO_RC_OK) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (_python_plugin_set_path(plugin_ctx, _lookup_value(plugin_options, "ModulePath")) != SUDO_RC_OK) {
|
if (_python_plugin_set_path(plugin_ctx, _lookup_value(plugin_options, "ModulePath")) != SUDO_RC_OK) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@@ -595,9 +595,6 @@ sudo_module_init(void)
|
|||||||
if (sudo_module_register_baseplugin(py_module) != SUDO_RC_OK)
|
if (sudo_module_register_baseplugin(py_module) != SUDO_RC_OK)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (sudo_module_register_loghandler(py_module) != SUDO_RC_OK)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
Py_CLEAR(py_module);
|
Py_CLEAR(py_module);
|
||||||
|
@@ -45,9 +45,6 @@ int sudo_module_ConvMessages_to_c(PyObject *py_tuple, Py_ssize_t *num_msgs, stru
|
|||||||
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||||||
int sudo_module_register_baseplugin(PyObject *py_module);
|
int sudo_module_register_baseplugin(PyObject *py_module);
|
||||||
|
|
||||||
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
|
||||||
int sudo_module_register_loghandler(PyObject *py_module);
|
|
||||||
|
|
||||||
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||||||
int sudo_module_set_default_loghandler(void);
|
int sudo_module_set_default_loghandler(void);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user