Browse code

Improved database update detection when not --external

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1365 77e5149b-7576-45b1-b177-96237e5ba77b

Nigel Horne authored on 2005/03/02 03:58:01
Showing 3 changed files
... ...
@@ -1,3 +1,7 @@
1
+Tue Mar  1 18:57:18 GMT 2005 (njh)
2
+----------------------------------
3
+  * clamav-milter:	Improved database update detection when not --external
4
+
1 5
 Tue Mar  1 02:29:54 CET 2005 (tk)
2 6
 ---------------------------------
3 7
   * clamscan: use --include-dir/exclude-dir for directories instead of
... ...
@@ -698,6 +698,10 @@ Changes
698 698
 0.83	13/2/05:	Up issue
699 699
 0.83a	23/2/05:	Issue a warning if sendmail can't be executed
700 700
 			Remove pidfile, suggested by Stephen Gran <steve@lobefin.net>
701
+0.83b	1/3/05:		When not using --external, if a database update is
702
+				found, stop accepting inputs to quiten the
703
+				system for the database reload, rather than
704
+				wait for it to happen by itself
701 705
 
702 706
 INTERNATIONALISATION
703 707
 
... ...
@@ -26,6 +26,9 @@
26 26
  *
27 27
  * Change History:
28 28
  * $Log: clamav-milter.c,v $
29
+ * Revision 1.185  2005/03/01 18:55:14  nigelhorne
30
+ * Improved database update detection when not --external
31
+ *
29 32
  * Revision 1.184  2005/02/23 09:41:39  nigelhorne
30 33
  * Remove the pidfile
31 34
  *
... ...
@@ -563,9 +566,9 @@
563 563
  * Revision 1.6  2003/09/28 16:37:23  nigelhorne
564 564
  * Added -f flag use MaxThreads if --max-children not set
565 565
  */
566
-static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.184 2005/02/23 09:41:39 nigelhorne Exp $";
566
+static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.185 2005/03/01 18:55:14 nigelhorne Exp $";
567 567
 
568
-#define	CM_VERSION	"0.83a"
568
+#define	CM_VERSION	"0.83b"
569 569
 
570 570
 #if HAVE_CONFIG_H
571 571
 #include "clamav-config.h"
... ...
@@ -894,6 +897,9 @@ static	pthread_mutex_t	n_children_mutex = PTHREAD_MUTEX_INITIALIZER;
894 894
 static	pthread_cond_t	n_children_cond = PTHREAD_COND_INITIALIZER;
895 895
 static	unsigned	int	n_children = 0;
896 896
 static	unsigned	int	max_children = 0;
897
+static	pthread_mutex_t	accept_mutex = PTHREAD_MUTEX_INITIALIZER;
898
+static	pthread_cond_t	accept_cond = PTHREAD_COND_INITIALIZER;
899
+static	int	accept_inputs;
897 900
 static	int	child_timeout = 0;	/* number of seconds to wait for
898 901
 					 * a child to die. Set to 0 to
899 902
 					 * wait forever
... ...
@@ -1328,7 +1334,7 @@ main(int argc, char **argv)
1328 1328
 	/* FIXME: error if --servers and --external is not given */
1329 1329
 	/* TODO: support freshclam's daemon notify if --external is not given */
1330 1330
 
1331
-	if (optind == argc) {
1331
+	if(optind == argc) {
1332 1332
 		fprintf(stderr, _("%s: No socket-addr given\n"), argv[0]);
1333 1333
 		return EX_USAGE;
1334 1334
 	}
... ...
@@ -1924,6 +1930,7 @@ main(int argc, char **argv)
1924 1924
 				limits.archivememlim = 0;
1925 1925
 		}
1926 1926
 	}
1927
+	accept_inputs = 1;
1927 1928
 
1928 1929
 #ifdef	SESSION
1929 1930
 	/* FIXME: add localSocket support to watchdog */
... ...
@@ -2053,6 +2060,8 @@ createSession(int s)
2053 2053
 		char hostname[MAXHOSTNAMELEN + 1];
2054 2054
 
2055 2055
 		cli_strtokbuf(serverHostNames, serverNumber, ":", hostname);
