From c2354ede162488f2ceaf7b8823548521f558951b Mon Sep 17 00:00:00 2001 From: Axel Kittenberger Date: Wed, 4 Aug 2010 20:22:38 +0000 Subject: [PATCH] Finally HUP-able --- lsyncd.c | 117 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 31 deletions(-) diff --git a/lsyncd.c b/lsyncd.c index c1c6fae..b65d049 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -386,8 +386,10 @@ struct delay_vector { * It's not worth to code a dynamic size handling... */ #define MAX_EXCLUDES 256 -char * exclude_dirs[MAX_EXCLUDES] = {NULL, }; -int exclude_dir_n = 0; +struct exclude_vector { + char * data[MAX_EXCLUDES]; + size_t len; +}; /*--------------------------------------------------------------------------* * MEMCHECK @@ -435,17 +437,30 @@ void maction(const void *nodep, const VISIT which, const int depth) { *--------------------------------------------------------------------------*/ /** - * Set to 0 in signal handler, when lsyncd should TERMinate nicely. + * Set to 0 in signal handler, when lsyncd should end ASAP. + * This can be either a TERM or a HUP signal. + * In case of HUP killed is 0 and start over. */ volatile sig_atomic_t keep_going = 1; +/** + * Received a TERM signal, TERMinate nicely. + */ +volatile sig_atomic_t termed = 0; + /** * Called (out-of-order) when signals arrive */ void catch_alarm(int sig) { - keep_going = 0; + switch(sig) { + case SIGTERM : + termed = 1; + /* fall through */ + case SIGHUP : + keep_going = 0; + } } /** @@ -941,7 +956,7 @@ append_delay(const struct log *log, struct watch *watch, clock_t alarm) { - printlogf(log, DEBUG, "append delay(%s, %d)", watch->dirname, alarm); + printlogf(log, DEBUG, "append_delay(%s, %d)", watch->dirname, alarm); if (watch->delayed) { printlogf(log, DEBUG, "ignored since already delayed."); return false; @@ -1401,6 +1416,7 @@ delay_or_act_dir(const struct global_options *opts, * @param opts global options * @param watches the watch vector * @param delays the delay vector + * @param excludes the excludes vector * @param inotify_fd inotify file descriptor. * @param dirname The name or absolute path of the directory to watch. * @param parent If not NULL, the watches to the parent directory already watched. @@ -1413,6 +1429,7 @@ struct watch * add_dirwatch(const struct global_options *opts, struct watch_vector *watches, struct delay_vector *delays, + struct exclude_vector *excludes, int inotify_fd, char const *dirname, struct watch *parent, @@ -1433,12 +1450,12 @@ add_dirwatch(const struct global_options *opts, { int i; - for (i = 0; i < exclude_dir_n; i++) { - if (!strcmp(pathname, exclude_dirs[i])) { + for (i = 0; i < excludes->len; i++) { + if (!strcmp(pathname, excludes->data[i])) { printlogf(log, NORMAL, "Excluded %s", pathname); return NULL; } - printlogf(log, DEBUG, "comparing %s with %s not an exclude so far.", pathname, exclude_dirs[i]); + printlogf(log, DEBUG, "comparing %s with %s not an exclude so far.", pathname, excludes->data[i]); } } @@ -1488,7 +1505,7 @@ add_dirwatch(const struct global_options *opts, // add watches if its a directory and not . or .. if (isdir && strcmp(de->d_name, "..") && strcmp(de->d_name, ".")) { // recurse into subdirectories - struct watch *nw = add_dirwatch(opts, watches, delays, inotify_fd, de->d_name, w, dir_conf); + struct watch *nw = add_dirwatch(opts, watches, delays, excludes, inotify_fd, de->d_name, w, dir_conf); printlogf(log, NORMAL, "found new directory: %s in %s -- %s", de->d_name, dirname, nw ? "will be synced" : "ignored it"); @@ -1614,6 +1631,7 @@ bool handle_event(const struct global_options *opts, struct watch_vector *watches, struct delay_vector *delays, + struct exclude_vector *excludes, int inotify_fd, struct inotify_event *event, clock_t alarm) @@ -1649,8 +1667,8 @@ handle_event(const struct global_options *opts, { // TODO, is this needed? or will it be excluded already? int i; - for (i = 0; i < exclude_dir_n; i++) { - if (!strcmp(event->name, exclude_dirs[i])) { + for (i = 0; i < excludes->len; i++) { + if (!strcmp(event->name, excludes->data[i])) { return true; } } @@ -1668,7 +1686,7 @@ handle_event(const struct global_options *opts, if ((IN_ATTRIB | IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM) & event->mask ) { - printlogf(log, NORMAL, "received event %s:%s.", masktext, event->name); + printlogf(log, NORMAL, "received event %s:%s for %d.", masktext, event->name, alarm); delay_or_act_dir(opts, delays, opts->delay > 0, watch, alarm); } else { printlogf(log, DEBUG, "... ignored this event."); @@ -1676,7 +1694,7 @@ handle_event(const struct global_options *opts, // in case of a new directory create new watches of the subdir if (((IN_CREATE | IN_MOVED_TO) & event->mask) && (IN_ISDIR & event->mask)) { - add_dirwatch(opts, watches, delays, inotify_fd, event->name, watch, watch->dir_conf); + add_dirwatch(opts, watches, delays, excludes, inotify_fd, event->name, watch, watch->dir_conf); } // in case of a removed directory remove watches from the subdir @@ -1693,12 +1711,14 @@ handle_event(const struct global_options *opts, * @param opts global options * @param watches the watch vector * @param delays the delay vector + * @param excludes the exclude vector * @param inotify_fd inotify file descriptor */ bool master_loop(const struct global_options *opts, struct watch_vector *watches, struct delay_vector *delays, + struct exclude_vector *excludes, int inotify_fd) { char buf[INOTIFY_BUF_LEN]; @@ -1780,7 +1800,7 @@ master_loop(const struct global_options *opts, int i = 0; while (i < len) { struct inotify_event *event = (struct inotify_event *) &buf[i]; - handle_event(opts, watches, delays, inotify_fd, event, alarm); + handle_event(opts, watches, delays, excludes, inotify_fd, event, alarm); i += sizeof(struct inotify_event) + event->len; } } @@ -1789,8 +1809,8 @@ master_loop(const struct global_options *opts, // until one item is found whose expiry time has not yet come // or the stack is empty. Using now time - times(NULL) - everytime // again as time may progresses while handling delayed entries. - while (delays->len > 0 && time_after_eq(times(NULL), delays->data[0])) { - printlogf(log, DEBUG, "time for '%s' arrived.", delays->data[0]->dirname); + while (delays->len > 0 && time_after_eq(times(NULL), delays->data[0]->alarm)) { + printlogf(log, DEBUG, "time %d for '%s' arrived. now=%d", delays->data[0]->alarm, delays->data[0]->dirname, times(NULL)); rsync_dir(opts, delays->data[0]); remove_first_delay(delays); } @@ -2361,9 +2381,13 @@ parse_options(struct global_options *opts, int argc, char **argv) /** * Parses the exclude file looking for directory masks to not watch. + * + * */ bool -parse_exclude_file(struct log *log, char *filename) { +parse_exclude_file(struct log *log, + struct exclude_vector * excludes, + char *filename) { FILE * ef; char line[PATH_MAX+1]; int sl; @@ -2402,7 +2426,7 @@ parse_exclude_file(struct log *log, char *filename) { } if (line[sl - 1] == '/') { - if (exclude_dir_n + 1 >= MAX_EXCLUDES) { + if (excludes->len + 1 >= MAX_EXCLUDES) { printlogf(log, ERROR, "Too many directory excludes, can only have %d at the most", MAX_EXCLUDES); @@ -2419,9 +2443,9 @@ parse_exclude_file(struct log *log, char *filename) { printlogf(log, NORMAL, "Excluding directories of the name '%s'", line); - exclude_dirs[exclude_dir_n] = s_malloc(log, strlen(line) + 1, "exclude_dir"); - strcpy(exclude_dirs[exclude_dir_n], line); - exclude_dir_n++; + excludes->data[excludes->len] = s_malloc(log, strlen(line) + 1, "exclude_dir"); + strcpy(excludes->data[excludes->len], line); + excludes->len++; } } @@ -2444,16 +2468,18 @@ write_pidfile(const struct log *log, const char *pidfile) { } /** - * Main. + * Main for one run. + * Can be runned through several times on HUPs. */ int -main(int argc, char **argv) +one_main(int argc, char **argv) { - struct global_options opts = {{0,}}; // global options - struct log *log = &opts.log; // shortcut to logging options. - struct watch_vector watches = {0, }; // all watches - struct delay_vector delays = {0, }; // delayed entries - int inotify_fd; // inotify file descriptor + struct global_options opts = {{0,}}; // global options + struct log *log = &opts.log; // shortcut to logging options. + struct watch_vector watches = {0, }; // all watches + struct delay_vector delays = {0, }; // delayed entries + struct exclude_vector excludes = {{0, }}; // excludes + int inotify_fd; // inotify file descriptor openlog("lsyncd", LOG_CONS | LOG_PID, LOG_DAEMON); @@ -2461,7 +2487,7 @@ main(int argc, char **argv) parse_options(&opts, argc, argv); if (opts.default_exclude_file) { - parse_exclude_file(log, opts.default_exclude_file); + parse_exclude_file(log, &excludes, opts.default_exclude_file); } inotify_fd = inotify_init(); @@ -2499,7 +2525,7 @@ main(int argc, char **argv) int i; for (i = 0; i < opts.dir_conf_n; i++) { printlogf(log, NORMAL, "watching %s", opts.dir_confs[i].source); - add_dirwatch(&opts, &watches, &delays, inotify_fd, + add_dirwatch(&opts, &watches, &delays, &excludes, inotify_fd, opts.dir_confs[i].source, NULL, &opts.dir_confs[i]); } } @@ -2542,9 +2568,13 @@ main(int argc, char **argv) watches.len); signal(SIGTERM, catch_alarm); + signal(SIGHUP, catch_alarm); - master_loop(&opts, &watches, &delays, inotify_fd); + master_loop(&opts, &watches, &delays, &excludes, inotify_fd); + if (!termed) { + printlogf(log, NORMAL, "--- Received HUP-Signal, cleaning up and starting over ---"); + } { // memory clean up int i; @@ -2557,6 +2587,9 @@ main(int argc, char **argv) } s_free(watches.data); s_free(delays.data); + for(i = 0; i < excludes.len; i++) { + s_free(excludes.data[i]); + } } @@ -2568,3 +2601,25 @@ main(int argc, char **argv) return 0; } + +/** + * Main wrapper + * + * Start actual main over and over on HUPs. + */ +int +main(int argc, char **argv) +{ + int ret; + do { + ret = one_main(argc, argv); + if (ret) { + return ret; + } + // start over + keep_going = 1; + } while (!termed); + + return ret; +} +