Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1a83070

Browse files
committed
Issue #19088: Fix incorrect caching of the copyreg module.
This fix does not cause any degradation in performance.
1 parent 04a684b commit 1a83070

2 files changed

Lines changed: 23 additions & 17 deletions

File tree

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #19088: Fixed incorrect caching of the copyreg module in
22+
object.__reduce__() and object.__reduce_ex__().
23+
2124
- Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with
2225
virtual interface. Original patch by Kent Frazier.
2326

Objects/typeobject.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
#include <ctype.h>
88

99

10-
/* Cached lookup of the copyreg module, for faster __reduce__ calls */
11-
12-
static PyObject *cached_copyreg_module = NULL;
13-
1410
/* Support type attribute cache */
1511

1612
/* The cache can keep references to the names alive for longer than
@@ -73,9 +69,6 @@ void
7369
_PyType_Fini(void)
7470
{
7571
PyType_ClearCache();
76-
/* Need to forget our obsolete instance of the copyreg module at
77-
* interpreter shutdown (issue #17408). */
78-
Py_CLEAR(cached_copyreg_module);
7972
}
8073

8174
void
@@ -3348,19 +3341,29 @@ static PyGetSetDef object_getsets[] = {
33483341
static PyObject *
33493342
import_copyreg(void)
33503343
{
3351-
static PyObject *copyreg_str;
3344+
PyObject *copyreg_str;
3345+
PyObject *copyreg_module;
3346+
PyInterpreterState *interp = PyThreadState_GET()->interp;
3347+
_Py_IDENTIFIER(copyreg);
33523348

3353-
if (!copyreg_str) {
3354-
copyreg_str = PyUnicode_InternFromString("copyreg");
3355-
if (copyreg_str == NULL)
3356-
return NULL;
3349+
copyreg_str = _PyUnicode_FromId(&PyId_copyreg);
3350+
if (copyreg_str == NULL) {
3351+
return NULL;
33573352
}
3358-
if (!cached_copyreg_module) {
3359-
cached_copyreg_module = PyImport_Import(copyreg_str);
3353+
/* Try to fetch cached copy of copyreg from sys.modules first in an
3354+
attempt to avoid the import overhead. Previously this was implemented
3355+
by storing a reference to the cached module in a static variable, but
3356+
this broke when multiple embeded interpreters were in use (see issue
3357+
#17408 and #19088). */
3358+
copyreg_module = PyDict_GetItemWithError(interp->modules, copyreg_str);
3359+
if (copyreg_module != NULL) {
3360+
Py_INCREF(copyreg_module);
3361+
return copyreg_module;
3362+
}
3363+
if (PyErr_Occurred()) {
3364+
return NULL;
33603365
}
3361-
3362-
Py_XINCREF(cached_copyreg_module);
3363-
return cached_copyreg_module;
3366+
return PyImport_Import(copyreg_str);
33643367
}
33653368

33663369
static PyObject *

0 commit comments

Comments
 (0)