diff --git a/core/emperor.c b/core/emperor.c index 393685e6..d84fbfe0 100644 --- a/core/emperor.c +++ b/core/emperor.c @@ -17,12 +17,7 @@ void emperor_send_stats(int); time_t emperor_throttle; int emperor_throttle_level; -// scanners are instances of 'imperial_monitor' -struct uwsgi_emperor_scanner { - char *arg; - struct uwsgi_imperial_monitor *monitor; - struct uwsgi_emperor_scanner *next; -}; +struct uwsgi_instance *ui; /* @@ -149,12 +144,12 @@ int uwsgi_emperor_is_valid(char *name) { } // this is the monitor for non-glob directories -void uwsgi_imperial_monitor_directory(char *arg) { +void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) { struct uwsgi_instance *ui_current; struct dirent *de; struct stat st; - if (chdir(arg)) { + if (chdir(ues->arg)) { uwsgi_error("chdir()"); return; } @@ -188,21 +183,33 @@ void uwsgi_imperial_monitor_directory(char *arg) { } } else { - emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid); + emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid); } } closedir(dir); + + // now check for removed instances + struct uwsgi_instance *c_ui = ui->ui_next; + + while (c_ui) { + if (c_ui->scanner == ues) { + if (stat(c_ui->name, &st)) { + emperor_stop(c_ui); + } + } + c_ui = c_ui->ui_next; + } } // this is the monitor for glob patterns -void uwsgi_imperial_monitor_glob(char *arg) { +void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) { glob_t g; int i; struct stat st; struct uwsgi_instance *ui_current; - if (glob(arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) { + if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) { uwsgi_error("glob()"); return; } @@ -235,14 +242,28 @@ void uwsgi_imperial_monitor_glob(char *arg) { } } else { - emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid); + emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid); } } globfree(&g); + + // now check for removed instances + struct uwsgi_instance *c_ui = ui->ui_next; + + while (c_ui) { + if (c_ui->scanner == ues) { + if (stat(c_ui->name, &st)) { + emperor_stop(c_ui); + } + } + c_ui = c_ui->ui_next; + } + + } -void uwsgi_register_imperial_monitor(char *name, void (*init) (char *), void (*func) (char *)) { +void uwsgi_register_imperial_monitor(char *name, void (*init) (struct uwsgi_emperor_scanner *), void (*func) (struct uwsgi_emperor_scanner *)) { struct uwsgi_imperial_monitor *uim = uwsgi.emperor_monitors; if (!uim) { @@ -266,7 +287,6 @@ void uwsgi_register_imperial_monitor(char *name, void (*init) (char *), void (*f uim->next = NULL; } -struct uwsgi_instance *ui; // the sad death of an Emperor static void royal_death(int signum) { @@ -419,7 +439,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) { uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name); } -void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) { +void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) { struct uwsgi_instance *c_ui = ui; struct uwsgi_instance *n_ui = NULL; @@ -505,6 +525,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui uwsgi.emperor_broodlord_count++; } + n_ui->scanner = ues; memcpy(n_ui->name, name, strlen(name)); n_ui->born = born; n_ui->uid = uid; @@ -733,7 +754,7 @@ clear: } -void uwsgi_imperial_monitor_glob_init(char *arg) { +void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) { if (chdir(uwsgi.cwd)) { uwsgi_error("chdir()"); exit(1); @@ -742,8 +763,8 @@ void uwsgi_imperial_monitor_glob_init(char *arg) { uwsgi.emperor_absolute_dir = uwsgi.cwd; } -void uwsgi_imperial_monitor_directory_init(char *arg) { - if (chdir(arg)) { +void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) { + if (chdir(ues->arg)) { uwsgi_error("chdir()"); exit(1); } @@ -803,13 +824,13 @@ void emperor_add_scanner(struct uwsgi_imperial_monitor *monitor, char *arg) { ues->next = NULL; // run the init hook - ues->monitor->init(arg); + ues->monitor->init(ues); } void uwsgi_emperor_run_scanners(void) { struct uwsgi_emperor_scanner *ues = emperor_scanners; while (ues) { - ues->monitor->func(ues->arg); + ues->monitor->func(ues); ues = ues->next; } } @@ -971,7 +992,7 @@ void emperor_loop() { else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) { uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name); char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg"); - emperor_add(zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid); + emperor_add(NULL, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid); free(zerg_name); } } @@ -1030,7 +1051,7 @@ void emperor_loop() { } else { // UNSAFE - emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid); + emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid); emperor_del(ui_current); } break; diff --git a/plugins/emperor_pg/emperor_pg.c b/plugins/emperor_pg/emperor_pg.c index 9a53e73c..1093820f 100644 --- a/plugins/emperor_pg/emperor_pg.c +++ b/plugins/emperor_pg/emperor_pg.c @@ -3,8 +3,8 @@ extern struct uwsgi_server uwsgi; -void uwsgi_imperial_monitor_pg_init(char *); -void uwsgi_imperial_monitor_pg(char *); +void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *); +void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *); void emperor_pg_init(void); void emperor_pg_do(char *, char *, time_t, uid_t, gid_t); @@ -12,7 +12,7 @@ void emperor_pg_init(void) { uwsgi_register_imperial_monitor("pg", uwsgi_imperial_monitor_pg_init, uwsgi_imperial_monitor_pg); } -void uwsgi_imperial_monitor_pg_init(char *arg) { +void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *ues) { uwsgi_log("[emperor] enabled emperor PostgreSQL monitor\n"); } @@ -44,13 +44,13 @@ void emperor_pg_do(char *name, char *config, time_t ts, uid_t uid, gid_t gid) { } -void uwsgi_imperial_monitor_pg(char *arg) { +void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) { PGconn *conn = NULL; PGresult *res = NULL; const char *query = "SELECT name,config,EXTRACT(epoch FROM ts) FROM vassals"; - char *conn_string = uwsgi_str(arg + 5); + char *conn_string = uwsgi_str(ues->arg + 5); char *semicolon = strchr(conn_string, ';'); if (semicolon) { diff --git a/uwsgi.h b/uwsgi.h index 78442093..70f50e3c 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1074,10 +1074,12 @@ struct uwsgi_cheaper_algo { struct uwsgi_cheaper_algo *next; }; +struct uwsgi_emperor_scanner; + struct uwsgi_imperial_monitor { char *scheme; - void (*init)(char *); - void (*func)(char *); + void (*init)(struct uwsgi_emperor_scanner *); + void (*func)(struct uwsgi_emperor_scanner *); struct uwsgi_imperial_monitor *next; }; @@ -3067,8 +3069,18 @@ void uwsgi_logit_lf_strftime(struct wsgi_request *); struct uwsgi_logvar *uwsgi_logvar_get(struct wsgi_request *, char *, uint8_t); void uwsgi_logvar_add(struct wsgi_request *, char *, uint8_t, char *, uint8_t); +// scanners are instances of 'imperial_monitor' +struct uwsgi_emperor_scanner { + char *arg; + int fd; + void (*event_func)(struct uwsgi_emperor_scanner *); + struct uwsgi_imperial_monitor *monitor; + struct uwsgi_emperor_scanner *next; +}; -void uwsgi_register_imperial_monitor(char *, void (*)(char *), void (*)(char *)); + + +void uwsgi_register_imperial_monitor(char *, void (*)(struct uwsgi_emperor_scanner *), void (*)(struct uwsgi_emperor_scanner *)); int uwsgi_emperor_is_valid(char *); // an instance (called vassal) is a uWSGI stack running @@ -3101,6 +3113,8 @@ struct uwsgi_instance { int zerg; + struct uwsgi_emperor_scanner *scanner; + uid_t uid; gid_t gid; }; @@ -3109,7 +3123,7 @@ struct uwsgi_instance *emperor_get_by_fd(int); struct uwsgi_instance *emperor_get(char *); void emperor_stop(struct uwsgi_instance *); void emperor_respawn(struct uwsgi_instance *, time_t); -void emperor_add(char *, time_t, char *, uint32_t, uid_t, gid_t); +void emperor_add(struct uwsgi_emperor_scanner *, char *, time_t, char *, uint32_t, uid_t, gid_t); #ifdef UWSGI_AS_SHARED_LIBRARY int uwsgi_init(int, char **, char **);