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