bpo-42955: Add sys.modules_names (GH-24238)

Add sys.module_names, containing the list of the standard library
module names.
This commit is contained in:
Victor Stinner 2021-01-25 13:24:42 +01:00 committed by GitHub
parent 879986d8a9
commit db584bdad3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 305 additions and 275 deletions

View file

@ -18,8 +18,6 @@
#include "pycore_sysmodule.h" // _PySys_ClearAuditHooks()
#include "pycore_traceback.h" // _Py_DumpTracebackThreads()
#include "module_names.h" // _Py_module_names
#include <locale.h> // setlocale()
#ifdef HAVE_SIGNAL_H
@ -2499,7 +2497,7 @@ fatal_error_exit(int status)
// Dump the list of extension modules of sys.modules, excluding stdlib modules
// (_Py_module_names), into fd file descriptor.
// (sys.module_names), into fd file descriptor.
//
// This function is called by a signal handler in faulthandler: avoid memory
// allocations and keep the implementation simple. For example, the list is not
@ -2515,10 +2513,31 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
return;
}
Py_ssize_t pos;
PyObject *key, *value;
// Avoid PyDict_GetItemString() which calls PyUnicode_FromString(),
// memory cannot be allocated on the heap in a signal handler.
// Iterate on the dict instead.
PyObject *module_names = NULL;
pos = 0;
while (PyDict_Next(interp->sysdict, &pos, &key, &value)) {
if (PyUnicode_Check(key)
&& PyUnicode_CompareWithASCIIString(key, "module_names") == 0) {
module_names = value;
break;
}
}
// If we failed to get sys.module_names or it's not a frozenset,
// don't exclude stdlib modules.
if (module_names != NULL && !PyFrozenSet_Check(module_names)) {
module_names = NULL;
}
// List extensions
int header = 1;
Py_ssize_t count = 0;
Py_ssize_t pos = 0;
PyObject *key, *value;
pos = 0;
while (PyDict_Next(modules, &pos, &key, &value)) {
if (!PyUnicode_Check(key)) {
continue;
@ -2526,22 +2545,26 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
if (!_PyModule_IsExtension(value)) {
continue;
}
// Check if it is a stdlib extension module.
// Use the module name from the sys.modules key,
// don't attempt to get the module object name.
const Py_ssize_t names_len = Py_ARRAY_LENGTH(_Py_module_names);
int is_stdlib_mod = 0;
for (Py_ssize_t i=0; i < names_len; i++) {
const char *name = _Py_module_names[i];
if (PyUnicode_CompareWithASCIIString(key, name) == 0) {
is_stdlib_mod = 1;
break;
if (module_names != NULL) {
int is_stdlib_ext = 0;
Py_ssize_t i;
PyObject *item;
Py_hash_t hash;
for (i=0; _PySet_NextEntry(module_names, &i, &item, &hash); ) {
if (PyUnicode_Check(item)
&& PyUnicode_Compare(key, item) == 0)
{
is_stdlib_ext = 1;
break;
}
}
if (is_stdlib_ext) {
// Ignore stdlib extension
continue;
}
}
if (is_stdlib_mod) {
// Ignore stdlib extension module.
continue;
}
if (header) {