From c1ec9126da716d8dde0d716fcd7a4d94abd78930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 23 May 2013 11:05:36 +0200 Subject: [PATCH] unique crons, fixes #227 --- core/cron.c | 47 +++++++++++++++++++++++++++++++++----------- core/master.c | 1 + core/master_checks.c | 14 +++++++++++++ core/uwsgi.c | 3 +++ uwsgi.h | 8 ++++++++ 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/core/cron.c b/core/cron.c index f964246c..b66300fa 100644 --- a/core/cron.c +++ b/core/cron.c @@ -27,13 +27,22 @@ struct uwsgi_cron *uwsgi_cron_add(char *crontab) { exit(1); } uc->command = crontab + i; + uc->pid = -1; return uc; } + void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) { uwsgi_cron_add(value); } + +void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) { + struct uwsgi_cron *uc = uwsgi_cron_add(value); + uc->unique = 1; +} + + #ifdef UWSGI_SSL void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) { char *space = strchr(value, ' '); @@ -45,6 +54,19 @@ void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) { struct uwsgi_cron *uc = uwsgi_cron_add(space+1); uc->legion = legion; } + + +void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) { + char *space = strchr(value, ' '); + if (!space) { + uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt); + exit(1); + } + char *legion = uwsgi_concat2n(value, space-value, "", 0); + struct uwsgi_cron *uc = uwsgi_cron_add(space+1); + uc->legion = legion; + uc->unique = 1; +} #endif @@ -134,15 +156,16 @@ void uwsgi_manage_command_cron(time_t now) { #ifdef UWSGI_SSL // check for legion cron if (current_cron->legion) { - if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) { - current_cron = current_cron->next; - continue; - } + if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) + goto next; } #endif - int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week); + // skip unique crons that are still running + if (current_cron->unique && current_cron->pid >= 0) + goto next; + int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week); if (run_task == 1) { // date match, run command ? @@ -153,20 +176,20 @@ void uwsgi_manage_command_cron(time_t now) { current_cron->func(current_cron, now); } else { - if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) { - uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command); - } + pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1); + if (pid >= 0) { + current_cron->pid = pid; + current_cron->started_at = now; + uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid); + } } } current_cron->last_job = now; } } - - +next: current_cron = current_cron->next; } - - } diff --git a/core/master.c b/core/master.c index 6b79e3d0..a773941e 100644 --- a/core/master.c +++ b/core/master.c @@ -789,6 +789,7 @@ int master_loop(char **argv, char **environ) { if (uwsgi_master_check_mules_death(diedpid)) continue; if (uwsgi_master_check_gateways_death(diedpid)) continue; if (uwsgi_master_check_daemons_death(diedpid)) continue; + if (uwsgi_master_check_cron_death(diedpid)) continue; } diff --git a/core/master_checks.c b/core/master_checks.c index 3db72d36..92d5dd76 100644 --- a/core/master_checks.c +++ b/core/master_checks.c @@ -277,3 +277,17 @@ int uwsgi_worker_is_busy(int wid) { } return 0; } + +int uwsgi_master_check_cron_death(int diedpid) { + struct uwsgi_cron *uc = uwsgi.crons; + while (uc) { + if (uc->pid == (pid_t) diedpid) { + uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at); + uc->pid = -1; + return -1; + } + uc = uc->next; + } + return 0; +} + diff --git a/core/uwsgi.c b/core/uwsgi.c index 7c7fd68c..d04e738c 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -653,9 +653,12 @@ static struct uwsgi_option uwsgi_base_options[] = { {"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER}, {"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER}, + {"unique-cron", required_argument, 0, "add a unique cron task", uwsgi_opt_add_unique_cron, NULL, UWSGI_OPT_MASTER}, #ifdef UWSGI_SSL {"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER}, {"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER}, + {"unique-legion-cron", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER}, + {"unique-cron-legion", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER}, #endif {"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0}, {"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0}, diff --git a/uwsgi.h b/uwsgi.h index 82d31ad8..6f9f13bf 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -2386,6 +2386,10 @@ struct uwsgi_cron { #endif void (*func)(struct uwsgi_cron *, time_t); + time_t started_at; + uint8_t unique; + pid_t pid; + struct uwsgi_cron *next; }; @@ -3256,12 +3260,14 @@ void uwsgi_opt_add_shared_socket(char *, char *, void *); void uwsgi_opt_add_socket(char *, char *, void *); void uwsgi_opt_add_lazy_socket(char *, char *, void *); void uwsgi_opt_add_cron(char *, char *, void *); +void uwsgi_opt_add_unique_cron(char *, char *, void *); void uwsgi_opt_load_plugin(char *, char *, void *); void uwsgi_opt_load_dl(char *, char *, void *); void uwsgi_opt_load(char *, char *, void *); void uwsgi_opt_safe_fd(char *, char *, void *); #ifdef UWSGI_SSL void uwsgi_opt_add_legion_cron(char *, char *, void *); +void uwsgi_opt_add_unique_legion_cron(char *, char *, void *); void uwsgi_opt_sni(char *, char *, void *); struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *, char *, char *, char *, char *); #endif @@ -4027,6 +4033,8 @@ void uwsgi_check_emperor(void); int uwsgi_init(int, char **, char **); #endif +int uwsgi_master_check_cron_death(int); + #ifdef __cplusplus } #endif