Browse code

set timeout to readtimeout after receiving a chunk (bb #1540). better checks and documentation for MaxQueue (bb #1521).

git-svn: trunk@5023

Török Edvin authored on 2009/04/06 18:26:11
Showing 3 changed files
... ...
@@ -1,3 +1,9 @@
1
+Mon Apr  6 12:02:38 EEST 2009 (edwin)
2
+-------------------------------------
3
+ * clamd/server-th.c, shared/optparser.c: set timeout to readtimeout
4
+ after receiving a chunk (bb #1540).  better checks and documentation
5
+ for MaxQueue (bb #1521).
6
+
1 7
 Fri Apr  3 15:30:34 CEST 2009 (tk)
2 8
 ----------------------------------
3 9
  * freshclam: short-term blacklisting of faulty mirrors;
... ...
@@ -603,13 +603,16 @@ static const unsigned char* parse_dispatch_cmd(client_conn_t *conn, struct fd_bu
603 603
 }
604 604
 
605 605
 //static const unsigned char* parse_dispatch_cmd(client_conn_t *conn, struct fd_buf *buf, size_t *ppos, int *error, const struct optstruct *opts, int readtimeout)
606
-static int handle_stream(client_conn_t *conn, struct fd_buf *buf, const struct optstruct *opts, int *error, size_t *ppos)
606
+static int handle_stream(client_conn_t *conn, struct fd_buf *buf, const struct optstruct *opts, int *error, size_t *ppos, int readtimeout)
607 607
 {
608 608
     int rc;
609 609
     size_t pos = *ppos;
610 610
     size_t cmdlen;
611 611
 
612 612
     logg("$mode == MODE_STREAM\n");
613
+    /* we received a chunk, set readtimeout */
614
+    time(&buf->timeout_at);
615
+    buf->timeout_at += readtimeout;
613 616
     if (!buf->chunksize) {
614 617
 	/* read chunksize */
615 618
 	if (buf->off >= 4) {
... ...
@@ -941,22 +944,40 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
941 941
 
942 942
 #if !defined(C_WINDOWS) && defined(RLIMIT_NOFILE)
943 943
     if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
944
-	if (max_queue*4 > rlim.rlim_cur) {
945
-	    max_queue = rlim.rlim_cur / 4;
946
-	    logg("^MaxQueue value too high, lowering to: %d\n", max_queue);
947
-	} else if (max_queue < 2*max_threads) {
948
-	    /* increase it but only if it doesn't exceed limit otherwise */
949
-	    int newmax = 2*max_threads;
950
-	    if (newmax*4 > rlim.rlim_cur)
951
-		newmax = rlim.rlim_cur/4;
952
-	    if (max_queue < newmax) {
953
-		max_queue = newmax;
954
-		logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue);
955
-	    }
944
+	/* don't warn if default value is too high, silently fix it */
945
+	unsigned warn = optget(opts, "MaxQueue")->active;
946
+	const unsigned clamdfiles = 6;
947
+	/* Condition to not run out of file descriptors:
948
+	 * MaxThreads * MaxRecursion + (MaxQueue - MaxThreads) + CLAMDFILES < RLIMIT_NOFILE 
949
+	 * CLAMDFILES is 6: 3 standard FD + logfile + 2 FD for reloading the DB
950
+	 * */
951
+	opt = optget(opts,"MaxRecursion");
952
+	unsigned maxrec = opt->numarg;
953
+	int max_max_queue = rlim.rlim_cur - maxrec * max_threads - clamdfiles + max_threads;
954
+	if (max_queue < max_threads) {
955
+	    max_queue = max_threads;
956
+	    if (warn)
957
+		logg("^MaxQueue value too low, increasing to: %d\n", max_queue);
958
+	}
959
+	if (max_max_queue < max_threads) {
960
+	    logg("^MaxThreads * MaxRecursion is too high: %d, open file descriptor limit is: %d\n",
961
+		 maxrec*max_threads, rlim.rlim_cur);
962
+	    max_max_queue = max_threads;
963
+	}
964
+	if (max_queue > max_max_queue) {
965
+	    max_queue = max_max_queue;
966
+	    if (warn)
967
+		logg("^MaxQueue value too high, lowering to: %d\n", max_queue);
968
+	} else if (max_queue < 2*max_threads && max_queue < max_max_queue) {
969
+	    max_queue = 2*max_threads;
970
+	    if (max_queue > max_max_queue)
971
+		max_queue = max_max_queue;
972
+	    /* always warn here */
973
+	    logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue);
956 974
 	}
957 975
     }
958 976
 #endif
959
-
977
+    logg("*MaxQueue set to: %d\n", max_queue);
960 978
     acceptdata.max_queue = max_queue;
961 979
 
962 980
     if(optget(opts, "ClamukoScanOnAccess")->enabled)
... ...
@@ -1156,7 +1177,7 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
1156 1156
 			logg("$Garbage: %s\n", buf->buffer);
1157 1157
 			error = 1;
1158 1158
 		    } else if (buf->mode == MODE_STREAM) {
1159
-			rc = handle_stream(&conn, buf, opts, &error, &pos);
1159
+			rc = handle_stream(&conn, buf, opts, &error, &pos, readtimeout);
1160 1160
 			if (rc == -1)
1161 1161
 			    break;
1162 1162
 			else
... ...
@@ -197,7 +197,7 @@ const struct clam_option clam_options[] = {
197 197
 
198 198
     { "ReadTimeout", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 120, NULL, 0, OPT_MILTER, "Waiting for data from clamd will timeout after this time (seconds).\nValue of 0 disables the timeout.", "300" },
199 199
 
200
-    { "MaxQueue", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 100, NULL, 0, OPT_CLAMD, "Maximum number of queued items (including those being processed)\nWARNING: you shouldn't increase this beyond 512, since you may run out of\nfile descriptors (usual max is 1024)\n", "200" },
200
+    { "MaxQueue", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 100, NULL, 0, OPT_CLAMD, "Maximum number of queued items (including those being processed by MaxThreads threads)\nIt is recommended to have this value at least twice MaxThreads if possible.\nWARNING: you shouldn't increase this too much to avoid running out  of file descriptors, the following condition should hold: MaxThreads*MaxRecursion + MaxQueue < RLIMIT_NOFILE (usual max is 1024)\n", "200" },
201 201
 
202 202
     { "IdleTimeout", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 30, NULL, 0, OPT_CLAMD, "This option specifies how long (in seconds) the process should wait\nfor a new job.", "60" },
203 203