From 3e4e3248e72ab15e69c78f42258d000e41dafcdb Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 3 Oct 2007 23:33:49 +0000 Subject: [PATCH] change order of thread cleanup to avoid python crash --- panda/src/pipeline/contextSwitch.c | 10 ++++++---- panda/src/pipeline/pythonThread.cxx | 7 ++++--- panda/src/pipeline/threadSimpleManager.cxx | 15 +++++++++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/panda/src/pipeline/contextSwitch.c b/panda/src/pipeline/contextSwitch.c index 329da296e7..7738c09641 100644 --- a/panda/src/pipeline/contextSwitch.c +++ b/panda/src/pipeline/contextSwitch.c @@ -45,8 +45,9 @@ init_thread_context(struct ThreadContext *context, makecontext(&context->_ucontext, (void (*)())&begin_context, 2, thread_func, data); } -void save_thread_context(struct ThreadContext *context, - ContextFunction *next_context, void *data) { +void +save_thread_context(struct ThreadContext *context, + ContextFunction *next_context, void *data) { /* getcontext requires us to use a volatile auto variable to differentiate between pass 1 (immediate return) and pass 2 (return from setcontext). */ @@ -297,8 +298,9 @@ init_thread_context(struct ThreadContext *context, setup_context_1(); } -void save_thread_context(struct ThreadContext *context, - ContextFunction *next_context, void *data) { +void +save_thread_context(struct ThreadContext *context, + ContextFunction *next_context, void *data) { if (cs_setjmp(context->_jmp_context) != 0) { /* We have just returned from longjmp. In this case, return from the function. The stack is still good. */ diff --git a/panda/src/pipeline/pythonThread.cxx b/panda/src/pipeline/pythonThread.cxx index 9e8c2382c0..f6ed9333bc 100644 --- a/panda/src/pipeline/pythonThread.cxx +++ b/panda/src/pipeline/pythonThread.cxx @@ -33,13 +33,14 @@ PythonThread(PyObject *function, PyObject *args, const string &name, const string &sync_name) : Thread(name, sync_name) { + _function = function; + Py_INCREF(_function); + _args = NULL; _result = NULL; - _function = function; if (!PyCallable_Check(_function)) { nassert_raise("Invalid function passed to PythonThread constructor"); } - Py_INCREF(_function); if (args == Py_None) { // None means no arguments; create an empty tuple. @@ -113,7 +114,7 @@ thread_main() { // thread state per OS-level thread, which is not true in the case // of SIMPLE_THREADS. - PyThreadState *orig_thread_state = PyThreadState_Swap(NULL); + PyThreadState *orig_thread_state = PyThreadState_Get(); PyInterpreterState *istate = orig_thread_state->interp; PyThreadState *new_thread_state = PyThreadState_New(istate); PyThreadState_Swap(new_thread_state); diff --git a/panda/src/pipeline/threadSimpleManager.cxx b/panda/src/pipeline/threadSimpleManager.cxx index 18a0135044..1eea09d6b3 100644 --- a/panda/src/pipeline/threadSimpleManager.cxx +++ b/panda/src/pipeline/threadSimpleManager.cxx @@ -200,6 +200,14 @@ preempt(ThreadSimpleImpl *thread) { //////////////////////////////////////////////////////////////////// void ThreadSimpleManager:: next_context() { + // Delete any threads that need it. We can't delete the current + // thread, though. + while (!_finished.empty() && _finished.front() != _current_thread) { + ThreadSimpleImpl *finished_thread = _finished.front(); + _finished.pop_front(); + unref_delete(finished_thread->_parent_obj); + } + // Mark the current thread's resume point. #ifdef HAVE_PYTHON @@ -268,6 +276,7 @@ prepare_for_exit() { next_context(); + // Delete any remaining threads. while (!_finished.empty() && _finished.front() != _current_thread) { ThreadSimpleImpl *finished_thread = _finished.front(); _finished.pop_front(); @@ -410,12 +419,6 @@ st_choose_next_context(void *data) { //////////////////////////////////////////////////////////////////// void ThreadSimpleManager:: choose_next_context() { - while (!_finished.empty() && _finished.front() != _current_thread) { - ThreadSimpleImpl *finished_thread = _finished.front(); - _finished.pop_front(); - unref_delete(finished_thread->_parent_obj); - } - _current_thread = NULL; double now = get_current_time();