From 9e00a5a28979b46bca0f4c62c21ce6127f9f0f78 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 20 Dec 2013 09:37:05 +0000 Subject: [PATCH] [0.3.x] fixed: compability with GILState API git-svn-id: https://pykd.svn.codeplex.com/svn@86899 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/windbgext.cpp | 220 ++++++++++++++++++++++++++++++++------------- 1 file changed, 160 insertions(+), 60 deletions(-) diff --git a/pykd/windbgext.cpp b/pykd/windbgext.cpp index 86e2534..251e8d6 100644 --- a/pykd/windbgext.cpp +++ b/pykd/windbgext.cpp @@ -94,6 +94,124 @@ void PykdExt::tearDown() /////////////////////////////////////////////////////////////////////////////// +class InterprterVirt +{ +public: + InterprterVirt() + { + PyThreadState *threadState = PyGILState_GetThisThreadState(); + + modules = threadState->interp->modules; + modules_reloading = threadState->interp->modules_reloading; + sysdict = threadState->interp->sysdict; + builtins = threadState->interp->builtins; + codec_search_path = threadState->interp->codec_search_path; + codec_search_cache = threadState->interp->codec_search_cache; + codec_error_registry = threadState->interp->codec_error_registry; + + newThread = NULL; + } + + ~InterprterVirt() + { + PyThreadState *threadState =PyGILState_GetThisThreadState(); + + if ( threadState->interp->modules != modules ) + { + Py_DECREF(threadState->interp->modules); + threadState->interp->modules = modules; + } + + if ( threadState->interp->modules_reloading != modules_reloading ) + { + Py_DECREF(threadState->interp->modules_reloading); + threadState->interp->modules_reloading = modules_reloading; + } + + if ( threadState->interp->sysdict != sysdict ) + { + Py_DECREF(threadState->interp->sysdict); + threadState->interp->sysdict = sysdict; + } + + if ( threadState->interp->builtins != builtins ) + { + Py_DECREF(threadState->interp->builtins); + threadState->interp->builtins = builtins; + } + + if ( threadState->interp->codec_search_path != codec_search_path ) + { + Py_DECREF(threadState->interp->codec_search_path); + threadState->interp->codec_search_path = codec_search_path; + } + + if ( threadState->interp->codec_search_cache != codec_search_cache ) + { + Py_DECREF(threadState->interp->codec_search_cache); + threadState->interp->codec_search_cache = codec_search_cache; + } + + if ( threadState->interp->codec_error_registry != codec_error_registry ) + { + Py_DECREF(threadState->interp->codec_error_registry); + threadState->interp->codec_search_cache = codec_error_registry; + } + + if (newThread) + { + PyThreadState* current = PyThreadState_Get(); + PyThreadState_Swap(newThread); + Py_EndInterpreter(newThread); + PyThreadState_Swap(current); + } + + } + + void fork() + { + PyThreadState *threadState =PyGILState_GetThisThreadState(); + newThread = Py_NewInterpreter(); + + threadState->interp->modules = newThread->interp->modules; + Py_INCREF(threadState->interp->modules); + + threadState->interp->modules_reloading = newThread->interp->modules_reloading; + Py_INCREF(threadState->interp->modules_reloading); + + threadState->interp->sysdict = newThread->interp->sysdict; + Py_INCREF(threadState->interp->sysdict); + + threadState->interp->builtins = newThread->interp->builtins; + Py_INCREF(threadState->interp->builtins); + + threadState->interp->codec_search_path = newThread->interp->codec_search_path; + Py_INCREF(threadState->interp->codec_search_path); + + threadState->interp->codec_search_cache = newThread->interp->codec_search_cache; + Py_INCREF(threadState->interp->codec_search_cache); + + threadState->interp->codec_error_registry = newThread->interp->codec_error_registry; + Py_INCREF(threadState->interp->codec_error_registry); + + PyThreadState_Swap(threadState); + } + + +private: + + PyObject *modules; + PyObject *sysdict; + PyObject *builtins; + PyObject *modules_reloading; + PyObject *codec_search_path; + PyObject *codec_search_cache; + PyObject *codec_error_registry; + + PyThreadState *newThread; +}; + + KDLIB_EXT_COMMAND_METHOD_IMPL(PykdExt, py) { ArgsList args = getArgs(); @@ -175,75 +293,57 @@ KDLIB_EXT_COMMAND_METHOD_IMPL(PykdExt, py) PyEval_RestoreThread( m_pyState ); - if ( !global ) - { - globalState = PyThreadState_Swap( NULL ); + do { - localState = Py_NewInterpreter(); + InterprterVirt interpretrVirt; - python::object sys = python::import("sys"); - - sys.attr("stdout") = python::object( pykd::DbgOut() ); - sys.attr("stderr") = python::object( pykd::DbgOut() ); - sys.attr("stdin") = python::object( pykd::DbgIn() ); - } - - if ( args.size() == 0 ) - { - startConsole(); - } - else - { - std::string scriptFileName = getScriptFileName( args[0] ); - - // устанавиливаем питоновские аргументы - char **pythonArgs = new char* [ args.size() ]; - - pythonArgs[0] = const_cast(scriptFileName.c_str()); - - for ( size_t i = 1; i < args.size(); ++i ) - pythonArgs[i] = const_cast( args[i].c_str() ); - - PySys_SetArgv( (int)args.size(), pythonArgs ); - - delete[] pythonArgs; - - // получаем достпу к глобальному мапу ( нужен для вызова exec_file ) - python::object main = python::import("__main__"); - - python::object global(main.attr("__dict__")); - - try { - PykdInterruptWatch interruptWatch; - python::exec_file( scriptFileName.c_str(), global ); - } - catch( python::error_already_set const & ) + if ( !global ) { - printException(); + interpretrVirt.fork(); + + python::object sys = python::import("sys"); + + sys.attr("stdout") = python::object( pykd::DbgOut() ); + sys.attr("stderr") = python::object( pykd::DbgOut() ); + sys.attr("stdin") = python::object( pykd::DbgIn() ); } - } - if ( !global ) - { - PyInterpreterState *interpreter = localState->interp; - - while( interpreter->tstate_head != NULL ) + if ( args.size() == 0 ) { - PyThreadState *threadState = (PyThreadState*)(interpreter->tstate_head); - - PyThreadState_Clear(threadState); - - PyThreadState_Swap( NULL ); - - PyThreadState_Delete(threadState); + startConsole(); } - - PyInterpreterState_Clear(interpreter); + else + { + std::string scriptFileName = getScriptFileName( args[0] ); - PyInterpreterState_Delete(interpreter); + // устанавиливаем питоновские аргументы + char **pythonArgs = new char* [ args.size() ]; - PyThreadState_Swap( globalState ); - } + pythonArgs[0] = const_cast(scriptFileName.c_str()); + + for ( size_t i = 1; i < args.size(); ++i ) + pythonArgs[i] = const_cast( args[i].c_str() ); + + PySys_SetArgv( (int)args.size(), pythonArgs ); + + delete[] pythonArgs; + + // получаем достпу к глобальному мапу ( нужен для вызова exec_file ) + python::object main = python::import("__main__"); + + python::object global(main.attr("__dict__")); + + try { + PykdInterruptWatch interruptWatch; + python::exec_file( scriptFileName.c_str(), global ); + } + catch( python::error_already_set const & ) + { + printException(); + } + } + + } while( false); m_pyState = PyEval_SaveThread();