Skip to content

Destructing _datetime in sub-interpreters in the same time may crash the process #136423

Description

@aisk

Crash report

What happened?

from concurrent.futures import InterpreterPoolExecutor


executor = InterpreterPoolExecutor()


def f():
    import _datetime
    print(_datetime)


executor.submit(f)
executor.submit(f)

executor.shutdown()

This code may lead to a interpreter crash:

PS C:\Users\xxxxx\Source\cpython> .\python.bat .\a.py
Running Debug|x64 interpreter...
<module '_datetime' (built-in)>
<module '_datetime' (built-in)>
Debug memory block at address p=000002340D505A70: API '?
    15987178197214944733 bytes originally requested
    The 7 pad bytes at p-7 are not all FORBIDDENBYTE (0xfd):
        at p-7: 0xdd *** OUCH
        at p-6: 0xdd *** OUCH
        at p-5: 0xdd *** OUCH
        at p-4: 0xdd *** OUCH
        at p-3: 0xdd *** OUCH
        at p-2: 0xdd *** OUCH
        at p-1: 0xdd *** OUCH
    Because memory is corrupted at the start, the count of bytes requested
       may be bogus, and checking the trailing pad bytes may segfault.
    The 8 pad bytes at tail=DDDDE011EB2E384D are

I think there is a double free here.

Please note that there is a similar issue may crash the interpreter but in the initializing phase: #136421

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS, Windows

Output from running 'python -VV' on the command line:

Python 3.15.0a0 (heads/main:ba9c1986305, Jul 8 2025, 22:13:18) [MSC v.1943 64 bit (AMD64)]

Activity

  1. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    on Jul 8, 2025
  2. aisk commented on Jul 8, 2025

    @aisk
    MemberAuthor
  3. changed the title [-]Destructing _datetime in sub-interpreters in the same time may crash the process[/-] [+]Destructing `_datetime` in sub-interpreters in the same time may crash the process[/+] on Jul 8, 2025
  4. seuwebber commented on Jul 9, 2025

    @seuwebber

    I encountered the same bug while using the C Python API.

  5. neonene commented on Jul 12, 2025

    @neonene
    Contributor

    It seems like Py_TPFLAGS_READY is cleared before managed_static_type_state_clear(), which conficts with _PyStaticType_InitForExtension() then crashes at _PyObject_ClearFreeLists().

    cpython/Objects/typeobject.c

    Lines 6606 to 6616 in db47f4d

    if (final) {
    BEGIN_TYPE_LOCK();
    type_clear_flags(type, Py_TPFLAGS_READY);
    set_version_unlocked(type, 0);
    END_TYPE_LOCK();
    }
    _PyStaticType_ClearWeakRefs(interp, type);
    managed_static_type_state_clear(interp, type, isbuiltin, final);
    /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */
    }

    managed_static_type_state_clear() invokes:

    static inline void
    managed_static_type_index_clear(PyTypeObject *self)
    {
    self->tp_subclasses = NULL;
    }

    So, a possible workaround only for this issue would be:

     int
     _PyStaticType_InitForExtension(PyInterpreterState *interp, PyTypeObject *self)
     {
    -    return init_static_type(interp, self, 0, ((self->tp_flags & Py_TPFLAGS_READY) == 0));
    +    return init_static_type(interp, self, 0, self->tp_subclasses == NULL);
     }
  6. kumaraditya303 commented on Jul 21, 2025

    @kumaraditya303
    Contributor

    Fixed by #136583

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions