void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) { int i; glob_t g; if (glob(value, GLOB_MARK, NULL, &g)) { uwsgi_string_new_list(&up.python_path, value); } else { for (i = 0; i < (int) g.gl_pathc; i++) { uwsgi_string_new_list(&up.python_path, g.gl_pathv[i]); } } }
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) { int i; for (i = 0; i < atoi(value); i++) { uwsgi.mules_cnt++; uwsgi_string_new_list(&uwsgi.mules_patches, NULL); } }
void uwsgi_opt_sni(char *opt, char *value, void *foobar) { char *client_ca = NULL; char *v = uwsgi_str(value); char *space = strchr(v, ' '); if (!space) { uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt); exit(1); } *space = 0; char *crt = space+1; char *key = strchr(crt, ','); if (!key) { uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt); exit(1); } *key = '\0'; key++; char *ciphers = strchr(key, ','); if (ciphers) { *ciphers = '\0'; ciphers++; client_ca = strchr(ciphers, ','); if (client_ca) { *client_ca = '\0'; client_ca++; } } if (!uwsgi.ssl_initialized) { uwsgi_ssl_init(); } SSL_CTX *ctx = uwsgi_ssl_new_server_context(v, crt, key, ciphers, client_ca); if (!ctx) { uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", v); free(v); return; } #ifdef UWSGI_PCRE if (!strcmp(opt, "sni-regexp")) { struct uwsgi_regexp_list *url = uwsgi_regexp_new_list(&uwsgi.sni_regexp, v); url->custom_ptr = ctx; } else { #endif struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, v); usl->custom_ptr = ctx; #ifdef UWSGI_PCRE } #endif }
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *key, char *ciphers, char *client_ca) { if (!uwsgi.ssl_initialized) { uwsgi_ssl_init(); } SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca); if (!ctx) { uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name); return NULL; } struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name); usl->custom_ptr = ctx; return usl; }
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) { uwsgi.farms_cnt++; uwsgi_string_new_list(&uwsgi.farms_list, value); }
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) { uwsgi.mules_cnt++; uwsgi_string_new_list(&uwsgi.mules_patches, value); }
void uwsgi_detach_daemons() { struct uwsgi_daemon *ud = uwsgi.daemons; while (ud) { #ifdef UWSGI_SSL // stop any legion daemon, doesn't matter if dumb or smart if (ud->pid > 0 && (ud->legion || !ud->pidfile)) { #else // stop only dumb daemons if (ud->pid > 0 && !ud->pidfile) { #endif uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command); // try to stop daemon gracefully, kill it if it won't die // if mercy is not set then wait up to 3 seconds time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3); int waitpid_status; while (!kill(ud->pid, 0)) { kill(-ud->pid, ud->stop_signal); sleep(1); waitpid(-ud->pid, &waitpid_status, WNOHANG); if (uwsgi_now() >= timeout) { uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command); kill(-ud->pid, SIGKILL); break; } } // unregister daemon to prevent it from being respawned ud->registered = 0; } ud = ud->next; } } void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) { // skip unregistered daemons if (!ud->registered) return; int throttle = 0; if (uwsgi.current_time - ud->last_spawn <= 3) { throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn); // if ud->respawns == 0 then we can end up with throttle < 0 if (throttle <= 0) throttle = 1; } pid_t pid = uwsgi_fork("uWSGI external daemon"); if (pid < 0) { uwsgi_error("fork()"); return; } if (pid > 0) { ud->has_daemonized = 0; ud->pid = pid; ud->status = 1; ud->pidfile_checks = 0; if (ud->respawns == 0) { ud->born = uwsgi_now(); } ud->respawns++; ud->last_spawn = uwsgi_now(); } else { // close uwsgi sockets uwsgi_close_all_sockets(); uwsgi_close_all_fds(); if (ud->gid) { if (setgid(ud->gid)) { uwsgi_error("uwsgi_spawn_daemon()/setgid()"); exit(1); } } if (ud->uid) { if (setuid(ud->uid)) { uwsgi_error("uwsgi_spawn_daemon()/setuid()"); exit(1); } } if (ud->daemonize) { /* refork... */ pid = fork(); if (pid < 0) { uwsgi_error("fork()"); exit(1); } if (pid != 0) { _exit(0); } uwsgi_write_pidfile(ud->pidfile); } if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) { // /dev/null will became stdin uwsgi_remap_fd(0, "/dev/null"); } if (setsid() < 0) { uwsgi_error("setsid()"); exit(1); } if (!ud->pidfile) { #ifdef __linux__ if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) { uwsgi_error("prctl()"); } #endif } if (throttle) { uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle); sleep((unsigned int) throttle); } uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid()); uwsgi_exec_command_with_args(ud->command); uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command); // never here; exit(1); } return; } void uwsgi_opt_add_daemon(char *opt, char *value, void *none) { struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud; char *pidfile = NULL; int daemonize = 0; int freq = 10; char *space = NULL; int stop_signal = SIGTERM; int reload_signal = 0; char *command = uwsgi_str(value); #ifdef UWSGI_SSL char *legion = NULL; if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) { space = strchr(command, ' '); if (!space) { uwsgi_log("invalid legion daemon syntax: %s\n", command); exit(1); } *space = 0; legion = command; command = space+1; } #endif if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) { space = strchr(command, ' '); if (!space) { uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command); exit(1); } *space = 0; pidfile = command; // check for freq char *comma = strchr(pidfile, ','); if (comma) { *comma = 0; freq = atoi(comma + 1); } command = space + 1; if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) { daemonize = 1; } } if (!uwsgi_ud) { uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon)); uwsgi_ud = uwsgi.daemons; } else { while (uwsgi_ud) { old_ud = uwsgi_ud; uwsgi_ud = uwsgi_ud->next; } uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon)); old_ud->next = uwsgi_ud; } uwsgi_ud->command = command; uwsgi_ud->pid = 0; uwsgi_ud->status = 0; uwsgi_ud->freq = freq; uwsgi_ud->registered = 0; uwsgi_ud->next = NULL; uwsgi_ud->respawns = 0; uwsgi_ud->last_spawn = 0; uwsgi_ud->daemonize = daemonize; uwsgi_ud->pidfile = pidfile; uwsgi_ud->control = 0; uwsgi_ud->stop_signal = stop_signal; uwsgi_ud->reload_signal = reload_signal; if (!strcmp(opt, "attach-control-daemon")) { uwsgi_ud->control = 1; } #ifdef UWSGI_SSL uwsgi_ud->legion = legion; #endif uwsgi.daemons_cnt++; } void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) { struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud; char *d_command = NULL; char *d_freq = NULL; char *d_pidfile = NULL; char *d_control = NULL; char *d_legion = NULL; char *d_daemonize = NULL; char *d_touch = NULL; char *d_stopsignal = NULL; char *d_reloadsignal = NULL; char *d_stdin = NULL; char *d_uid = NULL; char *d_gid = NULL; char *arg = uwsgi_str(value); if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "command", &d_command, "cmd", &d_command, "exec", &d_command, "freq", &d_freq, "pidfile", &d_pidfile, "control", &d_control, "daemonize", &d_daemonize, "daemon", &d_daemonize, "touch", &d_touch, "stopsignal", &d_stopsignal, "stop_signal", &d_stopsignal, "reloadsignal", &d_reloadsignal, "reload_signal", &d_reloadsignal, "stdin", &d_stdin, "uid", &d_uid, "gid", &d_gid, NULL)) { uwsgi_log("invalid --%s keyval syntax\n", opt); exit(1); } if (!d_command) { uwsgi_log("--%s: you need to specify a 'command' key\n", opt); exit(1); } #ifndef UWSGI_SSL if (d_legion) { uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n"); exit(1); } #endif if (!uwsgi_ud) { uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon)); uwsgi_ud = uwsgi.daemons; } else { while (uwsgi_ud) { old_ud = uwsgi_ud; uwsgi_ud = uwsgi_ud->next; } uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon)); old_ud->next = uwsgi_ud; } uwsgi_ud->command = d_command; uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10; uwsgi_ud->daemonize = d_daemonize ? 1 : 0; uwsgi_ud->pidfile = d_pidfile; uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM; uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0; uwsgi_ud->control = d_control ? 1 : 0; uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0; uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0; uwsgi_ud->honour_stdin = d_stdin ? 1 : 0; #ifdef UWSGI_SSL uwsgi_ud->legion = d_legion; #endif if (d_touch) { size_t i,rlen = 0; char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen); for(i=0;i<rlen;i++) { uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]); } if (argv) free(argv); } uwsgi.daemons_cnt++; free(arg); }
static void parse_argv_hook(uint16_t item, char *value, uint16_t vlen, void *data) { struct uwsgi_string_list **usl = (struct uwsgi_string_list **) data; uwsgi_string_new_list(usl, uwsgi_concat2n(value, vlen, "", 0)); }