From 957a23b0883c1d92f4d5c5de2459319615a8ed34 Mon Sep 17 00:00:00 2001
From: Antoine Pitrou <solipsis@pitrou.net>
Date: Sat, 4 May 2013 20:45:02 +0200
Subject: [PATCH] Issue #17408: Avoid using an obsolete instance of the copyreg
 module when the interpreter is shutdown and then started again.

---
 Include/pythonrun.h  |  1 +
 Misc/NEWS            |  3 +++
 Objects/typeobject.c | 22 +++++++++++++++++-----
 Python/pythonrun.c   |  4 +---
 4 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/Include/pythonrun.h b/Include/pythonrun.h
index 4d24b2df7d..e8a582d50a 100644
--- a/Include/pythonrun.h
+++ b/Include/pythonrun.h
@@ -219,6 +219,7 @@ PyAPI_FUNC(void) PyFloat_Fini(void);
 PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
 PyAPI_FUNC(void) _PyGC_Fini(void);
 PyAPI_FUNC(void) PySlice_Fini(void);
+PyAPI_FUNC(void) _PyType_Fini(void);
 
 PyAPI_DATA(PyThreadState *) _Py_Finalizing;
 #endif
diff --git a/Misc/NEWS b/Misc/NEWS
index 1bb73554c6..6a3f17c9b5 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 3.3.2?
 Core and Builtins
 -----------------
 
+- Issue #17408: Avoid using an obsolete instance of the copyreg module when
+  the interpreter is shutdown and then started again.
+
 - Issue #17863: In the interactive console, don't loop forever if the encoding
   can't be fetched from stdin.
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 6ece741833..f40dd10a34 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -7,6 +7,10 @@
 #include <ctype.h>
 
 
+/* Cached lookup of the copyreg module, for faster __reduce__ calls */
+
+static PyObject *cached_copyreg_module = NULL;
+
 /* Support type attribute cache */
 
 /* The cache can keep references to the names alive for longer than
@@ -68,6 +72,15 @@ PyType_ClearCache(void)
     return cur_version_tag;
 }
 
+void
+_PyType_Fini(void)
+{
+    PyType_ClearCache();
+    /* Need to forget our obsolete instance of the copyreg module at
+     * interpreter shutdown (issue #17408). */
+    Py_CLEAR(cached_copyreg_module);
+}
+
 void
 PyType_Modified(PyTypeObject *type)
 {
@@ -3339,19 +3352,18 @@ static PyObject *
 import_copyreg(void)
 {
     static PyObject *copyreg_str;
-    static PyObject *mod_copyreg = NULL;
 
     if (!copyreg_str) {
         copyreg_str = PyUnicode_InternFromString("copyreg");
         if (copyreg_str == NULL)
             return NULL;
     }
-    if (!mod_copyreg) {
-        mod_copyreg = PyImport_Import(copyreg_str);
+    if (!cached_copyreg_module) {
+        cached_copyreg_module = PyImport_Import(copyreg_str);
     }
 
-    Py_XINCREF(mod_copyreg);
-    return mod_copyreg;
+    Py_XINCREF(cached_copyreg_module);
+    return cached_copyreg_module;
 }
 
 static PyObject *
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ee6071e631..ddda4a4cd0 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -506,9 +506,6 @@ Py_Finalize(void)
     /* Disable signal handling */
     PyOS_FiniInterrupts();
 
-    /* Clear type lookup cache */
-    PyType_ClearCache();
-
     /* Collect garbage.  This may call finalizers; it's nice to call these
      * before all modules are destroyed.
      * XXX If a __del__ or weakref callback is triggered here, and tries to
@@ -614,6 +611,7 @@ Py_Finalize(void)
     PyFloat_Fini();
     PyDict_Fini();
     PySlice_Fini();
+    _PyType_Fini();
 
     /* Cleanup Unicode implementation */
     _PyUnicode_Fini();
-- 
2.40.0