mirror of https://github.com/python/cpython
Issue #1545463: At shutdown, defer finalization of codec modules so that stderr remains usable.
(should fix Windows buildbot failures on test_gc)
This commit is contained in:
parent
d62a514386
commit
070cb3c9be
|
@ -25,6 +25,12 @@ PyAPI_FUNC(int) PyErr_WarnExplicit(
|
||||||
const char *module, /* UTF-8 encoded string */
|
const char *module, /* UTF-8 encoded string */
|
||||||
PyObject *registry);
|
PyObject *registry);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int)
|
||||||
|
PyErr_WarnExplicitFormat(PyObject *category,
|
||||||
|
const char *filename, int lineno,
|
||||||
|
const char *module, PyObject *registry,
|
||||||
|
const char *format, ...);
|
||||||
|
|
||||||
/* DEPRECATED: Use PyErr_WarnEx() instead. */
|
/* DEPRECATED: Use PyErr_WarnEx() instead. */
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
|
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #1545463: At shutdown, defer finalization of codec modules so
|
||||||
|
that stderr remains usable.
|
||||||
|
|
||||||
- Issue #7330: Implement width and precision (ex: "%5.3s") for the format
|
- Issue #7330: Implement width and precision (ex: "%5.3s") for the format
|
||||||
string of PyUnicode_FromFormat() function, original patch written by Ysj Ray.
|
string of PyUnicode_FromFormat() function, original patch written by Ysj Ray.
|
||||||
|
|
||||||
|
|
|
@ -1557,8 +1557,12 @@ _PyGC_DumpShutdownStats(void)
|
||||||
else
|
else
|
||||||
message = "gc: %zd uncollectable objects at " \
|
message = "gc: %zd uncollectable objects at " \
|
||||||
"shutdown; use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them";
|
"shutdown; use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them";
|
||||||
if (PyErr_WarnFormat(PyExc_ResourceWarning, 0, message,
|
/* PyErr_WarnFormat does too many things and we are at shutdown,
|
||||||
PyList_GET_SIZE(garbage)) < 0)
|
the warnings module's dependencies (e.g. linecache) may be gone
|
||||||
|
already. */
|
||||||
|
if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0,
|
||||||
|
"gc", NULL, message,
|
||||||
|
PyList_GET_SIZE(garbage)))
|
||||||
PyErr_WriteUnraisable(NULL);
|
PyErr_WriteUnraisable(NULL);
|
||||||
if (debug & DEBUG_UNCOLLECTABLE) {
|
if (debug & DEBUG_UNCOLLECTABLE) {
|
||||||
PyObject *repr = NULL, *bytes = NULL;
|
PyObject *repr = NULL, *bytes = NULL;
|
||||||
|
|
|
@ -820,6 +820,49 @@ PyErr_WarnExplicit(PyObject *category, const char *text,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyErr_WarnExplicitFormat(PyObject *category,
|
||||||
|
const char *filename_str, int lineno,
|
||||||
|
const char *module_str, PyObject *registry,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
PyObject *message;
|
||||||
|
PyObject *module = NULL;
|
||||||
|
PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
|
||||||
|
int ret = -1;
|
||||||
|
va_list vargs;
|
||||||
|
|
||||||
|
if (filename == NULL)
|
||||||
|
goto exit;
|
||||||
|
if (module_str != NULL) {
|
||||||
|
module = PyUnicode_FromString(module_str);
|
||||||
|
if (module == NULL)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_PROTOTYPES
|
||||||
|
va_start(vargs, format);
|
||||||
|
#else
|
||||||
|
va_start(vargs);
|
||||||
|
#endif
|
||||||
|
message = PyUnicode_FromFormatV(format, vargs);
|
||||||
|
if (message != NULL) {
|
||||||
|
PyObject *res;
|
||||||
|
res = warn_explicit(category, message, filename, lineno,
|
||||||
|
module, registry, NULL);
|
||||||
|
Py_DECREF(message);
|
||||||
|
if (res != NULL) {
|
||||||
|
Py_DECREF(res);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(vargs);
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(module);
|
||||||
|
Py_XDECREF(filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(warn_doc,
|
PyDoc_STRVAR(warn_doc,
|
||||||
"Issue a warning, or maybe ignore it or raise an exception.");
|
"Issue a warning, or maybe ignore it or raise an exception.");
|
||||||
|
|
|
@ -295,6 +295,30 @@ static char* sys_files[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_essential_module(PyObject *name)
|
||||||
|
{
|
||||||
|
Py_ssize_t name_len;
|
||||||
|
char *name_str = PyUnicode_AsUTF8AndSize(name, &name_len);
|
||||||
|
|
||||||
|
if (name_str == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strcmp(name_str, "builtins") == 0)
|
||||||
|
return 1;
|
||||||
|
if (strcmp(name_str, "sys") == 0)
|
||||||
|
return 1;
|
||||||
|
/* These are all needed for stderr to still function */
|
||||||
|
if (strcmp(name_str, "codecs") == 0)
|
||||||
|
return 1;
|
||||||
|
if (strcmp(name_str, "_codecs") == 0)
|
||||||
|
return 1;
|
||||||
|
if (strncmp(name_str, "encodings.", 10) == 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Un-initialize things, as good as we can */
|
/* Un-initialize things, as good as we can */
|
||||||
|
|
||||||
|
@ -374,9 +398,7 @@ PyImport_Cleanup(void)
|
||||||
if (value->ob_refcnt != 1)
|
if (value->ob_refcnt != 1)
|
||||||
continue;
|
continue;
|
||||||
if (PyUnicode_Check(key) && PyModule_Check(value)) {
|
if (PyUnicode_Check(key) && PyModule_Check(value)) {
|
||||||
if (PyUnicode_CompareWithASCIIString(key, "builtins") == 0)
|
if (is_essential_module(key))
|
||||||
continue;
|
|
||||||
if (PyUnicode_CompareWithASCIIString(key, "sys") == 0)
|
|
||||||
continue;
|
continue;
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_FormatStderr(
|
PySys_FormatStderr(
|
||||||
|
@ -392,9 +414,7 @@ PyImport_Cleanup(void)
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (PyDict_Next(modules, &pos, &key, &value)) {
|
while (PyDict_Next(modules, &pos, &key, &value)) {
|
||||||
if (PyUnicode_Check(key) && PyModule_Check(value)) {
|
if (PyUnicode_Check(key) && PyModule_Check(value)) {
|
||||||
if (PyUnicode_CompareWithASCIIString(key, "builtins") == 0)
|
if (is_essential_module(key))
|
||||||
continue;
|
|
||||||
if (PyUnicode_CompareWithASCIIString(key, "sys") == 0)
|
|
||||||
continue;
|
continue;
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_FormatStderr("# cleanup[2] %U\n", key);
|
PySys_FormatStderr("# cleanup[2] %U\n", key);
|
||||||
|
@ -411,20 +431,15 @@ PyImport_Cleanup(void)
|
||||||
machinery. */
|
machinery. */
|
||||||
_PyGC_DumpShutdownStats();
|
_PyGC_DumpShutdownStats();
|
||||||
|
|
||||||
/* Next, delete sys and builtins (in that order) */
|
/* Next, delete all remaining modules */
|
||||||
value = PyDict_GetItemString(modules, "sys");
|
pos = 0;
|
||||||
if (value != NULL && PyModule_Check(value)) {
|
while (PyDict_Next(modules, &pos, &key, &value)) {
|
||||||
|
if (PyUnicode_Check(key) && PyModule_Check(value)) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# cleanup sys\n");
|
PySys_FormatStderr("# cleanup[3] %U\n", key);
|
||||||
_PyModule_Clear(value);
|
_PyModule_Clear(value);
|
||||||
PyDict_SetItemString(modules, "sys", Py_None);
|
PyDict_SetItem(modules, key, Py_None);
|
||||||
}
|
}
|
||||||
value = PyDict_GetItemString(modules, "builtins");
|
|
||||||
if (value != NULL && PyModule_Check(value)) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_WriteStderr("# cleanup builtins\n");
|
|
||||||
_PyModule_Clear(value);
|
|
||||||
PyDict_SetItemString(modules, "builtins", Py_None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, clear and delete the modules directory */
|
/* Finally, clear and delete the modules directory */
|
||||||
|
|
Loading…
Reference in New Issue