*
* \param tv A ThreadVars instance corresponding to the thread that has to be
* killed.
+ *
+ * \retval r 1 killed succesfully
+ * 0 not yet ready, needs another look
*/
-void TmThreadKillThread(ThreadVars *tv)
+static int TmThreadKillThread(ThreadVars *tv)
{
int i = 0;
- if (tv == NULL)
- return;
+ BUG_ON(tv == NULL);
+
+ /* kill only once :) */
+ if (TmThreadsCheckFlag(tv, THV_DEAD)) {
+ return 1;
+ }
if (tv->inq != NULL) {
/* we wait till we dry out all the inq packets, before we
if (!(strlen(tv->inq->name) == strlen("packetpool") &&
strcasecmp(tv->inq->name, "packetpool") == 0)) {
PacketQueue *q = &trans_q[tv->inq->id];
- while (q->len != 0) {
- usleep(1000);
+ if (q->len != 0) {
+ return 0;
}
}
}
TmThreadsSetFlag(tv, THV_DEINIT);
/* to be sure, signal more */
- int cnt = 0;
- while (1) {
- if (TmThreadsCheckFlag(tv, THV_CLOSED)) {
- SCLogDebug("signalled the thread %" PRId32 " times", cnt);
- break;
- }
-
- cnt++;
-
+ if (!(TmThreadsCheckFlag(tv, THV_CLOSED))) {
if (tv->InShutdownHandler != NULL) {
tv->InShutdownHandler(tv);
}
if (tv->ctrl_cond != NULL ) {
pthread_cond_broadcast(tv->ctrl_cond);
}
-
- usleep(100);
+ return 0;
}
if (tv->outctx != NULL) {
if (tmqh->OutHandlerCtxFree != NULL) {
tmqh->OutHandlerCtxFree(tv->outctx);
+ tv->outctx = NULL;
}
}
- /* join it */
+ /* join it and flag it as dead */
pthread_join(tv->t, NULL);
SCLogDebug("thread %s stopped", tv->name);
-
- return;
+ TmThreadsSetFlag(tv, THV_DEAD);
+ return 1;
}
/** \internal
return slots;
}
+#define MIN_WAIT_TIME 100
void TmThreadKillThreadsFamily(int family)
{
ThreadVars *tv = NULL;
+ unsigned int sleep = MIN_WAIT_TIME;
- if ((family < 0) || (family >= TVT_MAX))
- return;
+ BUG_ON((family < 0) || (family >= TVT_MAX));
+again:
SCMutexLock(&tv_root_lock);
tv = tv_root[family];
while (tv) {
- TmThreadKillThread(tv);
+ int r = TmThreadKillThread(tv);
+ if (r == 0) {
+ SCMutexUnlock(&tv_root_lock);
+ usleep(sleep);
+ sleep += MIN_WAIT_TIME; /* slowly back off */
+ goto again;
+ }
+ sleep = MIN_WAIT_TIME; /* reset */
tv = tv->next;
}
int i = 0;
uint16_t mgt_num = 0;
uint16_t ppt_num = 0;
+
+ uint64_t slept = 0;
+
again:
SCMutexLock(&tv_root_lock);
for (i = 0; i < TVT_MAX; i++) {
tv = tv_root[i];
while (tv != NULL) {
+ if (TmThreadsCheckFlag(tv, (THV_CLOSED|THV_DEAD))) {
+ SCMutexUnlock(&tv_root_lock);
+
+ SCLogError(SC_ERR_THREAD_INIT, "thread \"%s\" failed to "
+ "initialize: flags %04x", tv->name,
+ SC_ATOMIC_GET(tv->flags));
+ return TM_ECODE_FAILED;
+ }
+
if (!(TmThreadsCheckFlag(tv, THV_INIT_DONE))) {
SCMutexUnlock(&tv_root_lock);
+
+ if (slept > (120*1000000)) {
+ SCLogError(SC_ERR_THREAD_INIT, "thread \"%s\" failed to "
+ "initialize in time: flags %04x", tv->name,
+ SC_ATOMIC_GET(tv->flags));
+ return TM_ECODE_FAILED;
+ }
+
/* sleep a little to give the thread some
* time to finish initialization */
usleep(100);
+ slept += 100;
goto again;
}