--- libclamav/c++/bytecode2llvm.cpp.orig	2011-05-13 07:25:31.000000000 -0400
+++ libclamav/c++/bytecode2llvm.cpp	2011-06-29 09:32:09.000000000 -0400
@@ -1874,119 +1874,30 @@
 INITIALIZE_PASS_END(RuntimeLimits, "rl" ,"Runtime Limits", false, false)
 #endif
 
-static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER;
-static int watchdog_running = 0;
-
-struct watchdog_item {
+struct bc_watchdog {
     volatile uint8_t* timeout;
-    struct timespec abstimeout;
-    struct watchdog_item *next;
+    struct timespec * abstimeout;
+    pthread_mutex_t   mutex;
+    pthread_cond_t    cond;
+    int finished;
 };
 
-static struct watchdog_item* watchdog_head = NULL;
-static struct watchdog_item* watchdog_tail = NULL;
-
-#define WATCHDOG_IDLE 10
 static void *bytecode_watchdog(void *arg)
 {
-    struct timeval tv;
-    struct timespec out;
-
-    pthread_mutex_lock(&watchdog_mutex);
-    watchdog_running = 1;
-    if (cli_debug_flag)
-	cli_dbgmsg_internal("bytecode watchdog is running\n");
-    do {
-	struct watchdog_item *item;
-	gettimeofday(&tv, NULL);
-	out.tv_sec = tv.tv_sec + WATCHDOG_IDLE;
-	out.tv_nsec = tv.tv_usec*1000;
-	/* wait for some work, up to WATCHDOG_IDLE time */
-	while (watchdog_head == NULL &&
-	       pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex,
-				      &out) != ETIMEDOUT) {}
-	if (watchdog_head == NULL)
-	    break;
-	/* wait till timeout is reached on this item */
-	item = watchdog_head;
-	while (item == watchdog_head &&
-	       pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex,
-				      &item->abstimeout) != ETIMEDOUT) {}
-	if (item != watchdog_head)
-	    continue;/* got removed meanwhile */
-	/* timeout reached, signal it to bytecode */
-	*item->timeout = 1;
+    int ret = 0;
+    struct bc_watchdog *w = (struct bc_watchdog*)arg;
+    pthread_mutex_lock(&w->mutex);
+    while (!w->finished && ret != ETIMEDOUT) {
+	ret = pthread_cond_timedwait(&w->cond, &w->mutex, w->abstimeout);
+    }
+    pthread_mutex_unlock(&w->mutex);
+    if (ret == ETIMEDOUT) {
+	*w->timeout = 1;
 	cli_warnmsg("[Bytecode JIT]: Bytecode run timed out, timeout flag set\n");
-	watchdog_head = item->next;
-	if (!watchdog_head)
-	    watchdog_tail = NULL;
-    } while (1);
-    watchdog_running = 0;
-    if (cli_debug_flag)
-	cli_dbgmsg_internal("bytecode watchdog quiting\n");
-    pthread_mutex_unlock(&watchdog_mutex);
+    }
     return NULL;
 }
 
-extern "C" const char *cli_strerror(int errnum, char* buf, size_t len);
-static void watchdog_disarm(struct watchdog_item *item)
-{
-    struct watchdog_item *q, *p = NULL;
-    if (!item)
-	return;
-    pthread_mutex_lock(&watchdog_mutex);
-    for (q=watchdog_head;q && q != item;p = q, q = q->next) {}
-    if (q == item) {
-	if (p)
-	    p->next = q->next;
-	if (q == watchdog_head)
-	    watchdog_head = q->next;
-	if (q == watchdog_tail)
-	    watchdog_tail = p;
-    }
-    pthread_mutex_unlock(&watchdog_mutex);
-}
-
-static int watchdog_arm(struct watchdog_item *item, int ms, volatile uint8_t *timeout)
-{
-    int rc = 0;
-    struct timeval tv0;
-
-    *timeout = 0;
-    item->timeout = timeout;
-    item->next = NULL;
-
-    gettimeofday(&tv0, NULL);
-    tv0.tv_usec += ms * 1000;
-    item->abstimeout.tv_sec = tv0.tv_sec + tv0.tv_usec/1000000;
-    item->abstimeout.tv_nsec = (tv0.tv_usec%1000000)*1000;
-
-    pthread_mutex_lock(&watchdog_mutex);
-    if (!watchdog_running) {
-	pthread_t thread;
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-	if ((rc = pthread_create(&thread, &attr, bytecode_watchdog, NULL))) {
-	    char buf[256];
-	    cli_errmsg("(watchdog) pthread_create failed: %s\n", cli_strerror(rc, buf, sizeof(buf)));
-	}
-	pthread_attr_destroy(&attr);
-    }
-    if (!rc) {
-	if (watchdog_tail)
-	    watchdog_tail->next = item;
-	watchdog_tail = item;
-	if (!watchdog_head)
-	    watchdog_head = item;
-    }
-    pthread_cond_signal(&watchdog_cond);
-    pthread_mutex_unlock(&watchdog_mutex);
-    return rc;
-}
-
 static int bytecode_execute(intptr_t code, struct cli_bc_ctx *ctx)
 {
     ScopedExceptionHandler handler;
@@ -2002,12 +1913,15 @@
     return CL_EBYTECODE;
 }
 
+extern "C" const char *cli_strerror(int errnum, char* buf, size_t len);
 int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx,
 		       const struct cli_bc_func *func)
 {
+    char buf[1024];
     int ret;
+    pthread_t thread;
     struct timeval tv0, tv1;
-    struct watchdog_item witem;
+    uint32_t timeoutus;
     // no locks needed here, since LLVM automatically acquires a JIT lock
     // if needed.
     void *code = bcs->engine->compiledFunctions[func];
@@ -2018,20 +1932,40 @@
 			func->numArgs);
 	return CL_EBYTECODE;
     }
-    if (cli_debug_flag)
 	gettimeofday(&tv0, NULL);
+    struct timespec abstime;
+
+    timeoutus = (ctx->bytecode_timeout%1000)*1000 + tv0.tv_usec;
+    abstime.tv_sec = tv0.tv_sec + ctx->bytecode_timeout/1000 + timeoutus/1000000;
+    abstime.tv_nsec = 1000*(timeoutus%1000000);
+    ctx->timeout = 0;
+
+    struct bc_watchdog w = {
+	&ctx->timeout,
+	&abstime,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_COND_INITIALIZER,
+	0
+    };
 
     if (ctx->bytecode_timeout) {
 	/* only spawn if timeout is set.
 	 * we don't set timeout for selfcheck (see bb #2235) */
-	if (watchdog_arm(&witem, ctx->bytecode_timeout, &ctx->timeout))
+	if ((ret = pthread_create(&thread, NULL, bytecode_watchdog, &w))) {
+	    cli_warnmsg("[Bytecode JIT]: Bytecode: failed to create new thread :%s!\n",
+			cli_strerror(ret, buf, sizeof(buf)));
 	    return CL_EBYTECODE;
     }
+    }
 
     ret = bytecode_execute((intptr_t)code, ctx);
-
-    if (ctx->bytecode_timeout)
-	watchdog_disarm(&witem);
+    pthread_mutex_lock(&w.mutex);
+    w.finished = 1;
+    pthread_cond_signal(&w.cond);
+    pthread_mutex_unlock(&w.mutex);
+    if (ctx->bytecode_timeout) {
+	pthread_join(thread, NULL);
+    }
 
     if (cli_debug_flag) {
 	long diff;
