Skip to content

Commit

Permalink
pythongh-71587: Drop local reference cache to _strptime module in `…
Browse files Browse the repository at this point in the history
…_datetime` (pythongh-120224)

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()).
  • Loading branch information
neonene authored and noahbkim committed Jul 11, 2024
1 parent c1877da commit d4ec8c3
Showing 8 changed files with 24 additions and 8 deletions.
1 change: 1 addition & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
@@ -266,6 +266,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_)
1 change: 1 addition & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
@@ -404,6 +404,15 @@ def test_ucnhash_capi_reset(self):
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):
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix crash in C version of :meth:`datetime.datetime.strptime` when called again
on the restarted interpreter.
14 changes: 7 additions & 7 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
@@ -5514,19 +5514,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. */
1 change: 0 additions & 1 deletion Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
@@ -393,7 +393,6 @@ Modules/xxmodule.c - ErrorObject -

## initialized once
Modules/_cursesmodule.c - ModDict -
Modules/_datetimemodule.c datetime_strptime module -

## state
Modules/_datetimemodule.c - _datetime_global_state -

0 comments on commit d4ec8c3

Please sign in to comment.