|
From: <gne...@us...> - 2007-10-19 09:46:44
|
Update of /cvsroot/aolserver/aolserver/nsd In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv19049 Modified Files: driver.c queue.c Log Message: Better fix for BUG #1615787 in aolserver 4.5. Although the original fix apparently helped for www.openacs.org, it appears to simply change the timing, but did not fix the problem itself. The problem was that under limited resource configurations (e.g. maxthreads 5, maxconnections 3) and heavy traffic, incoming requests were queued but not processed in new connection threads. The situation was especially bad, when the number of queued requests was larger than maxconnections, since after processing n requests the server was idling with a high number of queued requests. New requests were put to the end of the queue while old (maybe already timed-out) requests are being served. The server appeared to hang. The current fix cares for queued requests even when maxconns is exceeded. A maybe better approach is to limit the number of queued requests or to restart automatically threads when a thread exists due to maxconns exceeded. Index: driver.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/driver.c,v retrieving revision 1.56 retrieving revision 1.57 diff -C2 -d -r1.56 -r1.57 *** driver.c 15 Dec 2006 17:26:57 -0000 1.56 --- driver.c 19 Oct 2007 09:46:38 -0000 1.57 *************** *** 949,958 **** /* - * Register an at-ready callback to trigger the poll. - */ - - Ns_RegisterAtReady(TriggerDriver, drvPtr); - - /* * Loop forever until signalled to shutdown and all * connections are complete and gracefully closed. --- 949,952 ---- *************** *** 1314,1318 **** Ns_DStringPrintf(drvPtr->queryPtr, "time %ld:%ld " ! "spins %ld accepts %u queued %u reads %u " "dropped %u overflow %d timeout %u", now.sec, now.usec, --- 1308,1312 ---- Ns_DStringPrintf(drvPtr->queryPtr, "time %ld:%ld " ! "spins %d accepts %u queued %u reads %u " "dropped %u overflow %d timeout %u", now.sec, now.usec, Index: queue.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/queue.c,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** queue.c 13 Apr 2006 19:06:24 -0000 1.38 --- queue.c 19 Oct 2007 09:46:38 -0000 1.39 *************** *** 185,189 **** --- 185,197 ---- create = 1; } + /* + Note that in situations, where the maximum number of + connection threads is reached (poolPtr->threads.idle == 0 and create == 0) + the request is queued without resources to process these. + One has to take care about that one restarts the queue, when + resources become available again. + */ ++poolPtr->queue.wait.num; + Ns_MutexUnlock(&poolPtr->lock); if (create) { *************** *** 370,374 **** Ns_MutexLock(&poolPtr->lock); ! while (poolPtr->threads.maxconns <= 0 || ncons-- > 0) { /* --- 378,394 ---- Ns_MutexLock(&poolPtr->lock); ! /* ! The last test (poolPtr->queue.wait.num > 0) might lead to situations ! where a single connection thread processes more than maxconns ! connection requests. This condition fixes situations, where the ! driver accepts more connection requests than resources available. ! When e.g. the number of queued requests is higher than connections per threads, ! this might lead to situations, where there server comes to a halt. ! Maybe it is a good idea to limit the number of queued requests or ! to start a new thread automatically, when the current one exists due ! to max conns. However, the test with the queue.wait.num consition ! is better than a hang. ! */ ! while (poolPtr->threads.maxconns <= 0 || ncons-- > 0 || poolPtr->queue.wait.num > 1) { /* *************** *** 386,394 **** status = NS_OK; ! while (!poolPtr->shutdown ! && status == NS_OK ! && poolPtr->queue.wait.firstPtr == NULL) { ! status = Ns_CondTimedWait(&poolPtr->cond, &poolPtr->lock, timePtr); ! } if (poolPtr->queue.wait.firstPtr == NULL) { msg = "timeout waiting for connection"; --- 406,420 ---- status = NS_OK; ! ! if (poolPtr->queue.wait.num == 0) { ! /* ! nothing is queued, we wait for a queue entry ! */ ! while (!poolPtr->shutdown ! && status == NS_OK ! && poolPtr->queue.wait.firstPtr == NULL) { ! status = Ns_CondTimedWait(&poolPtr->cond, &poolPtr->lock, timePtr); ! } ! } if (poolPtr->queue.wait.firstPtr == NULL) { msg = "timeout waiting for connection"; |