GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-124622: Add PyThreadState_Ensure() function by vstinner · Pull Request #130012 · python/cpython Conversation
|
| PyGILState_STATE | ||
| PyGILState_Ensure(void) | ||
| { | ||
| PyInterpreterState *interp = _PyRuntime.gilstate.autoInterpreterState; |
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
If it's NULL, we should probably just fatal error or hang the thread.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could add an assert.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
That doesn't help much. Release builds will crash at finalization with spurious NULL derefs if we don't add a case for it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
If possible, I would prefer to not change PyGILState_Ensure() in this PR which ("only") adds PyThreadState_Ensure().
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I'd be happy to do that in a follow-up then.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
|
||
|
|
||
| void | ||
| PyThreadState_Release(int oldstate) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thinking out loud here: instead of manually passing an int around indicating the number of PyThreadState_Ensure calls, why not just store that number on the thread state itself?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The oldstate is either PyGILState_UNLOCKED or PyGILState_LOCKED, it's not a counter.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Oh, hm. Why do we need PyGILState here at all? The thread state should pretty much manage itself, there just needs to be a call to PyThreadState_Clear and PyThreadState_DeleteCurrent at the end (which is why I thought it would be done with a counter of calls).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I understand that PyThreadState_Release() does basically nothing if oldstate is PyGILState_LOCKED: if the thread already hold the GIL when PyThreadState_Ensure() was called.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I might just be used to dealing with thread states the subinterpreter way, but I think it could be worth avoiding any ints entirely in PyThreadState_Ensure. If we add a new field to PyThreadState (e.g., ensured) which is incremented for a call to PyThreadState_Ensure and then decremented upon a call to PyThreadState_Release, we could automatically clear and delete the thread state when that number hits zero from PyThreadState_Release. I think we should discuss this elsewhere, though. I think I'll create the WG discussion.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The problem is that you can have nested calls to PyThreadState_Ensure(). How do you store such stack of states in PyThreadState?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we could set up a field for a linked list, so PyThreadState_Ensure/PyThreadState_Release would look something along the lines of:
int PyThreadState_Ensure(PyInterpreterState *interp) { PyThreadState *current = current_fast_get(); if (current == NULL) { // Make a new thread state for *interp* and return it /* ... */ } else { PyThreadState *new_tstate = _PyThreadState_NewBound(interp); assert(new_tstate->ensured == NULL); new_tstate->ensured = current; _PyThreadState_Detach(current); /* AttachOrFail(new_tstate) ... */ } } void PyThreadState_Release() { PyThreadState *current = current_fast_get(); _Py_EnsureTstateNotNULL(current); PyThreadState *to_restore = current->ensured; _PyThreadState_Detach(current); if (to_restore != NULL) { /* AttachOrFail(to_restore) */ } // Nothing to restore, leave no attached tstate assert(current_fast_get() == NULL); }
PyThreadState_Release because it should be able to reattach to the previous thread state if it didn't have the requested interpreter (regardless of any linked list).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I changed the API to Currently, the only error message is: "Python is being finalized". |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this, by the way :)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Add PyThreadState.ensure_depth member.
| if (tcur != NULL && tcur->interp != interp) { | ||
| // The current thread state is from another interpreter | ||
| tcur = NULL; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think PyThreadState_Release is missing code to restore the previous thread state for this case where the active thread state was from a different interpreter.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It is, but the design is still being discussed. This PR is, more or less, a draft until the C API WG approves it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I prefer to close this PR for now until we agree on the API semantics. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.