diff --git a/src/if_python.c b/src/if_python.c index 1bf737fc4c27d1e2ccc016b8a4ffe32090d342d6..d0314e2f535363201932cd61683362cd6eb4bd1d 100644 --- a/src/if_python.c +++ b/src/if_python.c @@ -741,7 +741,7 @@ Python_Init(void) PyMac_Initialize(); #endif /* Initialise threads, and below save the state using - * PyGILState_Ensure. Without the call to PyGILState_Ensure, thread + * PyEval_SaveThread. Without the call to PyEval_SaveThread, thread * specific state (such as the system trace hook), will be lost * between invocations of Python code. */ PyEval_InitThreads(); @@ -755,10 +755,6 @@ Python_Init(void) if (PythonMod_Init()) goto fail; - /* The first python thread is vim's, release the lock. */ - Python_SaveThread(); - pygilstate = PyGILState_Ensure(); - globals = PyModule_GetDict(PyImport_AddModule("__main__")); /* Remove the element from sys.path that was added because of our @@ -767,7 +763,14 @@ Python_Init(void) * the current directory in sys.path. */ PyRun_SimpleString("import sys; sys.path = filter(lambda x: x != '/must>not&exist', sys.path)"); - PyGILState_Release(pygilstate); + /* lock is created and acquired in PyEval_InitThreads() and thread + * state is created in Py_Initialize() + * there _PyGILState_NoteThreadState() also sets gilcounter to 1 + * (python must have threads enabled!) + * so the following does both: unlock GIL and save thread state in TLS + * without deleting thread state + */ + PyEval_SaveThread(); initialised = 1; } diff --git a/src/if_python3.c b/src/if_python3.c index 4067517acda95383933057587e52e140e8ca37ad..5311483ddb94cf1f3c6ef981d27c6d77fdc1b4e2 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -729,13 +729,11 @@ Python3_Init(void) #else PyMac_Initialize(); #endif - /* Initialise threads, and save the state using PyGILState_Ensure. - * Without the call to PyGILState_Ensure, thread specific state (such - * as the system trace hook), will be lost between invocations of - * Python code. */ + /* Initialise threads, and below save the state using + * PyEval_SaveThread. Without the call to PyEval_SaveThread, thread + * specific state (such as the system trace hook), will be lost + * between invocations of Python code. */ PyEval_InitThreads(); - pygilstate = PyGILState_Ensure(); - #ifdef DYNAMIC_PYTHON3 get_py3_exceptions(); #endif @@ -754,13 +752,14 @@ Python3_Init(void) */ PyRun_SimpleString("import vim; import sys; sys.path = list(filter(lambda x: not x.endswith('must>not&exist'), sys.path))"); - // lock is created and acquired in PyEval_InitThreads() and thread - // state is created in Py_Initialize() - // there _PyGILState_NoteThreadState() also sets gilcounter to 1 - // (python must have threads enabled!) - // so the following does both: unlock GIL and save thread state in TLS - // without deleting thread state - PyGILState_Release(pygilstate); + /* lock is created and acquired in PyEval_InitThreads() and thread + * state is created in Py_Initialize() + * there _PyGILState_NoteThreadState() also sets gilcounter to 1 + * (python must have threads enabled!) + * so the following does both: unlock GIL and save thread state in TLS + * without deleting thread state + */ + PyEval_SaveThread(); py3initialised = 1; } diff --git a/src/testdir/test86.in b/src/testdir/test86.in index 1309643d8b1d222c30fe732fb9ccbbaac3d75c82..71635bda2f05817d3b470edfd9486b7fbfba3c22 100644 --- a/src/testdir/test86.in +++ b/src/testdir/test86.in @@ -267,6 +267,54 @@ EOF : $put =toput : endtry :endfor +:" +:" threading +:let l = [0] +:py l=vim.bindeval('l') +:py <<EOF +import threading +import time + +class T(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.t = 0 + self.running = True + + def run(self): + while self.running: + self.t += 1 + time.sleep(0.1) + +t = T() +t.start() +EOF +:sleep 1 +:py t.running = False +:py t.join() +:py l[0] = t.t > 8 # check if the background thread is working +:$put =string(l) +:" +:" settrace +:let l = [] +:py l=vim.bindeval('l') +:py <<EOF +import sys + +def traceit(frame, event, arg): + global l + if event == "line": + l.extend([frame.f_lineno]) + return traceit + +def trace_main(): + for i in range(5): + pass +EOF +:py sys.settrace(traceit) +:py trace_main() +:py sys.settrace(None) +:$put =string(l) :endfun :" :call Test() diff --git a/src/testdir/test86.ok b/src/testdir/test86.ok index 5ef8689a24191e6d2727a27df3625a87fab0df39..3dd8d799444c4182d6c29c32ed1c29fc82b3c7ca 100644 --- a/src/testdir/test86.ok +++ b/src/testdir/test86.ok @@ -63,3 +63,5 @@ ll:[1] {"\0": 1}: Vim(let):E859: undefined_name: Vim(let):E858: vim: Vim(let):E859: +[1] +[1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1] diff --git a/src/testdir/test87.in b/src/testdir/test87.in index 1d7ccedd51da7d1cf4555b9063e5ca78f33e514b..5115e5be7362289e00469cc00f44d2a326c5e8d6 100644 --- a/src/testdir/test87.in +++ b/src/testdir/test87.in @@ -267,6 +267,54 @@ EOF : $put =toput : endtry :endfor +:" +:" threading +:let l = [0] +:py3 l=vim.bindeval('l') +:py3 <<EOF +import threading +import time + +class T(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.t = 0 + self.running = True + + def run(self): + while self.running: + self.t += 1 + time.sleep(0.1) + +t = T() +t.start() +EOF +:sleep 1 +:py3 t.running = False +:py3 t.join() +:py3 l[0] = t.t > 8 # check if the background thread is working +:$put =string(l) +:" +:" settrace +:let l = [] +:py3 l=vim.bindeval('l') +:py3 <<EOF +import sys + +def traceit(frame, event, arg): + global l + if event == "line": + l += [frame.f_lineno] + return traceit + +def trace_main(): + for i in range(5): + pass +EOF +:py3 sys.settrace(traceit) +:py3 trace_main() +:py3 sys.settrace(None) +:$put =string(l) :endfun :" :call Test() diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok index 4c0bb799d7948171a676d5e8e27aecfa31434562..3dffa26d475bf8739fdcccceb47ed25c2958899b 100644 --- a/src/testdir/test87.ok +++ b/src/testdir/test87.ok @@ -63,3 +63,5 @@ ll:[1] {"\0": 1}: Vim(let):E861: undefined_name: Vim(let):E860: vim: Vim(let):E861: +[1] +[1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1] diff --git a/src/version.c b/src/version.c index 1c23a5e87320e19490a55636065fad07f5059989..c716154e236cd18e03a4450c9adae65a07e57515 100644 --- a/src/version.c +++ b/src/version.c @@ -725,6 +725,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 808, /**/ 807, /**/