2056
+		if(strcmp(hostname, "127.0.0.1") == 0)
2057
+			gethostname(hostname, sizeof(hostname));
2056 2058
 #else
2057 2059
 		char *hostname = cli_strtok(serverHostNames, serverNumber, ":");
2058 2060
 #endif
... ...
@@ -2316,6 +2325,8 @@ findServer(void)
2316 2316
 			char hostname[MAXHOSTNAMELEN + 1];
2317 2317
 
2318 2318
 			cli_strtokbuf(serverHostNames, i, ":", hostname);
2319
+			if(strcmp(hostname, "127.0.0.1") == 0)
2320
+				gethostname(hostname, sizeof(hostname));
2319 2321
 #else
2320 2322
 			char *hostname = cli_strtok(serverHostNames, i, ":");
2321 2323
 #endif
... ...
@@ -2395,10 +2406,27 @@ clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
2395 2395
 	char ip[INET_ADDRSTRLEN];	/* IPv4 only */
2396 2396
 #endif
2397 2397
 	const char *remoteIP;
2398
+	int accepting;
2398 2399
 
2399 2400
 	if(quitting)
2400 2401
 		return cl_error;
2401 2402
 
2403
+	pthread_mutex_lock(&accept_mutex);
2404
+	accepting = accept_inputs;
2405
+	pthread_mutex_unlock(&accept_mutex);
2406
+	if(!accepting) {
2407
+		cli_warnmsg("Not accepting inputs at the moment\n");
2408
+		if(dont_wait)
2409
+			return SMFIS_TEMPFAIL;
2410
+		do {
2411
+			pthread_cond_wait(&accept_cond, &accept_mutex);
2412
+			pthread_mutex_lock(&accept_mutex);
2413
+			accepting = accept_inputs;
2414
+			pthread_mutex_unlock(&accept_mutex);
2415
+		} while(!accepting);
2416
+		cli_warnmsg("Accepting inputs again\n");
2417
+	}
2418
+
2402 2419
 	if(ctx == NULL) {
2403 2420
 		if(use_syslog)
2404 2421
 			syslog(LOG_ERR, _("clamfi_connect: ctx is null"));
... ...
@@ -3038,15 +3066,24 @@ clamfi_eom(SMFICTX *ctx)
3038 3038
 				syslog(LOG_DEBUG, _("clamfi_eom: read %s"), mess);
3039 3039
 			cli_dbgmsg(_("clamfi_eom: read %s\n"), mess);
3040 3040
 		} else {
3041
+#ifdef	MAXHOSTNAMELEN
3042
+			char hostname[MAXHOSTNAMELEN + 1];
3043
+
3044
+			cli_strtokbuf(serverHostNames, privdata->serverNumber, ":", hostname);
3045
+			if(strcmp(hostname, "127.0.0.1") == 0)
3046
+				gethostname(hostname, sizeof(hostname));
3047
+#else
3048
+			char *hostname = cli_strtok(serverHostNames, privdata->serverNumber, ":");
3049
+#endif
3041 3050
 			/*
3042 3051
 			 * TODO: if more than one host has been specified, try
3043 3052
 			 * another one - setting cl_error to SMFIS_TEMPFAIL helps
3044 3053
 			 * by forcing a retry
3045 3054
 			 */
3046 3055
 			clamfi_cleanup(ctx);
3047
-			syslog(LOG_NOTICE, _("clamfi_eom: read nothing from clamd"));
3056
+			syslog(LOG_NOTICE, _("clamfi_eom: read nothing from clamd on %s"), hostname);
3048 3057
 #ifdef	CL_DEBUG
3049
-			cli_dbgmsg(_("clamfi_eom: read nothing from clamd\n"));
3058
+			cli_dbgmsg(_("clamfi_eom: read nothing from clamd on %s\n"), hostname);
3050 3059
 #endif
3051 3060
 #ifdef	SESSION
3052 3061
 			pthread_mutex_lock(&sstatus_mutex);
... ...
@@ -3116,6 +3153,8 @@ clamfi_eom(SMFICTX *ctx)
3116 3116
 			char hostname[MAXHOSTNAMELEN + 1];
3117 3117
 
3118 3118
 			if(cli_strtokbuf(serverHostNames, privdata->serverNumber, ":", hostname)) {
3119
+				if(strcmp(hostname, "127.0.0.1") == 0)
3120
+					gethostname(hostname, sizeof(hostname));
3119 3121
 #else
3120 3122
 			char *hostname = cli_strtok(serverHostNames, privdata->serverNumber, ":");
3121 3123
 			if(hostname) {
... ...
@@ -4750,6 +4789,8 @@ watchdog(void *a)
4750 4750
 		pthread_mutex_unlock(&watchdog_mutex);
4751 4751
 
4752 4752
 		if(!external) {
4753
+			int dbstatus = cl_statchkdir(&dbstat);
4754
+
4753 4755
 			/*
4754 4756
 			 * Re-load the database if the server's not busy.
4755 4757
 			 * TODO: If a reload is needed go into a mode when
... ...
@@ -4759,12 +4800,54 @@ watchdog(void *a)
4759 4759
 			 *	servers
4760 4760
 			 */
4761 4761
 			pthread_mutex_lock(&n_children_mutex);
4762
-			if((n_children == 0) && (cl_statchkdir(&dbstat) == 1)) {
4762
+			if((n_children == 0) && (dbstatus == 1)) {
4763
+				pthread_mutex_lock(&accept_mutex);
4764
+				accept_inputs = 0;
4765
+				pthread_mutex_unlock(&accept_mutex);
4766
+				cli_dbgmsg("Database has changed\n");
4767
+				cl_statfree(&dbstat);
4768
+				/* check for race condition */
4769
+				while(n_children > 0)
4770
+					pthread_cond_wait(&n_children_cond, &n_children_mutex);
4771
+				if(use_syslog)
4772
+					syslog(LOG_WARNING, _("Loading new database"));
4773
+				if(loadDatabase() != 0) {
4774
+					pthread_mutex_unlock(&n_children_mutex);
4775
+					smfi_stop();
4776
+					return NULL;
4777
+				}
4778
+				pthread_mutex_lock(&accept_mutex);
4779
+				accept_inputs = 1;
4780
+				pthread_cond_broadcast(&accept_cond);
4781
+				pthread_mutex_unlock(&accept_mutex);
4782
+			} else if(dbstatus == 0)
4783
+				cli_dbgmsg("Database has not changed\n");
4784
+			else if(dbstatus == 1) {
4785
+				cli_warnmsg("Not reloading database until idle\n");
4786
+				pthread_mutex_lock(&accept_mutex);
4787
+				accept_inputs = 0;
4788
+				pthread_mutex_unlock(&accept_mutex);
4789
+
4790
+				while(n_children > 0)
4791
+					pthread_cond_wait(&n_children_cond, &n_children_mutex);
4792
+
4763 4793
 				cl_statfree(&dbstat);
4764 4794
 				if(use_syslog)
4765 4795
 					syslog(LOG_WARNING, _("Loading new database"));
4766
-				if(loadDatabase() != 0)
4767
-					exit(EX_CONFIG);
4796
+				if(loadDatabase() != 0) {
4797
+					pthread_mutex_unlock(&n_children_mutex);
4798
+					smfi_stop();
4799
+					return NULL;
4800
+				}
4801
+				pthread_mutex_lock(&accept_mutex);
4802
+				accept_inputs = 1;
4803
+				pthread_cond_broadcast(&accept_cond);
4804
+				pthread_mutex_unlock(&accept_mutex);
4805
+			} else {
4806
+				smfi_stop();
4807
+				cli_errmsg("Database error - clamav-milter is stopping\n");
4808
+				pthread_mutex_unlock(&n_children_mutex);
4809
+				return NULL;
4768 4810
 			}
4769 4811
 			pthread_mutex_unlock(&n_children_mutex);
4770 4812
 			continue;
... ...
@@ -4872,6 +4955,7 @@ watchdog(void *a)
4872 4872
 	while(!quitting) {
4873 4873
 		struct timespec ts;
4874 4874
 		struct timeval tp;
4875
+		int dbstatus;
4875 4876
 
4876 4877
 		gettimeofday(&tp, NULL);
4877 4878
 
... ...
@@ -4902,13 +4986,54 @@ watchdog(void *a)
4902 4902
 		 *	otherwise a reload may not occur on overloaded
4903 4903
 		 *	servers
4904 4904
 		 */
4905
+		dbstatus = cl_statchkdir(&dbstat);
4905 4906
 		pthread_mutex_lock(&n_children_mutex);
4906
-		if((n_children == 0) && (cl_statchkdir(&dbstat) == 1)) {
4907
+		if((n_children == 0) && (dbstatus == 1)) {
4908
+			pthread_mutex_lock(&accept_mutex);
4909
+			accept_inputs = 0;
4910
+			pthread_mutex_unlock(&accept_mutex);
4911
+			cli_dbgmsg("Database has changed\n");
4907 4912
 			cl_statfree(&dbstat);
4913
+			/* check for race condition */
4914
+			while(n_children > 0)
4915
+				pthread_cond_wait(&n_children_cond, &n_children_mutex);
4908 4916
 			if(use_syslog)
4909 4917
 				syslog(LOG_WARNING, _("Loading new database"));
4910
-			if(loadDatabase() != 0)
4911
-				exit(EX_CONFIG);
4918
+			if(loadDatabase() != 0) {
4919
+				pthread_mutex_unlock(&n_children_mutex);
4920
+				smfi_stop();
4921
+				return NULL;
4922
+			}
4923
+			pthread_mutex_lock(&accept_mutex);
4924
+			accept_inputs = 1;
4925
+			pthread_cond_broadcast(&accept_cond);
4926
+			pthread_mutex_unlock(&accept_mutex);
4927
+		} else if(dbstatus == 0)
4928
+			cli_dbgmsg("Database has not changed\n");
4929
+		else if(dbstatus == 1) {
4930
+			cli_warnmsg("Not reloading database until idle\n");
4931
+			pthread_mutex_lock(&accept_mutex);
4932
+			accept_inputs = 0;
4933
+			pthread_mutex_unlock(&accept_mutex);
4934
+			while(n_children > 0)
4935
+				pthread_cond_wait(&n_children_cond, &n_children_mutex);
4936
+			cl_statfree(&dbstat);
4937
+			if(use_syslog)
4938
+				syslog(LOG_WARNING, _("Loading new database"));
4939
+			if(loadDatabase() != 0) {
4940
+				pthread_mutex_unlock(&n_children_mutex);
4941
+				smfi_stop();
4942
+				return NULL;
4943
+			}
4944
+			pthread_mutex_lock(&accept_mutex);
4945
+			accept_inputs = 1;
4946
+			pthread_cond_broadcast(&accept_cond);
4947
+			pthread_mutex_unlock(&accept_mutex);
4948
+		} else {
4949
+			smfi_stop();
4950
+			cli_errmsg("Database error - clamav-milter is stopping\n");
4951
+			pthread_mutex_unlock(&n_children_mutex);
4952
+			return NULL;
4912 4953
 		}
4913 4954
 		pthread_mutex_unlock(&n_children_mutex);
4914 4955
 	}
... ...
@@ -5006,6 +5131,10 @@ quit(void)
5006 5006
 
5007 5007
 	quitting++;
5008 5008
 
5009
+	pthread_mutex_lock(&accept_mutex);
5010
+	accept_inputs = 0;
5011
+	pthread_mutex_unlock(&accept_mutex);
5012
+
5009 5013
 #ifdef	SESSION
5010 5014
 	pthread_mutex_lock(&version_mutex);
5011 5015
 #endif
... ...
@@ -5195,7 +5324,7 @@ sigsegv(int sig)
5195 5195
 		syslog(LOG_ERR, "Segmentation fault :-( Bye..");
5196 5196
 	cli_dbgmsg("Segmentation fault :-( Bye..\n");
5197 5197
 
5198
-	exit(SIGSEGV);
5198
+	smfi_stop();
5199 5199
 }
5200 5200
 
5201 5201
 static void