Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread-safe one-time initialization #111956

Closed
Tracked by #108219
colesbury opened this issue Nov 10, 2023 · 0 comments
Closed
Tracked by #108219

Thread-safe one-time initialization #111956

colesbury opened this issue Nov 10, 2023 · 0 comments
Assignees
Labels
3.13 bugs and security fixes topic-free-threading type-feature A feature request or enhancement

Comments

@colesbury
Copy link
Contributor

colesbury commented Nov 10, 2023

Feature or enhancement

Some CPython internals require initialization exactly once. Some of these one time initializations are not thread-safe without the GIL or have data races according to the C11 memory model.

We should add a lightweight, thread-safe one-time initialization API similar to C++11's std::call_once 1. The proposed internal-only API follows C++11's std::call_once, but adapted for C (i.e., error returns and function pointers):

typedef struct {
    uint8_t v;
} _PyOnceFlag;

typedef int _Py_once_fn_t(void *arg);

// Calls `fn` once using `flag`. The `arg` is passed to the call to `fn`.
//
// Returns 1 on success and 0 on failure.
//
// If `fn` returns 1 (success), then subsequent calls immediately return 1.
// If `fn` returns 0 (failure), then subsequent calls will retry the call.
int _PyOnceFlag_CallOnce(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg);

As an example, the Python-ast.c relies on the GIL and an initialized variable to ensure that it is only initialized once:

cpython/Python/Python-ast.c

Lines 1126 to 1135 in d61313b

static int
init_types(struct ast_state *state)
{
// init_types() must not be called after _PyAST_Fini()
// has been called
assert(state->initialized >= 0);
if (state->initialized) {
return 1;
}

Linked PRs

Footnotes

  1. Also, pthread_once and C11's call_once. std::call_once supports error returns, which is important for CPython's use cases.

@colesbury colesbury added type-feature A feature request or enhancement 3.13 bugs and security fixes topic-free-threading labels Nov 10, 2023
colesbury added a commit to colesbury/cpython that referenced this issue Nov 10, 2023
The one-time initialization (`_PyOnceFlag`) is used in two places:

 * `Python/Python-ast.c`
 * `Python/getargs.c`
colesbury added a commit to colesbury/cpython that referenced this issue Nov 10, 2023
The one-time initialization (`_PyOnceFlag`) is used in two places:

 * `Python/Python-ast.c`
 * `Python/getargs.c`
@colesbury colesbury self-assigned this Nov 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes topic-free-threading type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

1 participant