Skip to content

implement multi-phase init#1024

Open
provinzkraut wants to merge 1 commit intojcrist:mainfrom
provinzkraut:multi-phase-init
Open

implement multi-phase init#1024
provinzkraut wants to merge 1 commit intojcrist:mainfrom
provinzkraut:multi-phase-init

Conversation

@provinzkraut
Copy link
Copy Markdown
Contributor

Closes #563.

Implement multi-phase init.

Relatively straightforward, the only slight hiccough is msgspec_get_global_state, which relied on PyState_FindModule / PyState_AddModule, which in turn don't work (well) with multi-phase init. I've replaced them with a global static MsgspecState, set during module init; This is not safe for sub-interpreters, but handling it properly would be a large refactor that I think is best kept for separate PRs.


Road to subinterpreter support

This is the first step for msgspec to support subinterpreters, but it's still a long way to go. I'll open a separate tracking issue for that once this gets merged, but it'll likely involve some larger refactors, especially around moving things to heap types where absolutely necessary, and ensuring this does not impact performance negatively.

Comment thread tests/unit/test_module.py
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

since we're changing how the subinterpreter support is flagged, i wanted some tests to show it's still working

@provinzkraut provinzkraut force-pushed the multi-phase-init branch 2 times, most recently from d65661e to 16fe68d Compare April 18, 2026 15:35
@provinzkraut provinzkraut marked this pull request as draft April 18, 2026 15:36
@provinzkraut provinzkraut marked this pull request as ready for review April 18, 2026 21:13
Comment thread src/msgspec/_core.c
return 0;
}

static struct PyModuleDef msgspecmodule = {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was simply moved down to make the flow easier, as it references _core_exec

Copy link
Copy Markdown
Collaborator

@Siyet Siyet left a comment

Choose a reason for hiding this comment

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

Leaving a note for the history / backlink: this obsoletes the PyState_AddModule workaround jcrist added in #561, where the body said "in the long run we should move to using multiphase module init which should avoid this problem entirely." Good to have the thread connected.

Comment thread src/msgspec/_core.c
with multi-phase init PyState_FindModule is not usable.
since we declare MULTIPLE_INTERPRETERS_NOT_SUPPORTED, we are guaranteed to have
at most one live module instance per process, so we can cache its state here.
state is populated populate in _core_exec and cleared by m_clear / m_free.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: populated populate - duplicated word.

@goodboy
Copy link
Copy Markdown

goodboy commented Apr 21, 2026

I'll open a separate tracking issue for that once this gets merged,

please do ping if/when that happens 🙏🏼

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.

Use multi-phase init for c-extension initialization

3 participants