summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-06-12 17:15:16 (GMT)
committerGitHub <noreply@github.com>2024-06-12 17:15:16 (GMT)
commit0041087aa12044223103c7b8a3ca07d896652ab9 (patch)
tree4be4723449a1658a18a46177c6954a124692ea63
parent8e5caa72c2556c4ba1fb90dfc6593bb848a6c116 (diff)
downloadcpython-0041087aa12044223103c7b8a3ca07d896652ab9.zip
cpython-0041087aa12044223103c7b8a3ca07d896652ab9.tar.gz
cpython-0041087aa12044223103c7b8a3ca07d896652ab9.tar.bz2
[3.13] gh-71587: Drop local reference cache to `_strptime` module in `_datetime` (gh-120424)
The _strptime module object was cached in a static local variable (in the datetime.strptime() implementation). That's a problem when it crosses isolation boundaries, such as reinitializing the runtme or between interpreters. This change fixes the problem by dropping the static variable, instead always relying on the normal sys.modules cache (via PyImport_Import()). (cherry picked from commit 127c1d2771749853e287632c086b6054212bf12a, AKA gh-120224) Co-authored-by: neonene <53406459+neonene@users.noreply.github.com>
-rw-r--r--Include/internal/pycore_global_objects_fini_generated.h1
-rw-r--r--Include/internal/pycore_global_strings.h1
-rw-r--r--Include/internal/pycore_runtime_init_generated.h1
-rw-r--r--Include/internal/pycore_unicodeobject_generated.h3
-rw-r--r--Lib/test/test_embed.py9
-rw-r--r--Misc/NEWS.d/next/Library/2024-06-07-11-23-31.gh-issue-71587.IjFajE.rst2
-rw-r--r--Modules/_datetimemodule.c14
-rw-r--r--Tools/c-analyzer/cpython/globals-to-fix.tsv1
8 files changed, 24 insertions, 8 deletions
diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h
index a40f007..07d96ba 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -776,6 +776,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_showwarnmsg));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_shutdown));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_slotnames));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime_datetime));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_swappedbytes_));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_type_));
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index eaf81e4..9b2becd 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -265,6 +265,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(_showwarnmsg)
STRUCT_FOR_ID(_shutdown)
STRUCT_FOR_ID(_slotnames)
+ STRUCT_FOR_ID(_strptime)
STRUCT_FOR_ID(_strptime_datetime)
STRUCT_FOR_ID(_swappedbytes_)
STRUCT_FOR_ID(_type_)
diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h
index b18c268..6a38b20 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -774,6 +774,7 @@ extern "C" {
INIT_ID(_showwarnmsg), \
INIT_ID(_shutdown), \
INIT_ID(_slotnames), \
+ INIT_ID(_strptime), \
INIT_ID(_strptime_datetime), \
INIT_ID(_swappedbytes_), \
INIT_ID(_type_), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h
index 87e22ac..16502bb 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -636,6 +636,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(_slotnames);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
+ string = &_Py_ID(_strptime);
+ assert(_PyUnicode_CheckConsistency(string, 1));
+ _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(_strptime_datetime);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index d94c63a..634513e 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -404,6 +404,15 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
self.assertEqual(out, '9\n' * INIT_LOOPS)
+ def test_datetime_reset_strptime(self):
+ code = (
+ "import datetime;"
+ "d = datetime.datetime.strptime('2000-01-01', '%Y-%m-%d');"
+ "print(d.strftime('%Y%m%d'))"
+ )
+ out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
+ self.assertEqual(out, '20000101\n' * INIT_LOOPS)
+
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2024-06-07-11-23-31.gh-issue-71587.IjFajE.rst b/Misc/NEWS.d/next/Library/2024-06-07-11-23-31.gh-issue-71587.IjFajE.rst
new file mode 100644
index 0000000..50a6629
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-06-07-11-23-31.gh-issue-71587.IjFajE.rst
@@ -0,0 +1,2 @@
+Fix crash in C version of :meth:`datetime.datetime.strptime` when called again
+on the restarted interpreter.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index d6fa273..7db3030 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -5511,19 +5511,19 @@ datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
static PyObject *
datetime_strptime(PyObject *cls, PyObject *args)
{
- static PyObject *module = NULL;
- PyObject *string, *format;
+ PyObject *string, *format, *result;
if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format))
return NULL;
+ PyObject *module = PyImport_Import(&_Py_ID(_strptime));
if (module == NULL) {
- module = PyImport_ImportModule("_strptime");
- if (module == NULL)
- return NULL;
+ return NULL;
}
- return PyObject_CallMethodObjArgs(module, &_Py_ID(_strptime_datetime),
- cls, string, format, NULL);
+ result = PyObject_CallMethodObjArgs(module, &_Py_ID(_strptime_datetime),
+ cls, string, format, NULL);
+ Py_DECREF(module);
+ return result;
}
/* Return new datetime from date/datetime and time arguments. */
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index aeb7cad..06e58e9 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -434,7 +434,6 @@ Modules/_ctypes/_ctypes.c CreateSwappedType swapped_suffix -
Modules/_ctypes/_ctypes.c - _unpickle -
Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype array_cache -
Modules/_cursesmodule.c - ModDict -
-Modules/_datetimemodule.c datetime_strptime module -
## state
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -