← 返回首页
[3.7] bpo-32604: Swap threads only if the interpreter is different. (gh-5778) by miss-islington · Pull Request #5783 · python/cpython · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (2) .py  (1) All 2 file types selected Viewed files
Conversations
Failed to load comments. Retry
Loading
Jump to
Jump to file
Failed to load files. Retry
Loading
Diff view
Unified
Split
Hide whitespace
Apply and reload
Show whitespace
Diff view
Unified
Split
Hide whitespace
Apply and reload
49 changes: 49 additions & 0 deletions Lib/test/test__xxsubinterpreters.py
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pickle
from textwrap import dedent, indent
import threading
import time
import unittest

from test import support
Expand Down Expand Up @@ -1147,6 +1148,54 @@ def test_send_recv_different_interpreters(self):

self.assertEqual(obj, b'spam')

def test_send_recv_different_threads(self):
cid = interpreters.channel_create()

def f():
while True:
try:
obj = interpreters.channel_recv(cid)
break
except interpreters.ChannelEmptyError:
time.sleep(0.1)
interpreters.channel_send(cid, obj)
t = threading.Thread(target=f)
t.start()

interpreters.channel_send(cid, b'spam')
t.join()
obj = interpreters.channel_recv(cid)

self.assertEqual(obj, b'spam')

def test_send_recv_different_interpreters_and_threads(self):
cid = interpreters.channel_create()
id1 = interpreters.create()
out = None

def f():
nonlocal out
out = _run_output(id1, dedent(f"""
import time
import _xxsubinterpreters as _interpreters
while True:
try:
obj = _interpreters.channel_recv({int(cid)})
break
except _interpreters.ChannelEmptyError:
time.sleep(0.1)
assert(obj == b'spam')
_interpreters.channel_send({int(cid)}, b'eggs')
"""))
t = threading.Thread(target=f)
t.start()

interpreters.channel_send(cid, b'spam')
t.join()
obj = interpreters.channel_recv(cid)

self.assertEqual(obj, b'eggs')

def test_send_not_found(self):
with self.assertRaises(interpreters.ChannelNotFoundError):
interpreters.channel_send(10, b'spam')
Expand Down
22 changes: 14 additions & 8 deletions Modules/_xxsubinterpretersmodule.c
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1759,8 +1759,13 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr,
}

// Switch to interpreter.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
PyThreadState *save_tstate = NULL;
if (interp != PyThreadState_Get()->interp) {
// XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
save_tstate = PyThreadState_Swap(tstate);
}

// Run the script.
_sharedexception *exc = NULL;
Expand Down Expand Up @@ -2079,9 +2084,9 @@ interp_create(PyObject *self, PyObject *args)
}

// Create and initialize the new interpreter.
PyThreadState *tstate, *save_tstate;
save_tstate = PyThreadState_Swap(NULL);
tstate = Py_NewInterpreter();
PyThreadState *save_tstate = PyThreadState_Swap(NULL);
// XXX Possible GILState issues?
PyThreadState *tstate = Py_NewInterpreter();
PyThreadState_Swap(save_tstate);
if (tstate == NULL) {
/* Since no new thread state was created, there is no exception to
Expand All @@ -2096,6 +2101,7 @@ interp_create(PyObject *self, PyObject *args)
return _get_id(tstate->interp);

error:
// XXX Possible GILState issues?
save_tstate = PyThreadState_Swap(tstate);
Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate);
Expand Down Expand Up @@ -2146,9 +2152,9 @@ interp_destroy(PyObject *self, PyObject *args)

// Destroy the interpreter.
//PyInterpreterState_Delete(interp);
PyThreadState *tstate, *save_tstate;
tstate = PyInterpreterState_ThreadHead(interp);
save_tstate = PyThreadState_Swap(tstate);
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate);

Expand Down
20 changes: 14 additions & 6 deletions Python/pystate.c
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,10 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp)
PyThread_release_lock(interp->id_mutex);

if (refcount == 0) {
PyThreadState *tstate, *save_tstate;
tstate = PyInterpreterState_ThreadHead(interp);
save_tstate = PyThreadState_Swap(tstate);
// XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate);
}
Expand Down Expand Up @@ -1213,8 +1214,14 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
}
return;
}
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
PyThreadState *save_tstate = PyThreadState_Swap(tstate);

PyThreadState *save_tstate = NULL;
if (interp != PyThreadState_Get()->interp) {
// XXX Using the "head" thread isn't strictly correct.
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
save_tstate = PyThreadState_Swap(tstate);
}

// "Release" the data and/or the object.
if (data->free != NULL) {
Expand All @@ -1223,8 +1230,9 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
Py_XDECREF(data->obj);

// Switch back.
if (save_tstate != NULL)
if (save_tstate != NULL) {
PyThreadState_Swap(save_tstate);
}
}

PyObject *
Expand Down
Toggle all file notes Toggle all file annotations

Footer

© 2026 GitHub, Inc.