that_thread = this_thread;
this_thread = this_thread->next;
+ if ((that_thread->state == CTDL_THREAD_STOP_REQ || that_thread->state == CTDL_THREAD_STOPPING)
+ && (!citthread_equal(that_thread->tid, citthread_self())))
+ that_thread->stop_ticker++;
+
+ if (that_thread->stop_ticker == 5)
+ {
+ CtdlLogPrintf(CTDL_DEBUG, "Thread System: The thread \"%s\" (0x%08lx) failed to self terminate withing 5 ticks. Canceling it.\n", that_thread->name, that_thread->tid);
+ if ((that_thread->flags & CTDLTHREAD_WORKER) == 0)
+ CtdlLogPrintf(CTDL_INFO, "Thread System: A non worker thread was canceled this may cause message loss.\n");
+ that_thread->state = CTDL_THREAD_CANCELLED;
+ that_thread->stop_ticker++;
+ citthread_cancel(that_thread->tid);
+ continue;
+ }
+
/* Do we need to clean up this thread? */
- if (that_thread->state != CTDL_THREAD_EXITED)
+ if ((that_thread->state != CTDL_THREAD_EXITED) && (that_thread->state != CTDL_THREAD_CANCELLED))
{
if(that_thread->flags & CTDLTHREAD_WORKER)
workers++; /* Sanity check on number of worker threads */
else if (ret == ESRCH)
CtdlLogPrintf(CTDL_DEBUG, "Garbage collection, no thread to join on.\n");
else if (ret != 0)
- CtdlLogPrintf(CTDL_DEBUG, "Garbage collection, citthread_join returned an unknown error.\n");
+ CtdlLogPrintf(CTDL_DEBUG, "Garbage collection, citthread_join returned an unknown error(%d).\n", ret);
/*
* Now we own that thread entry
*/
void *user_args; /* Arguments passed to this threads work function */
long flags; /* Flags that describe this thread */
enum CtdlThreadState state; /* Flag to show state of this thread */
+ int stop_ticker; /* A counter to determine how long it has taken for this thread to exit */
citthread_mutex_t ThreadMutex; /* A mutex to sync this thread to others if this thread allows (also used for sleeping) */
citthread_cond_t ThreadCond; /* A condition variable to sync this thread with others */
citthread_mutex_t SleepMutex; /* A mutex for sleeping */