--- daemon.cpp	Thu Oct 31 11:13:12 2002
+++ daemon.cpp	Thu Mar 11 21:38:58 2004
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <dlfcn.h>
 #include <string.h>
+#include <time.h>
 #include <string>
 #include <vector>
 #include "sqldb.h"
@@ -76,6 +77,7 @@
 #include "cache.h"
 
 int MaxThreads = 10;
+int max_idle_time = 60;
 string ConfDir = CONF_DIR;
 string DataDir = DATA_DIR;
 
@@ -445,6 +467,10 @@
 			{
 				MaxThreads = atoi(Trim(str + 10, "= \t\r\n"));
 			}
+			else if (!STRNCASECMP(str, "MaxIdleTime"))
+			{
+					max_idle_time = atoi(Trim(str + 11, "= \t\r\n"));
+			}
 			else if (!STRNCASECMP(str, "DebugLevel"))
 			{
 				logger.setloglevel(Trim(str + 10, "= \t\r\n"));
@@ -1068,33 +1116,59 @@
 void* processReqs(void* p)
 {
 	CWorkerThread* thread = (CWorkerThread*)p;
+	time_t last_query = time(NULL);
+	int timeout = 0;
+	thread->m_parent->m_threads++;
 	while (doit_forever)
 	{
 		// Wait for event, posted in CWorkerThreadList::processReq
-		thread->m_req.Wait();
-		// Create search context
-		CSearchContext ctx(thread->m_database, thread->m_socket);
-		while (doit_forever)
-		{
-			// Process one query
-			processReq1(&ctx);
-			ctx.m_socket.Close();
-			{
-				CLocker lock(&thread->m_parent->m_mutex);
-				if (thread->m_parent->IsWaiting())
-				{
-					// Process other queries in the loop buffer
-					ctx.m_socket = thread->m_parent->PopFirstWaiting();
-				}
-				else
+		timeout = thread->m_req.Wait(1000);
+		if(!timeout)
+		{
+			time(&last_query);
+			// Create search context
+			CSearchContext ctx(thread->m_database, thread->m_socket);
+			while (doit_forever)
+			{
+				// Process one query
+				processReq1(&ctx);
+				ctx.m_socket.Close();
 				{
-					// Make thread available for other requests
-					thread->Insert(&thread->m_parent->m_first);
-					break;
+					CLocker lock(&thread->m_parent->m_mutex);
+					if (thread->m_parent->IsWaiting())
+					{
+						// Process other queries in the loop buffer
+						ctx.m_socket = thread->m_parent->PopFirstWaiting();
+					}
+					else
+					{
+						// Make thread available for other requests
+						if(!thread->m_parent->m_first)
+							thread->m_parent->m_first = thread;
+							//thread->Insert(thread);
+						else
+							thread->Insert(thread->m_parent->m_first);
+						break;
+					}
 				}
 			}
 		}
+		else
+		{
+			if((time(NULL) - last_query) > max_idle_time)
+				break;
+		}
 	}
+	// create scope for CLocker
+	{
+		CLocker lock(&thread->m_parent->m_mutex);
+		if(!thread->m_removed)
+			thread->Remove();
+	}
+	// unlocked and removed...
+	if(MultiDBConnections)
+		thread->m_database->CloseDb();
+	thread->m_parent->m_threads--;
 	delete thread;
 	return NULL; // to make g++ happy
 }
@@ -1130,7 +1204,6 @@
 			if (thread_stack_size)
 				pthread_attr_setstacksize(&attr, thread_stack_size);
 			pthread_create(&thread->m_thread, &attr, processReqs, thread);
-			m_threads++;
 		}
 		else
 		{
@@ -1141,7 +1214,6 @@
 	}
 	else
 	{
-		// Remove first worker thread from the linked list
 		thread = m_first->Remove();
 	}
 	thread->m_socket = csock;
@@ -1175,11 +1247,26 @@
 		logger.log(CAT_NET, L_ERR, "Error %d in socket(): %s\n", errno, strerror(errno));
 		return 4;
 	}
-	int rc = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
-	if (rc < 0)
+	int x = 1;
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &x, sizeof(x));
+	int retrycount = 0;
+	int rc;
+	while(retrycount < 5)
 	{
-		logger.log(CAT_NET, L_ERR, "Error %d in bind(): %s\n", errno, strerror(errno));
-		return 5;
+		rc = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
+		if (rc < 0 && retrycount >= 5)
+		{
+			logger.log(CAT_NET, L_ERR, "Error %d in bind(): %s\n", errno, strerror(errno));
+			return 5;
+		}
+		else
+		{
+			retrycount++;
+			timespec ts;
+			ts.tv_sec = 1;
+			ts.tv_nsec = 0;
+			nanosleep(&ts,NULL);
+		}
 	}
 	rc = listen(sock, 10);
 	if (rc < 0)

