gh-117398: Use Per-Interpreter State for the _datetime Static Types by ericsnowcurrently · Pull Request #119929 · python/cpython · GitHub
Skip to content

gh-117398: Use Per-Interpreter State for the _datetime Static Types - #119929

Merged
ericsnowcurrently merged 39 commits into
python:mainfrom
ericsnowcurrently:datetime-static-types
Jun 3, 2024
Merged

gh-117398: Use Per-Interpreter State for the _datetime Static Types#119929
ericsnowcurrently merged 39 commits into
python:mainfrom
ericsnowcurrently:datetime-static-types

Conversation

@ericsnowcurrently

@ericsnowcurrently ericsnowcurrently commented Jun 1, 2024

Copy link
Copy Markdown
Member

We make use of the same mechanism that we use for the static builtin types. This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this PR. I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly.

(Note for reviewers: this PR is based on top of gh-119810. Consider reviewing only the commits from 1e3005d ("_PyStaticType_Dealloc() -> _PyStaticType_FiniBuiltin()") down or you can wait for that other PR to be merged first. For simplicity sake: https://github.com/python/cpython/pull/119929/files/1e3005d1874534121aba7de890e91300ac5fac84..HEAD)

@neonene neonene left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the crashes and refleaks on main/sub interpreters, just a rough workaround can be seen in my repo: 6e761d7. Inheritance between _datetime types seems to make things complicated, unlike the static builtin types.

Comment thread Modules/_datetimemodule.c
Comment on lines +7169 to +7170

@neonene neonene Jun 3, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to run callback_for_interp_exit(NULL) directly before the return when PyUnstable_AtExit() fails?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that should work fine. Good idea.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread Objects/typeobject.c Outdated
Comment on lines +206 to +210
if (!isbuiltin) {
PyMutex_Lock(&interp->types.mutex);
index = interp->types.for_extensions.next_index;
interp->types.for_extensions.next_index++;
PyMutex_Unlock(&interp->types.mutex);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels safer to me for each _datetime type to have a constant index value, if the module can be reloaded multiple times before the interpreter-dict gets a key. Index overflow, intermittent indexes are my concerns.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can simply not clear the value ever and adjust various asserts accordingly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, there isn't much value in keeping the index fixed between reinits. Furthermore, that wouldn't be an option if multiple extension modules were involved. I'd rather iron this out in later 3.14 changes that we won't be backporting.

Comment thread Objects/typeobject.c
Comment on lines +176 to +189
static managed_static_type_state *
managed_static_type_state_get(PyInterpreterState *interp, PyTypeObject *self)
{
// It's probably a builtin type.
size_t index = managed_static_type_index_get(self);
managed_static_type_state *state =
&(interp->types.builtins.initialized[index]);
if (state->type == self) {
return state;
}
if (index > _Py_MAX_MANAGED_STATIC_EXT_TYPES) {
return state;
}
return &(interp->types.for_extensions.initialized[index]);

@neonene neonene Jun 3, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could _datetime types have their index plus 200 (_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES) in the tp_subclasses? Then, is_builten = tp_subclasses <= 200, and like index = tp_subclasses % 200 - 1 ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I considered doing that and plan on an approach like that eventually. However, for now I'd like to get the simpler approach in for the 3.13 backport.

Co-authored-by: neonene <53406459+neonene@users.noreply.github.com>
@ericsnowcurrently

Copy link
Copy Markdown
Member Author
>_testembed_d test_repeated_init_exec "import _datetime"
--- Loop #1 ---
--- Loop #2 ---
Assertion failed: lookup_tp_bases(type) == NULL, file C:\cp\Objects\typeobject.c, line 7840
>>> import _interpreters
>>> interp = _interpreters.create()
>>> _interpreters.run_string(interp, "import _datetime")
Assertion failed: lookup_tp_bases(type) != NULL, file C:\cp\Objects\typeobject.c, line 7837

No error occurred when main interpreter imported _datetime first:

>>> import _datetime
>>> import _interpreters
>>> interp = _interpreters.create()
>>> _interpreters.run_string(interp, "import _datetime")
>>> _interpreters.destroy(interp)
>>>

Good catch. I'll take a look.

@ericsnowcurrently

Copy link
Copy Markdown
Member Author

Regarding the crashes and refleaks on main/sub interpreters, just a rough workaround can be seen in my repo: 6e761d7. Inheritance between _datetime types seems to make things complicated, unlike the static builtin types.

I've taken care of this and did it in a similar way to what you did. Thanks for bringing it up.

@ericsnowcurrently

Copy link
Copy Markdown
Member Author

There are some really neat tricks here, Eric; I really enjoyed reading through this :)

Thanks for saying so! :)

Consider to split this in three PRs:

  1. refactor/rename the _PyStaticType APIs for builtins
  2. add the internal _PyStaticType APIs for extension modules
  3. the _datetime changes

It should not be too hard to separate those changes, 1. and 2. touches different files than 3.

I appreciate this feedback. Normally I'd actually have split this into a number of PRs along the lines you've enumerated. However, the current schedule makes it a bit trickier.

Comment thread Misc/NEWS.d/next/Library/2024-06-01-16-58-43.gh-issue-117398.kR0RW7.rst Outdated
@ericsnowcurrently ericsnowcurrently added the needs backport to 3.13 bugs and security fixes label Jun 3, 2024
@ericsnowcurrently
ericsnowcurrently merged commit 105f22e into python:main Jun 3, 2024
@miss-islington-app

Copy link
Copy Markdown

Thanks @ericsnowcurrently for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13.
🐍🍒⛏🤖

@ericsnowcurrently
ericsnowcurrently deleted the datetime-static-types branch June 3, 2024 23:09
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jun 3, 2024
…ypes (pythongh-119929)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this change.  I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.
(cherry picked from commit 105f22e)

Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
@bedevere-app

bedevere-app Bot commented Jun 3, 2024

Copy link
Copy Markdown

GH-120009 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.13 bugs and security fixes label Jun 3, 2024
ericsnowcurrently added a commit that referenced this pull request Jun 3, 2024
…Types (gh-120009)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.

(cherry picked from commit 105f22e, AKA gh-119929)

Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
@neonene

neonene commented Jun 4, 2024

Copy link
Copy Markdown
Contributor

Thank you very much for landing this.

@bedevere-bot

Copy link
Copy Markdown

barneygale pushed a commit to barneygale/cpython that referenced this pull request Jun 5, 2024
…ypes (pythongh-119929)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this change.  I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.
noahbkim pushed a commit to hudson-trading/cpython that referenced this pull request Jul 11, 2024
…ypes (pythongh-119929)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this change.  I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.
estyxx pushed a commit to estyxx/cpython that referenced this pull request Jul 17, 2024
…ypes (pythongh-119929)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this change.  I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants