PERFORCE change 123676 for review

Andrew Turner andrew at FreeBSD.org
Wed Jul 18 06:57:04 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=123676

Change 123676 by andrew at andrew_hermies on 2007/07/18 06:56:55

	When sending a SIGINT to the back end clean up before exiting

Affected files ...

.. //depot/projects/soc2007/andrew-update/backend/facund-be.c#14 edit

Differences ...

==== //depot/projects/soc2007/andrew-update/backend/facund-be.c#14 (text+ko) ====

@@ -40,6 +40,7 @@
 #include <libutil.h>
 #include <limits.h>
 #include <sha256.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -52,6 +53,8 @@
 /* Check if there are updates every 30min  */
 static const time_t default_check_period = 30 * 60;
 
+static int facund_in_loop = 1;
+
 #define DEFAULT_CONFIG_FILE	"/etc/freebsd-update-control.conf"
 #define UPDATE_DATA_DIR		"/var/db/freebsd-update"
 
@@ -73,6 +76,8 @@
 static struct facund_response *facund_call_restart_services(const char *,
     struct facund_object *);
 
+static void	facund_signal_handler(int, siginfo_t *, void *);
+
 /*
  * Looks for updates on the system with a root of basedir
  */
@@ -111,10 +116,12 @@
 	char db_dir[PATH_MAX];
 	struct timespec timeout;
 	int *dir_fd, kq, use_kqueue, found_updates;
-	struct kevent *events, changes;
-	size_t pos, dir_count;
+	struct kevent event, changes;
+	size_t pos, dir_count, signals;
 	char **base_dirs;
+	int error, first_loop;
 
+	signals = 1;
 	base_dirs = data;
 	for (dir_count = 0; base_dirs[dir_count] != NULL; dir_count++)
 		continue;
@@ -125,11 +132,10 @@
 		errx(1, "Could not allocate enough memory");
 	}
 
-	/* Create an array of events */
-	events = malloc(dir_count * sizeof(struct kevent));
-	if (events == NULL) {
-		errx(1, "Could not allocate enough memory");
-	}
+	/* Create the kqueue to wait for events */
+	kq = kqueue();
+	if (kq == -1)
+		use_kqueue = 0;
 
 	for (pos = 0; pos < dir_count; pos++) {
 		snprintf(db_dir, PATH_MAX, "%s/var/db/freebsd-update/",
@@ -137,29 +143,34 @@
 		dir_fd[pos] = open(db_dir, O_RDONLY);
 
 		/* Create an event to look for files being added to the dir */
-		EV_SET(&events[pos], dir_fd[pos], EVFILT_VNODE, EV_ADD,
+		EV_SET(&event, dir_fd[pos], EVFILT_VNODE, EV_ADD,
 		    NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND, 0, (void *)pos);
+
+		kevent(kq, &event, 1, NULL, 0, NULL);
 	}
 
+	/* Add a signal event to check if there was a signal sent */
+	EV_SET(&event, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+	kevent(kq, &event, 1, NULL, 0, NULL);
+
 	use_kqueue = 1;
 	found_updates = 0;
 
-	/* XXX This timeout will be bigger in a live system */
 	timeout.tv_sec = default_check_period;
 	timeout.tv_nsec = 0;
-	kq = kqueue();
-	if (kq == -1)
-		use_kqueue = 0;
 
+	/* Scan all directories on the first run */
 	pos = dir_count;
 
+	first_loop = 1;
+
 	/*
 	 * This is the main loop to check for updates. It will
 	 * either wait for file system activity on the update
 	 * directories of just sleep for a fixed amount of time
 	 * then scan all directories.
 	 */
-	while(1) {
+	while(facund_in_loop != 0) {
 		assert(pos <= dir_count);
 		if (use_kqueue == 0 || pos == dir_count) {
 			/*
@@ -193,6 +204,13 @@
 		pos = dir_count;
 
 		/*
+		 * Before we sleep again check if we are to stop running
+		 */
+		if (facund_in_loop == 0) {
+			break;
+		}
+
+		/*
 		 * Wait for any disk activity to
 		 * quieten down before waiting again
 		 */
@@ -204,10 +222,8 @@
 		/* Wait for posible updates */
 		if (use_kqueue == 1) {
 			/* Wait for posible updates ready to be installed */
-			int error;
-
-			error = kevent(kq, events, dir_count, &changes, 1,
-			    &timeout);
+			/* There are no changes, use the same events */
+			error = kevent(kq, NULL, 0, &changes, 1, &timeout);
 
 			if (error == -1) {
 				/*
@@ -216,8 +232,10 @@
 				 */
 				use_kqueue = 0;
 			} else if (error > 0) {
-				/* Read in the item that changed */
-				pos = (size_t)changes.udata;
+				if (changes.filter == EVFILT_VNODE) {
+					/* Find in the item that changed */
+					pos = (size_t)changes.udata;
+				}
 			}
 		} else {
 			sleep(default_check_period);
@@ -292,21 +310,27 @@
 {
 	struct facund_conn *conn = (struct facund_conn *)data;
 
-	signal(SIGPIPE, SIG_DFL);
-
 	while(1) {
 		int ret = 0;
 		if(facund_server_start(conn) == -1) {
-			fprintf(stderr,
-			    "ERROR: Couldn't start the connection\n");
+			if (facund_in_loop != 0) {
+				/*
+				 * When we are not quiting tell
+				 * the user there was a problem
+				 */
+				fprintf(stderr,
+				    "ERROR: Couldn't start the connection\n");
+			}
 			break;
 		}
 
 		while(ret == 0) {
 			ret = facund_server_get_request(conn);
 			if (ret == -1) {
-				fprintf(stderr,
-				    "ERROR: Couldn't read data from network\n");
+				if (facund_in_loop != 0) {
+					fprintf(stderr, "ERROR: Couldn't read "
+					    "data from network\n");
+				}
 			}
 		}
 
@@ -518,9 +542,17 @@
 	return NULL;
 }
 
+static void
+facund_signal_handler(int sig __unused, siginfo_t *info __unused,
+    void *uap __unused)
+{
+	facund_in_loop = 0;
+}
+
 int
 main(int argc, char *argv[])
 {
+	struct sigaction sa;
 	pthread_t update_thread, comms_thread;
 	struct facund_conn *conn;
 	const char *config_file;
@@ -548,6 +580,11 @@
 
 	basedirs_string = NULL;
 
+	sa.sa_sigaction = facund_signal_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_SIGINFO;
+	sigaction(SIGINT, &sa, NULL);
+
 	/* Read in the config file */
 	config_fd = open(config_file, O_RDONLY);
 	if (config_fd == -1 && errno != ENOENT) {
@@ -593,6 +630,7 @@
 	pthread_create(&update_thread, NULL, look_for_updates, base_dirs);
 	pthread_create(&comms_thread, NULL, do_communication, conn);
 
+	/* Wait for the threads to quit */
 	pthread_join(comms_thread, NULL);
 	pthread_join(update_thread, NULL);
 


More information about the p4-projects mailing list