diff --git a/include/QF/gib_thread.h b/include/QF/gib_thread.h index 077f2e739..268d80d80 100644 --- a/include/QF/gib_thread.h +++ b/include/QF/gib_thread.h @@ -47,6 +47,7 @@ typedef struct gib_event_s { void GIB_Thread_Add (gib_thread_t *thread); void GIB_Thread_Remove (gib_thread_t *thread); +void GIB_Thread_Delete (gib_thread_t *thread); gib_thread_t *GIB_Thread_Find (unsigned long int id); gib_thread_t *GIB_Thread_New (void); void GIB_Thread_Execute (void); diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 42550c720..689e3beb9 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -618,12 +618,16 @@ GIB_Thread_Kill_f (void) id); return; } - // Set error condition on the top of the stack so the thread will exit - // We can't simply nuke the thread, as it would cause the stack walker - // to segfault if a thread kills itself. - for (cur = thread->cbuf; - cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down); - cur->state = CBUF_STATE_ERROR; + + // If we are currently running this thread, set an error state so we exit it cleanly + // if it were simply nuked, a crash would result + for (cur = thread->cbuf; cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down) + if (cur == cbuf_active) { + cur->state = CBUF_STATE_ERROR; + return; + } + GIB_Thread_Remove (thread); + GIB_Thread_Delete (thread); } } diff --git a/libs/gib/gib_thread.c b/libs/gib/gib_thread.c index f842f16b4..60f7845a7 100644 --- a/libs/gib/gib_thread.c +++ b/libs/gib/gib_thread.c @@ -100,7 +100,7 @@ GIB_Thread_New (void) return new; } -static void +void GIB_Thread_Delete (gib_thread_t * thread) { Cbuf_DeleteStack (thread->cbuf); diff --git a/libs/util/cbuf.c b/libs/util/cbuf.c index 917c28fda..9abf403ff 100644 --- a/libs/util/cbuf.c +++ b/libs/util/cbuf.c @@ -132,6 +132,7 @@ Cbuf_Reset (cbuf_t *cbuf) { cbuf->resumetime = 0.0; cbuf->args->argc = 0; + cbuf->state = CBUF_STATE_NORMAL; if (cbuf->interpreter->reset) cbuf->interpreter->reset (cbuf); } @@ -168,7 +169,6 @@ void Cbuf_Execute (cbuf_t *cbuf) { cbuf_active = cbuf; - cbuf->state = CBUF_STATE_NORMAL; cbuf->interpreter->execute (cbuf); } @@ -188,12 +188,15 @@ Cbuf_Execute_Stack (cbuf_t *cbuf) Cbuf_Execute (sp); if (sp->state) { if (sp->state == CBUF_STATE_STACK) { + sp->state = CBUF_STATE_NORMAL; sp = sp->down; continue; } else if (sp->state == CBUF_STATE_ERROR) break; - else + else { + sp->state = CBUF_STATE_NORMAL; return; + } } sp->state = CBUF_STATE_JUNK; sp = sp->up;