diff --git a/core/config.c b/core/config.c index 88e58b3e..489b539d 100644 --- a/core/config.c +++ b/core/config.c @@ -465,3 +465,16 @@ add: } +void uwsgi_fallback_config() { + if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) { + uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code); + uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config); + char *argv[3]; + argv[0] = uwsgi.binary_path; + argv[1] = uwsgi.fallback_config; + argv[2] = NULL; + execvp(uwsgi.binary_path, argv); + uwsgi_error("execvp()"); + // never here + } +} diff --git a/core/utils.c b/core/utils.c index db7d0dfc..f376dcbd 100644 --- a/core/utils.c +++ b/core/utils.c @@ -3736,3 +3736,9 @@ void uwsgi_envdirs(struct uwsgi_string_list *envdirs) { void uwsgi_opt_envdir(char *opt, char *value, void *foobar) { uwsgi_envdir(value); } + +void uwsgi_exit(int status) { + uwsgi.last_exit_code = status; + // disable macro expansion + (exit)(status); +} diff --git a/core/uwsgi.c b/core/uwsgi.c index dae9e0e8..2abbd6d5 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -72,6 +72,7 @@ static struct uwsgi_option uwsgi_base_options[] = { {"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE}, #endif {"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE}, + {"fallback-config", required_argument, 0, "re-exec uwsgi with the specified config when exit code is 1", uwsgi_opt_set_str, &uwsgi.fallback_config, UWSGI_OPT_IMMEDIATE}, {"strict", no_argument, 0, "enable strict mode (placeholder cannot be used)", uwsgi_opt_true, &uwsgi.strict, UWSGI_OPT_IMMEDIATE}, {"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0}, @@ -1762,6 +1763,8 @@ int main(int argc, char *argv[], char *envp[]) { uwsgi_register_clock(&uwsgi_unix_clock); uwsgi_set_clock("unix"); + // fallback config + atexit(uwsgi_fallback_config); // manage/flush logs atexit(uwsgi_flush_logs); // clear sockets, pidfiles... diff --git a/uwsgi.h b/uwsgi.h index fbce93cf..2163f809 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1561,12 +1561,17 @@ void uwsgi_opt_load_config(char *, char *, void *); #define uwsgi_instance_is_dying (uwsgi.status.gracefully_destroying || uwsgi.status.brutally_destroying) #define uwsgi_instance_is_reloading (uwsgi.status.gracefully_reloading || uwsgi.status.brutally_reloading) +#define exit(x) uwsgi_exit(x) + struct uwsgi_server { // store the machine hostname char hostname[256]; int hostname_len; + // used to store the exit code for atexit hooks + int last_exit_code; + int (*proto_hooks[UWSGI_PROTO_MAX_CHECK]) (struct wsgi_request *, char *, char *, uint16_t); struct uwsgi_configurator *configurators; @@ -2162,7 +2167,7 @@ struct uwsgi_server { mode_t chmod_logfile_value; int listen_queue; - char *file_config; + char *fallback_config; #ifdef UWSGI_ROUTING struct uwsgi_router *routers; @@ -4124,6 +4129,9 @@ int uwsgi_register_fsmon(struct uwsgi_string_list *); int uwsgi_fsmon_event(int); void uwsgi_fsmon_setup(); +void uwsgi_exit(int) __attribute__ ((__noreturn__)); +void uwsgi_fallback_config(); + #ifdef __cplusplus } #endif