Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

4073 lines (3339 sloc) 134.606 kb
/*
*** uWSGI ***
Copyright (C) 2009-2012 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "uwsgi.h"
struct uwsgi_server uwsgi;
#if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
#include <crt_externs.h>
char **environ;
#else
extern char **environ;
#endif
UWSGI_DECLARE_EMBEDDED_PLUGINS;
static struct uwsgi_option uwsgi_base_options[] = {
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL,0},
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi",0},
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http",0},
{"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi",0},
#ifdef UWSGI_SCTP
{"sctp-socket", required_argument, 's', "bind to the specified SCTP socket using uwsgi protocol", uwsgi_opt_add_socket, "sctp",0},
#endif
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol,0},
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol,0},
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL,0},
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc,0},
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc,0},
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI ,0},
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose,0},
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
{"no-harakiri-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
{"no-harakiri-after-req-hook", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
{"backtrace-depth", no_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SPOOLER_HARAKIRI,0},
{"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MULE_HARAKIRI,0},
#ifdef UWSGI_XML
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero,0},
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"if-env", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
{"if-not-env", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_env, UWSGI_OPT_IMMEDIATE},
{"ifenv", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
{"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
{"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
{"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
{"if-not-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_exists, UWSGI_OPT_IMMEDIATE},
{"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
{"if-file", required_argument, 0, "(opt logic) check for file existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_file, UWSGI_OPT_IMMEDIATE},
{"if-not-file", required_argument, 0, "(opt logic) check for file existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_file, UWSGI_OPT_IMMEDIATE},
{"if-dir", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"if-not-dir", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_dir, UWSGI_OPT_IMMEDIATE},
{"ifdir", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"ignore-sigpipe", no_argument, 0, "do not report (annoying) SIGPIPE", uwsgi_opt_true, &uwsgi.ignore_sigpipe,0},
{"ignore-write-errors", no_argument, 0, "do not report (annoying) write()/writev() errors", uwsgi_opt_true, &uwsgi.ignore_write_errors,0},
{"write-errors-tolerance", required_argument, 0, "set the maximum number of allowed write errors (default: no tolerance)", uwsgi_opt_set_int, &uwsgi.write_errors_tolerance,0},
{"write-errors-exception-only", no_argument, 0, "only raise an exception on write errors giving control to the app itself", uwsgi_opt_true, &uwsgi.write_errors_exception_only,0},
{"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL,0},
{"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
{"daemonize2", required_argument, 0, "daemonize uWSGI after app loading", uwsgi_opt_set_str, &uwsgi.daemonize2, 0},
{"stop", required_argument, 0, "stop an instance", uwsgi_opt_pidfile_signal, (void *) SIGINT, UWSGI_OPT_IMMEDIATE},
{"reload", required_argument, 0, "reload an instance", uwsgi_opt_pidfile_signal, (void *) SIGHUP, UWSGI_OPT_IMMEDIATE},
{"pause", required_argument, 0, "pause an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
{"suspend", required_argument, 0, "suspend an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP,UWSGI_OPT_IMMEDIATE},
{"resume", required_argument, 0, "resume an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP,UWSGI_OPT_IMMEDIATE},
{"listen", required_argument, 'l', "set the socket listen queue size", uwsgi_opt_set_int, &uwsgi.listen_queue,0},
{"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL,0},
{"buffer-size", required_argument, 'b', "set internal buffer size", uwsgi_opt_set_int, &uwsgi.buffer_size,0},
{"memory-report", no_argument, 'm', "enable memory report", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_MEMORY_DEBUG,0},
{"profiler", required_argument, 0, "enable the specified profiler", uwsgi_opt_set_str, &uwsgi.profiler,0},
{"cgi-mode", no_argument, 'c', "force CGI-mode for plugins supporting it", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_CGI_MODE,0},
{"abstract-socket", no_argument, 'a', "force UNIX socket in abstract mode (Linux only)", uwsgi_opt_true, &uwsgi.abstract_socket,0},
{"chmod-socket", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL,0},
{"chmod", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL,0},
{"chown-socket", required_argument, 0, "chown unix sockets", uwsgi_opt_set_str, &uwsgi.chown_socket, 0},
{"umask", required_argument, 0, "set umask", uwsgi_opt_set_umask, NULL, UWSGI_OPT_IMMEDIATE},
#ifdef __linux__
{"freebind", no_argument, 0, "put socket in freebind mode", uwsgi_opt_true, &uwsgi.freebind,0},
#endif
{"map-socket", required_argument, 0, "map sockets to specific workers", uwsgi_opt_add_string_list, &uwsgi.map_socket,0},
#ifdef UWSGI_THREADING
{"enable-threads", no_argument, 'T', "enable threads", uwsgi_opt_true, &uwsgi.has_threads, 0},
#endif
{"auto-procname", no_argument, 0, "automatically set processes name to something meaningful", uwsgi_opt_true, &uwsgi.auto_procname,0},
{"procname-prefix", required_argument, 0, "add a prefix to the process names", uwsgi_opt_set_str, &uwsgi.procname_prefix, UWSGI_OPT_PROCNAME},
{"procname-prefix-spaced", required_argument, 0, "add a spaced prefix to the process names", uwsgi_opt_set_str_spaced, &uwsgi.procname_prefix, UWSGI_OPT_PROCNAME},
{"procname-append", required_argument, 0, "append a string to process names", uwsgi_opt_set_str, &uwsgi.procname_append, UWSGI_OPT_PROCNAME},
{"procname", required_argument, 0, "set process names", uwsgi_opt_set_str, &uwsgi.procname, UWSGI_OPT_PROCNAME},
{"procname-master", required_argument, 0, "set master process name", uwsgi_opt_set_str, &uwsgi.procname_master, UWSGI_OPT_PROCNAME},
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process,0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_set_str, &uwsgi.emperor_dir,0},
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant,0},
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
{"emperor-broodlord", required_argument, 0, "run the emperor in BroodLord mode", uwsgi_opt_set_int, &uwsgi.emperor_broodlord, 0},
{"emperor-amqp-vhost", required_argument, 0, "set emperor amqp virtualhost", uwsgi_opt_set_str, &uwsgi.emperor_amqp_vhost, 0},
{"emperor-amqp-username", required_argument, 0, "set emperor amqp username", uwsgi_opt_set_str, &uwsgi.emperor_amqp_username, 0},
{"emperor-amqp-password", required_argument, 0, "set emperor amqp password", uwsgi_opt_set_str, &uwsgi.emperor_amqp_password, 0},
{"emperor-throttle", required_argument, 0, "throttle each vassal spawn (in seconds)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook,0},
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
{"auto-snapshot", optional_argument, 0, "automatically make workers snaphost after reload", uwsgi_opt_set_int, &uwsgi.auto_snapshot, UWSGI_OPT_LAZY},
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload,0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER ,0},
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS,0},
{"socket-timeout", required_argument, 'z', "set internal sockets timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SOCKET_TIMEOUT, 0},
{"no-fd-passing", no_argument, 0, "disable file descriptor passing", uwsgi_opt_true, &uwsgi.no_fd_passing, 0},
{"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_int, &uwsgi.cache_max_items, 0},
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_int, &uwsgi.cache_blocksize, 0},
{"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store , UWSGI_OPT_MASTER},
{"cache-store-sync", required_argument, 0, "set frequency of sync for persistent cache", uwsgi_opt_set_int, &uwsgi.cache_store_sync,0},
{"cache-server", required_argument, 0, "enable the threaded cache server", uwsgi_opt_set_str, &uwsgi.cache_server, 0},
{"cache-server-threads", required_argument, 0, "set the number of threads for the cache server", uwsgi_opt_set_int, &uwsgi.cache_server_threads,0},
{"cache-no-expire", no_argument, 0, "disable auto sweep of expired items", uwsgi_opt_true, &uwsgi.cache_no_expire,0},
{"cache-expire-freq", required_argument, 0, "set the frequency of cache sweeper scans (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.cache_expire_freq,0},
{"cache-report-freed-items", no_argument, 0, "constantly report the cache item freed by the sweeper (use only for debug)", uwsgi_opt_true, &uwsgi.cache_report_freed_items,0},
{"queue", required_argument, 0, "enable shared queue", uwsgi_opt_set_int, &uwsgi.queue_size, 0},
{"queue-blocksize", required_argument, 0, "set queue blocksize", uwsgi_opt_set_int, &uwsgi.queue_store_sync, 0},
{"queue-store", required_argument, 0, "enable persistent queue to disk", uwsgi_opt_set_str, &uwsgi.queue_store, UWSGI_OPT_MASTER},
{"queue-store-sync", required_argument, 0, "set frequency of sync for persistent queue", uwsgi_opt_set_int, &uwsgi.queue_store_sync,0},
#ifdef UWSGI_SPOOLER
{"spooler", required_argument, 'Q', "run a spooler on the specified directory", uwsgi_opt_add_spooler, NULL, UWSGI_OPT_MASTER},
{"spooler-ordered", no_argument, 0, "try to order the execution of spooler tasks", uwsgi_opt_true, &uwsgi.spooler_ordered,0},
{"spooler-chdir", required_argument, 0, "chdir() to specified directory before each spooler task", uwsgi_opt_set_str, &uwsgi.spooler_chdir,0},
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, 0},
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
#endif
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
{"signals-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
{"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_dyn_false, (void *) UWSGI_OPTION_LOGGING, 0},
{"flock", required_argument, 0, "lock the specified file before starting, exit if locked", uwsgi_opt_flock, NULL, UWSGI_OPT_IMMEDIATE},
{"flock-wait", required_argument, 0, "lock the specified file before starting, wait if locked", uwsgi_opt_flock_wait, NULL, UWSGI_OPT_IMMEDIATE},
{"flock2", required_argument, 0, "lock the specified file after logging/daemon setup, exit if locked", uwsgi_opt_set_str, &uwsgi.flock2, UWSGI_OPT_IMMEDIATE},
{"flock-wait2", required_argument, 0, "lock the specified file after logging/daemon setup, wait if locked", uwsgi_opt_set_str, &uwsgi.flock_wait2, UWSGI_OPT_IMMEDIATE},
{"pidfile", required_argument, 0, "create pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile,0},
{"pidfile2", required_argument, 0, "create pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile2,0},
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot,0},
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
#ifdef UWSGI_CAP
{"cap", required_argument,0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
#endif
#ifdef __linux__
{"unshare", required_argument,0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0},
#endif
{"exec-pre-jail", required_argument,0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail ,0},
{"exec-post-jail", required_argument,0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail,0},
{"exec-in-jail", required_argument,0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail,0},
{"exec-as-root", required_argument,0, "run the specified command before privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_root,0},
{"exec-as-user", required_argument,0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user,0},
{"exec-pre-app", required_argument,0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app,0},
#ifdef UWSGI_INI
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_YAML
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL,UWSGI_OPT_IMMEDIATE},
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL,UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_JSON
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL,0},
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL,0},
#endif
#ifdef UWSGI_SQLITE3
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_ZEROMQ
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_set_str, &uwsgi.zeromq,0},
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_set_str, &uwsgi.zeromq,0},
#endif
#ifdef UWSGI_LDAP
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
{"no-server", no_argument, 0, "force no-server mode", uwsgi_opt_true, &uwsgi.no_server,0},
{"command-mode", no_argument, 0, "force command mode", uwsgi_opt_true, &uwsgi.command_mode, UWSGI_OPT_IMMEDIATE},
{"no-defer-accept", no_argument, 0, "disable deferred-accept on sockets", uwsgi_opt_true, &uwsgi.no_defer_accept,0},
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max,0},
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
{"reload-on-rss", required_argument, 0, "reload if rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_rss, UWSGI_OPT_MEMORY },
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER|UWSGI_OPT_MEMORY},
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER|UWSGI_OPT_MEMORY},
#ifdef __linux__
#ifdef MADV_MERGEABLE
{"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
#endif
#endif
{"never-swap", no_argument, 0, "lock all memory pages avoiding swapping", uwsgi_opt_true, &uwsgi.never_swap, 0},
{"touch-reload", required_argument, 0, "reload uWSGI if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_reload, UWSGI_OPT_MASTER},
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
{"cpu-affinity", required_argument, 0, "set cpu affinity", uwsgi_opt_set_int, &uwsgi.cpu_affinity, 0},
{"post-buffering", required_argument, 0, "enable post buffering", uwsgi_opt_set_64bit, &uwsgi.post_buffering, 0},
{"post-buffering-bufsize", required_argument, 0, "set buffer size for read() in post buffering mode", uwsgi_opt_set_64bit, &uwsgi.post_buffering_bufsize,0},
{"upload-progress", required_argument, 0, "enable creation of .json files in the specified directory during a file upload", uwsgi_opt_set_str, &uwsgi.upload_progress,0},
{"no-default-app", no_argument, 0, "do not fallback to default app", uwsgi_opt_true, &uwsgi.no_default_app, 0},
{"manage-script-name", no_argument, 0, "automatically rewrite SCRIPT_NAME and PATH_INFO", uwsgi_opt_true, &uwsgi.manage_script_name, 0},
{"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &uwsgi.ignore_script_name, 0},
{"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &uwsgi.catch_exceptions, 0},
{"reload-on-exception", no_argument, 0, "reload a worker when an exception is raised", uwsgi_opt_true, &uwsgi.reload_on_exception, 0},
{"reload-on-exception-type", required_argument, 0, "reload a worker when a specific exception type is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_type, 0},
{"reload-on-exception-value", required_argument, 0, "reload a worker when a specific exception value is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_value, 0},
{"reload-on-exception-repr", required_argument, 0, "reload a worker when a specific exception type+value (language-specific) is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_repr, 0},
#ifdef UWSGI_UDP
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
#endif
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
{"stats-server", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
#ifdef UWSGI_MULTICAST
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
{"cluster", required_argument, 0, "join specified uWSGI cluster", uwsgi_opt_set_str, &uwsgi.cluster, UWSGI_OPT_MASTER},
{"cluster-nodes", required_argument, 0, "get nodes list from the specified cluster", uwsgi_opt_true, &uwsgi.cluster_nodes, UWSGI_OPT_MASTER|UWSGI_OPT_CLUSTER},
{"cluster-reload", required_argument, 0, "send a reload message to the cluster", uwsgi_opt_cluster_reload, NULL, UWSGI_OPT_IMMEDIATE},
{"cluster-log", required_argument, 0, "send a log line to the cluster", uwsgi_opt_cluster_log, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"subscribe-to", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
{"st", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
{"subscribe", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
{"subscribe-freq", required_argument, 0, "send subscription announce at the specified interval", uwsgi_opt_set_int, &uwsgi.subscribe_freq, 0},
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
#ifdef UWSGI_SNMP
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
#endif
{"check-interval", required_argument, 0, "set the interval (in seconds) of master checks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MASTER_INTERVAL, 0},
{"forkbomb-delay", required_argument, 0, "sleep for the specified number of seconds when a forkbomb is detected", uwsgi_opt_set_int, &uwsgi.forkbomb_delay, UWSGI_OPT_MASTER},
{"binary-path", required_argument, 0, "force binary path", uwsgi_opt_set_str, &uwsgi.binary_path, 0},
#ifdef UWSGI_ASYNC
{"async", required_argument, 0, "enable async mode with specified cores", uwsgi_opt_set_int, &uwsgi.async, 0},
#endif
{"max-fd", required_argument, 0, "set maximum number of file descriptors (requires root privileges)", uwsgi_opt_set_int, &uwsgi.requested_max_fd, 0},
{"logto", required_argument, 0, "set logfile/udp address", uwsgi_opt_set_str, &uwsgi.logfile, 0},
{"logto2", required_argument, 0, "log to specified file or udp address after privileges drop", uwsgi_opt_set_str, &uwsgi.logto2, 0},
{"logfile-chown", no_argument, 0, "chown logfiles", uwsgi_opt_true, &uwsgi.logfile_chown, 0},
{"logfile-chmod", required_argument, 0, "chmod logfiles", uwsgi_opt_logfile_chmod, NULL, 0},
{"log-syslog", optional_argument, 0, "log to syslog", uwsgi_opt_set_logger, "syslog", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
{"log-socket", required_argument, 0, "send logs to the specified socket", uwsgi_opt_set_logger, "socket", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
{"logger", required_argument, 0, "set logger system", uwsgi_opt_set_logger, NULL, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER },
{"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
#ifdef UWSGI_ZEROMQ
{"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
#endif
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, 0},
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_int, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
{"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
{"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
{"log-date", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
{"log-prefix", optional_argument, 0, "prefix logs with a string", uwsgi_opt_log_date, NULL, 0},
{"log-zero", no_argument, 0, "log responses without body", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_ZERO,0},
{"log-slow", required_argument, 0, "log requestes slower than the specified numbr of seconds", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_SLOW, 0},
{"log-4xx", no_argument, 0, "log requests with a 4xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_4xx,0},
{"log-5xx", no_argument, 0, "log requests with a 5xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_5xx,0},
{"log-big", required_argument, 0, "log requestes bigger than the specified size", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_BIG, 0},
{"log-sendfile", required_argument, 0, "log sendfile requests", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_SENDFILE, 0},
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root,0},
{"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
{"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
{"cheap", no_argument, 0, "set cheap mode (spawn workers only after the first request)", uwsgi_opt_true, &uwsgi.cheap, 0},
{"cheaper", required_argument, 0, "set cheaper mode (adaptive process spawning)", uwsgi_opt_set_int, &uwsgi.cheaper_count, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning)", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
{"cheaper-step", required_argument, 0, "number of additional processes to spawn at each overload", uwsgi_opt_set_int, &uwsgi.cheaper_step, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
{"cheaper-overload", required_argument, 0, "increase workers after specified overload", uwsgi_opt_set_64bit, &uwsgi.cheaper_overload, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
{"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, 0},
{"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
{"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_app, NULL,0},
#ifdef UWSGI_PCRE
{"regexp-mount", required_argument, 0, "load application under a regexp-based mountpoint", uwsgi_opt_add_app, (void *) 1, 0},
#endif
{"grunt", no_argument, 0, "enable grunt mode (in-request fork)", uwsgi_opt_true, &uwsgi.grunt, 0},
{"threads", required_argument, 0, "run each worker in prethreaded mode with the specified number of threads", uwsgi_opt_set_int, &uwsgi.threads, UWSGI_OPT_THREADS},
{"thread-stacksize", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
{"threads-stacksize", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
{"thread-stack-size", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
{"threads-stack-size", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
{"vhost", no_argument, 0, "enable virtualhosting mode (based on SERVER_NAME variable)", uwsgi_opt_true, &uwsgi.vhost, 0},
{"vhost-host", no_argument, 0, "enable virtualhosting mode (based on HTTP_HOST variable)", uwsgi_opt_true, &uwsgi.vhost_host, UWSGI_OPT_VHOST},
#ifdef UWSGI_ROUTING
{"route", required_argument, 0, "add a route", uwsgi_opt_add_route, "path_info", 0},
{"route-host", required_argument, 0, "add a route based on Host header", uwsgi_opt_add_route, "http_host", 0},
{"route-uri", required_argument, 0, "add a route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
{"route-qs", required_argument, 0, "add a route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
#endif
{"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
{"static-map", required_argument, 0, "map mountpoint to static directory (or file)", uwsgi_opt_static_map, &uwsgi.static_maps, UWSGI_OPT_MIME},
{"static-map2", required_argument, 0, "like static-map but completely appending the requested resource to the docroot", uwsgi_opt_static_map, &uwsgi.static_maps2, UWSGI_OPT_MIME},
{"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, UWSGI_OPT_MIME},
{"static-index", required_argument, 0, "search for specified file if a directory is requested", uwsgi_opt_add_string_list, &uwsgi.static_index, UWSGI_OPT_MIME},
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
{"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
{"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
#ifdef UWSGI_PCRE
{"static-expires", required_argument, 0, "set the Expires header based on filename regexp", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires, UWSGI_OPT_MIME},
{"static-expires-mtime", required_argument, 0, "set the Expires header based on filename regexp and file mtime", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires_mtime, UWSGI_OPT_MIME},
#endif
{"static-offload-to-thread", required_argument, 0, "offload static file serving to a thread (upto the specified number of threads)", uwsgi_opt_set_int, &uwsgi.static_offload_to_thread, UWSGI_OPT_MIME},
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
{"check-cache", no_argument, 0, "check for response data in the cache", uwsgi_opt_true, &uwsgi.check_cache, 0},
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode,0},
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum,0},
#ifdef __linux__
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup,0},
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt,0},
{"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns,0},
{"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns,0},
{"namespace-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
{"ns-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
#endif
{"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
{"zerg", required_argument, 0, "attach to a zerg server", uwsgi_opt_add_string_list, &uwsgi.zerg_node, 0},
{"zerg-fallback", no_argument, 0, "fallback to normal sockets if the zerg server is not available", uwsgi_opt_true, &uwsgi.zerg_fallback, 0},
{"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},
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"plugin-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"autoload", no_argument, 0, "try to automatically load plugins when unknown options are found", uwsgi_opt_true, &uwsgi.autoload, UWSGI_OPT_IMMEDIATE},
{"allowed-modifiers", required_argument, 0,"comma separated list of allowed modifiers", uwsgi_opt_set_str, &uwsgi.allowed_modifiers, 0},
{"remap-modifier", required_argument, 0, "remap request modifier from one id to another", uwsgi_opt_set_str, &uwsgi.remap_modifier, 0},
{"app", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "use the more advanced \"mount\" option",0},
{"dump-options", no_argument, 0, "dump the full list of available options", uwsgi_opt_true, &uwsgi.dump_options,0},
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config,0},
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL,0},
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
{0, 0, 0, 0, 0, 0, 0}
};
void show_config(void) {
int i;
fprintf(stdout, "\n;uWSGI instance configuration\n[uwsgi]\n");
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->value) {
fprintf(stdout, "%s = %s\n", uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
}
else {
fprintf(stdout, "%s = true\n", uwsgi.exported_opts[i]->key);
}
}
fprintf(stdout, ";end of configuration\n\n");
}
int uwsgi_manage_opt(char *key, char *value) {
struct uwsgi_option *op = uwsgi.options;
while(op->name) {
if (!strcmp(key, op->name)) {
op->func(key, value, op->data);
return 1;
}
op++;
}
return 0;
}
void uwsgi_configure() {
int i;
// and now apply the remaining configs
restart:
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
uwsgi.dirty_config = 0;
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
if (uwsgi.exported_opts[i]->configured == 0 && uwsgi.autoload) {
uwsgi.dirty_config = uwsgi_try_autoload(uwsgi.exported_opts[i]->key);
}
if (uwsgi.dirty_config) goto restart;
}
}
void config_magic_table_fill(char *filename, char **magic_table) {
char *tmp = NULL;
magic_table['o'] = filename;
if (filename[0] == '/') {
magic_table['p'] = filename;
}
else {
magic_table['p'] = uwsgi_concat3(uwsgi.cwd, "/", filename);
}
magic_table['s'] = uwsgi_get_last_char(magic_table['p'], '/') + 1;
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
if (magic_table['d'][strlen(magic_table['d'])-1] == '/') {
tmp = magic_table['d'] + (strlen(magic_table['d']) -1) ;
#ifdef UWSGI_DEBUG
uwsgi_log("tmp = %c\n", *tmp);
#endif
*tmp = 0;
}
if (uwsgi_get_last_char(magic_table['d'], '/'))
magic_table['c'] = uwsgi_get_last_char(magic_table['d'], '/') + 1;
if (tmp) *tmp = '/';
if (uwsgi_get_last_char(filename, '.'))
magic_table['e'] = uwsgi_get_last_char(filename, '.') + 1;
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
}
int find_worker_id(pid_t pid) {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid == pid)
return i;
}
return -1;
}
void warn_pipe() {
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi.threads < 2 && wsgi_req->uri_len > 0) {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
}
else {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
}
}
#ifdef UWSGI_THREADING
// in threading mode we need to use the cancel pthread subsystem
void wait_for_threads() {
int i, ret;
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
for (i = 0; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
pthread_cancel(uwsgi.core[i]->thread_id);
}
}
// wait for thread termination
for (i = 0; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
ret = pthread_join(uwsgi.core[i]->thread_id, NULL);
if (ret) {
uwsgi_log("pthread_join() = %d\n", ret);
}
}
}
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
}
#endif
void gracefully_kill(int signum) {
uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wait_for_threads();
if (!uwsgi.core[wsgi_req->async_id]->in_request) {
exit(UWSGI_RELOAD_CODE);
}
return;
// never here
}
#endif
// still not found a way to gracefully reload in async mode
if (uwsgi.async > 1) {
exit(UWSGI_RELOAD_CODE);
}
if (!uwsgi.core[0]->in_request) {
exit(UWSGI_RELOAD_CODE);
}
}
void end_me(int signum) {
exit(UWSGI_END_CODE);
}
void goodbye_cruel_world() {
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1 && !uwsgi.to_hell) {
wait_for_threads();
}
#endif
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
uwsgi_log("...The work of process %d is done. Seeya!\n", getpid());
exit(0);
}
#ifdef UWSGI_SPOOLER
static void uwsgi_signal_spoolers(int signum) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
if (uspool->pid > 0) {
kill(uspool->pid, SIGKILL);
uwsgi_log("killing the spooler with pid %d\n", uspool->pid);
}
uspool = uspool->next;
}
}
#endif
void kill_them_all(int signum) {
int i;
if (uwsgi.to_hell == 1) return;
uwsgi.to_hell = 1;
if (uwsgi.reload_mercy > 0) {
uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
}
else {
uwsgi.master_mercy = time(NULL) + 5;
}
uwsgi_log("SIGINT/SIGQUIT received...killing workers...\n");
// unsubscribe if needed
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_log("unsubscribing from %s\n", subscriptions->value);
uwsgi_subscribe(subscriptions->value, 1);
subscriptions = subscriptions->next;
}
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0)
kill(uwsgi.workers[i].pid, SIGINT);
}
#ifdef UWSGI_SPOOLER
uwsgi_signal_spoolers(SIGKILL);
#endif
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
}
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid > 0)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid > 0)
kill(ushared->gateways[i].pid, SIGKILL);
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid > 0)
kill(uwsgi.mules[i].pid, SIGKILL);
}
}
void grace_them_all(int signum) {
int i;
int waitpid_status;
if (uwsgi.to_heaven == 1 || uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0) return;
if (!uwsgi.lazy)
uwsgi.to_heaven = 1;
else uwsgi.to_outworld = 1;
if (uwsgi.reload_mercy > 0) {
uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
}
else {
// wait max 60 seconds for graceful reload
uwsgi.master_mercy = time(NULL) + 60;
}
#ifdef UWSGI_SPOOLER
uwsgi_signal_spoolers(SIGKILL);
#endif
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
}
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid > 0)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid > 0)
kill(ushared->gateways[i].pid, SIGKILL);
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid > 0)
kill(uwsgi.mules[i].pid, SIGKILL);
}
uwsgi_log("...gracefully killing workers...\n");
if (uwsgi.unsubscribe_on_graceful_reload) {
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_log("unsubscribing from %s\n", subscriptions->value);
uwsgi_subscribe(subscriptions->value, 1);
subscriptions = subscriptions->next;
}
}
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.auto_snapshot) {
if (uwsgi.workers[i].snapshot > 0) {
kill(uwsgi.workers[i].snapshot, SIGKILL);
if (waitpid(uwsgi.workers[i].snapshot, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
if (uwsgi.workers[i].pid > 0) {
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGHUP);
}
else {
uwsgi.workers[i].snapshot = uwsgi.workers[i].pid;
kill(uwsgi.workers[i].pid, SIGURG);
}
}
}
else if (uwsgi.workers[i].pid > 0) {
if (uwsgi.lazy) uwsgi.workers[i].destroy = 1;
kill(uwsgi.workers[i].pid, SIGHUP);
}
}
if (uwsgi.auto_snapshot) {
uwsgi.respawn_workers = 1;
}
}
void uwsgi_nuclear_blast() {
if (!uwsgi.workers) {
reap_them_all(0);
}
else if (uwsgi.master_process) {
if (getpid() == uwsgi.workers[0].pid) {
reap_them_all(0);
}
}
exit(1);
}
void reap_them_all(int signum) {
int i;
// avoid reace condition in lazy mode
if (uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0) return;
if (!uwsgi.lazy)
uwsgi.to_heaven = 1;
else uwsgi.to_outworld = 1;
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid > 0)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid > 0)
kill(ushared->gateways[i].pid, SIGKILL);
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (!uwsgi.mules) break;
if (uwsgi.mules[i].pid > 0)
kill(uwsgi.mules[i].pid, SIGKILL);
}
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
}
if (!uwsgi.workers)
return;
uwsgi_log("...brutally killing workers...\n");
// unsubscribe if needed
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_log("unsubscribing from %s\n", subscriptions->value);
uwsgi_subscribe(subscriptions->value, 1);
subscriptions = subscriptions->next;
}
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0)
kill(uwsgi.workers[i].pid, SIGTERM);
}
}
void harakiri() {
uwsgi_log("\nF*CK !!! i must kill myself (pid: %d app_id: %d)...\n", uwsgi.mypid, uwsgi.wsgi_req->app_id);
if (!uwsgi.master_process) {
uwsgi_log("*** if you want your workers to be automatically respawned consider enabling the uWSGI master process ***\n");
}
exit(0);
}
void snapshot_me(int signum) {
// wakeup !!!
if (uwsgi.snapshot) {
uwsgi.snapshot = 0;
return;
}
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) {
wait_for_threads();
}
#endif
uwsgi.snapshot = 1;
uwsgi_log("[snapshot] process %d taken\n", (int) getpid());
}
void stats(int signum) {
//fix this for better logging(this cause races)
struct uwsgi_app *ua = NULL;
int i, j;
if (uwsgi.mywid == 0) {
show_config();
uwsgi_log("\tworkers total requests: %llu\n", uwsgi.workers[0].requests);
uwsgi_log("-----------------\n");
for(j=1;j<=uwsgi.numproc;j++) {
for (i = 0; i < uwsgi.workers[j].apps_cnt; i++) {
ua = &uwsgi.workers[j].apps[i];
if (ua) {
uwsgi_log("\tworker %d app %d [%.*s] requests: %d exceptions: %d\n", j, i, ua->mountpoint_len, ua->mountpoint, ua->requests, ua->exceptions);
}
}
uwsgi_log("-----------------\n");
}
}
else {
uwsgi_log("worker %d total requests: %llu\n", uwsgi.mywid, uwsgi.workers[0].requests);
for (i = 0; i < uwsgi.workers[uwsgi.mywid].apps_cnt; i++) {
ua = &uwsgi.workers[uwsgi.mywid].apps[i];
if (ua) {
uwsgi_log("\tapp %d [%.*s] requests: %d exceptions: %d\n", i, ua->mountpoint_len, ua->mountpoint, ua->requests, ua->exceptions);
}
}
uwsgi_log("-----------------\n");
}
uwsgi_log("\n");
}
void what_i_am_doing() {
struct wsgi_request *wsgi_req;
int i;
char ctime_storage[26];
uwsgi_backtrace(uwsgi.backtrace_depth);
if (uwsgi.cores > 1) {
for (i = 0; i < uwsgi.cores; i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
#endif
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d core %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
else {
uwsgi_log("SIGUSR2: --- uWSGI worker %d core %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
}
}
}
else {
wsgi_req = uwsgi.wsgi_requests[0];
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
#endif
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
else {
uwsgi_log("SIGUSR2: --- uWSGI worker %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
}
}
else if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL) && uwsgi.workers[uwsgi.mywid].sig) {
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS handling signal %d ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, uwsgi.workers[uwsgi.mywid].signum);
}
}
}
pid_t masterpid;
struct timeval last_respawn;
int unconfigured_hook(struct wsgi_request *wsgi_req) {
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh.modifier1);
return -1;
}
static void unconfigured_after_hook(struct wsgi_request *wsgi_req) {
return;
}
struct uwsgi_plugin unconfigured_plugin = {
.name = "unconfigured",
.request = unconfigured_hook,
.after_request = unconfigured_after_hook,
};
static void vacuum(void) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
if (uwsgi.restore_tc) {
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
uwsgi_error("tcsetattr()");
}
}
if (uwsgi.vacuum) {
if (getpid() == masterpid) {
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
}
if (uwsgi.pidfile && !uwsgi.uid) {
if (unlink(uwsgi.pidfile)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: pidfile removed.\n");
}
}
if (uwsgi.pidfile2) {
if (unlink(uwsgi.pidfile2)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: pidfile2 removed.\n");
}
}
if (uwsgi.chdir) {
if (chdir(uwsgi.chdir)) {
uwsgi_error("chdir()");
}
}
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_UNIX) {
if (unlink(uwsgi_sock->name)) {
uwsgi_error("unlink()");
}
else {
uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
}
}
uwsgi_sock = uwsgi_sock->next;
}
}
}
}
void signal_pidfile(int sig, char *filename) {
int size = 0;
char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
if (size > 0) {
if (kill((pid_t) atoi(buffer), sig)) {
uwsgi_error("kill()");
}
}
else {
uwsgi_log("error: invalid pidfile\n");
}
}
/*static*/ void uwsgi_command_signal(char *opt) {
int tmp_signal;
char *colon = strchr(opt, ',');
if (!colon) {
uwsgi_log("invalid syntax for signal, must be addr,signal\n");
exit(1);
}
colon[0] = 0;
tmp_signal = atoi(colon+1);
if (tmp_signal < 0 || tmp_signal > 255) {
uwsgi_log("invalid signal number\n");
exit(3);
}
uint8_t uwsgi_signal = tmp_signal;
int ret = uwsgi_remote_signal_send(opt, uwsgi_signal);
if (ret < 0) {
uwsgi_log("unable to deliver signal %d to node %s\n", uwsgi_signal, opt);
exit(1);
}
if (ret == 0) {
uwsgi_log("node %s rejected signal %d\n", opt, uwsgi_signal);
exit(2);
}
uwsgi_log("signal %d delivered to node %s\n", uwsgi_signal, opt);
exit(0);
}
void fixup_argv_and_environ(int argc, char **argv, char **environ) {
uwsgi.orig_argv = argv;
uwsgi.argv = argv;
uwsgi.argc = argc;
uwsgi.environ = environ;
#if defined(__linux__) || defined(__sun__)
int i;
int env_count = 0;
uwsgi.argv = uwsgi_malloc( sizeof(char *) * (argc+1));
for(i=0;i<argc;i++) {
if (i==0 || argv[0] + uwsgi.max_procname + 1 == argv[i]) {
uwsgi.max_procname += strlen(argv[i]) + 1;
}
uwsgi.argv[i] = strdup(argv[i]);
}
// required by execve
uwsgi.argv[i] = NULL;
uwsgi.max_procname++;
for (i = 0; environ[i] != NULL; i++) {
// useless
//if ((environ[0] + uwsgi.max_procname + 1) == environ[i]) {
uwsgi.max_procname += strlen(environ[i]) + 1;
//}
env_count++;
}
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
for(i=0;i<env_count;i++) {
uwsgi.environ[i] = strdup(environ[i]);
#ifdef UWSGI_DEBUG
uwsgi_log("ENVIRON: %s\n", uwsgi.environ[i]);
#endif
environ[i] = uwsgi.environ[i];
}
#ifdef UWSGI_DEBUG
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
#endif
//environ = uwsgi.environ;
#endif
}
void uwsgi_plugins_atexit(void) {
int j;
if (!uwsgi.workers) return;
// the master cannot run atexit handlers...
if (uwsgi.master_process && uwsgi.workers[0].pid == getpid())
return;
for (j = 0; j< uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->atexit) {
uwsgi.gp[j]->atexit();
}
}
for (j = 0; j<256; j++) {
if (uwsgi.p[j]->atexit) {
uwsgi.p[j]->atexit();
}
}
}
void uwsgi_backtrace(int depth) {
#if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
#include <execinfo.h>
void **btrace = uwsgi_malloc(sizeof(void *) * depth);
size_t bt_size, i;
char **bt_strings;
bt_size = backtrace(btrace, depth);
bt_strings = backtrace_symbols(btrace, bt_size);
uwsgi_log("*** backtrace of %d ***\n", (int) getpid());
for(i=0;i<bt_size;i++) {
uwsgi_log("%s\n", bt_strings[i]);
}
free(btrace);
uwsgi_log("*** end of backtrace ***\n");
#endif
}
void uwsgi_segfault(int signum) {
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
// never here...
exit(1);
}
void uwsgi_fpe(int signum) {
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
// never here...
exit(1);
}
void uwsgi_flush_logs() {
struct pollfd pfd;
if (!uwsgi.master_process) return;
if (!uwsgi.log_master) return;
if (uwsgi.workers) {
if (uwsgi.workers[0].pid == getpid()) {
goto check;
}
}
if (uwsgi.mywid == 0)
goto check;
return ;
check:
// check for data in logpipe
pfd.events = POLLIN;
pfd.fd = uwsgi.shared->worker_log_pipe[0];
if (pfd.fd == -1) pfd.fd = 2;
while(poll(&pfd, 1, 0) > 0) {
if (uwsgi_master_log()) {
break;
}
}
}
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int argc, char *argv[], char *envp[]) {
#ifdef __APPLE__
char*** envPtr = _NSGetEnviron();
environ = *envPtr;
#endif
#else
int main(int argc, char *argv[], char *envp[]) {
#endif
int i;
int rlen;
char *env_reloads;
char env_reload_buf[11];
char *plugins_requested;
#ifdef UNBIT
//struct uidsec_struct us;
#endif
#ifdef UWSGI_DEBUG
struct utsname uuts;
#endif
char *emperor_env;
//char *optname;
signal(SIGSEGV, uwsgi_segfault);
signal(SIGFPE, uwsgi_fpe);
signal(SIGHUP, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
//initialize masterpid with a default value
masterpid = getpid();
memset(&uwsgi, 0, sizeof(struct uwsgi_server));
uwsgi.cwd = uwsgi_get_cwd();
init_magic_table(uwsgi.magic_table);
atexit(uwsgi_flush_logs);
atexit(vacuum);
atexit(uwsgi_plugins_atexit);
#ifdef UWSGI_DEBUG
#ifdef __sun__
if (uname(&uuts) < 0) {
#else
if (uname(&uuts)) {
#endif
uwsgi_error("uname()");
}
else {
uwsgi_log("SYSNAME: %s\nNODENAME: %s\nRELEASE: %s\nVERSION: %s\nMACHINE: %s\n", uuts.sysname, uuts.nodename, uuts.release, uuts.version, uuts.machine);
}
#endif
uwsgi.shared = (struct uwsgi_shared *) mmap(NULL, sizeof(struct uwsgi_shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.shared) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.shared, 0, sizeof(struct uwsgi_shared));
#ifdef UWSGI_SPOOLER
//set the spooler frequency to 30 seconds by default
uwsgi.shared->spooler_frequency = 30;
#endif
for (i = 0; i < 256; i++) {
uwsgi.p[i] = &unconfigured_plugin;
}
uwsgi.backtrace_depth = 64;
uwsgi.master_queue = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.original_log_fd = -1;
uwsgi.emperor_fd_config = -1;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_pid = -1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.default_app = -1;
uwsgi.buffer_size = 4096;
uwsgi.numproc = 1;
uwsgi.forkbomb_delay = 2;
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.cheaper_overload = 3;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
#ifdef UWSGI_SPOOLER
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
#endif
uwsgi.shared->mule_signal_pipe[0] = -1;
uwsgi.shared->mule_signal_pipe[1] = -1;
uwsgi.shared->mule_queue_pipe[0] = -1;
uwsgi.shared->mule_queue_pipe[1] = -1;
uwsgi.shared->worker_log_pipe[0] = -1;
uwsgi.shared->worker_log_pipe[1] = -1;
#ifdef UWSGI_BLACKLIST
if (!uwsgi_file_to_string_list(UWSGI_BLACKLIST, &uwsgi.blacklist)) {
uwsgi_log("you cannot run this build of uWSGI without a blacklist file\n");
exit(1);
}
#endif
#ifdef UWSGI_WHITELIST
if (!uwsgi_file_to_string_list(UWSGI_WHITELIST, &uwsgi.whitelist)) {
uwsgi_log("you cannot run this build of uWSGI without a whitelist file\n");
exit(1);
}
#endif
gettimeofday(&uwsgi.start_tv, NULL);
setlinebuf(stdout);
uwsgi.rl.rlim_cur = 0;
uwsgi.rl.rlim_max = 0;
// are we under systemd ?
char *notify_socket = getenv("NOTIFY_SOCKET");
if (notify_socket) {
uwsgi_systemd_init(notify_socket);
}
uwsgi_notify("initializing uWSGI");
emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = atoi(emperor_env);
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
}
}
char *screen_env = getenv("TERM");
if (screen_env) {
if (!strcmp(screen_env, "screen")) {
uwsgi.screen_session = getenv("STY");
}
}
env_reloads = getenv("UWSGI_RELOADS");
if (env_reloads) {
//convert env value to int
uwsgi.reloads = atoi(env_reloads);
uwsgi.reloads++;
//convert reloads to string
rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
}
}
uwsgi.is_a_reload = 1;
}
else {
if (setenv("UWSGI_RELOADS", "0", 1)) {
uwsgi_error("setenv()");
}
}
uwsgi.page_size = getpagesize();
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
// ok we can now safely play with argv and environ
fixup_argv_and_environ(argc, argv, environ);
if (gethostname(uwsgi.hostname, 255)) {
uwsgi_error("gethostname()");
}
uwsgi.hostname_len = strlen(uwsgi.hostname);
#ifdef UWSGI_ZEROMQ
uwsgi_register_logger("zeromq", uwsgi_zeromq_logger);
uwsgi_register_logger("zmq", uwsgi_zeromq_logger);
#endif
//initialize embedded plugins
UWSGI_LOAD_EMBEDDED_PLUGINS
// now a bit of magic, if the executable basename contains a 'uwsgi_' string,
// try to automatically load a plugin
#ifdef UWSGI_DEBUG
uwsgi_log("executable name: %s\n", uwsgi.binary_path);
#endif
char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
if (!original_proc_name) {
// here we use argv[0];
original_proc_name = argv[0];
setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
}
char *p = strrchr(original_proc_name, '/');
if (p == NULL) p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p+6), "_");
while(plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
build_options();
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
#ifdef UWSGI_EMBED_CONFIG
uwsgi_ini_config("", uwsgi.magic_table);
#endif
//parse environ
parse_sys_envs(environ);
uwsgi.option_index = -1;
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
if (i == '?') { uwsgi_log("getopt_long() error\n"); exit(1); }
if (uwsgi.option_index > -1) {
optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
}
else {
optname = uwsgi_get_optname_by_index(i);
}
if (!optname) {
uwsgi_log("unable to parse command line options\n");
exit(1);
}
uwsgi.option_index = -1;
add_exported_option(optname, optarg, 0);
}
#ifdef UWSGI_DEBUG
uwsgi_log("optind:%d argc:%d\n", optind,argc);
#endif
if (optind < argc) {
for(i=optind;i<uwsgi.argc;i++) {
char *lazy = uwsgi.argv[i];
if (lazy[0] != '[') {
uwsgi_opt_load(NULL, lazy, NULL);
// manage magic mountpoint
int magic = 0;
int j;
for (j = 0; j< uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->magic) {
if (uwsgi.gp[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
if (!magic) {
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->magic) {
if (uwsgi.p[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
}
}
}
}
// second pass: ENVs
uwsgi_apply_config_pass('$', (char *(*)(char *))getenv);
// third pass: FILEs
uwsgi_apply_config_pass('@', uwsgi_simple_file_read);
// last pass: REFERENCEs
uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
if (uwsgi.daemonize) {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize);
}
else {
if (!uwsgi.is_a_reload) {
daemonize(uwsgi.daemonize);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize);
}
}
}
else if (uwsgi.logfile) {
logto(uwsgi.logfile);
}
if (uwsgi.never_swap) {
if (mlockall( MCL_CURRENT | MCL_FUTURE )) {
uwsgi_error("mlockall()");
}
}
if (uwsgi.flock2) {
uwsgi_opt_flock(NULL, uwsgi.flock2, NULL);
}
if (uwsgi.flock_wait2) {
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
}
// setup master logging
if (uwsgi.log_master) {
if (uwsgi.requested_logger) {
char *colon = strchr(uwsgi.requested_logger, ':');
if (colon) {
*colon = 0;
}
uwsgi.choosen_logger = uwsgi_get_logger(uwsgi.requested_logger);
if (!uwsgi.choosen_logger) {
uwsgi_log("unable to find logger %s\n", uwsgi.requested_logger);
exit(1);
}
if (colon) {
uwsgi.choosen_logger_arg = colon+1;
*colon = ':';
}
}
uwsgi.original_log_fd = dup(1);
create_logpipe();
}
/* uWSGI IS CONFIGURED !!! */
if (uwsgi.dump_options) {
struct option *lopt = uwsgi.long_options;
while (lopt && lopt->name) {
fprintf(stdout, "%s\n", lopt->name);
lopt++;
}
exit(0);
}
if (uwsgi.show_config) show_config();
// call cluster initialization procedures
#ifdef UWSGI_MULTICAST
cluster_setup();
#endif
if (uwsgi.binary_path == uwsgi.argv[0]) {
uwsgi.binary_path = uwsgi_str(uwsgi.argv[0]);
}
uwsgi_log_initial("*** Starting uWSGI %s (%dbit) on [%.*s] ***\n", UWSGI_VERSION, (int) (sizeof(void *)) * 8, 24, ctime((const time_t *) &uwsgi.start_tv.tv_sec));
#ifdef UWSGI_DEBUG
uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, please disable debug in your build profile and recompile it ***\n***\n");
#endif
uwsgi_log_initial("compiled with version: %s on %s\n", __VERSION__, UWSGI_BUILD_DATE);
#ifdef __BIG_ENDIAN__
uwsgi_log_initial("*** big endian arch detected ***\n");
#endif
#if defined(_SC_NPROCESSORS_ONLN)
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_ONLN));
#elif defined(_SC_NPROCESSORS_CONF)
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_CONF));
#endif
uwsgi_log_initial("current working directory: %s\n", uwsgi.cwd);
if (uwsgi.screen_session) {
uwsgi_log("*** running under screen session %s ***\n", uwsgi.screen_session);
}
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
uwsgi_log_initial("detected binary path: %s\n", uwsgi.binary_path);
struct uwsgi_socket *shared_sock = uwsgi.shared_sockets;
while (shared_sock) {
char *tcp_port = strchr(shared_sock->name, ':');
if (tcp_port == NULL) {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
else {
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET;
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
if (shared_sock->fd < 0) {
uwsgi_log("unable to create shared socket on: %s\n", shared_sock->name);
exit(1);
}
shared_sock->bound = 1;
shared_sock = shared_sock->next;
}
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->shared) {
shared_sock = uwsgi_get_shared_socket_by_num(uwsgi_sock->from_shared);
if (!shared_sock) {
uwsgi_log("unable to find shared socket %d\n", uwsgi_sock->from_shared);
exit(1);
}
uwsgi_sock->fd = shared_sock->fd;
uwsgi_sock->family = shared_sock->family;
uwsgi_sock->name = shared_sock->name;
uwsgi_log("uwsgi socket %d mapped to shared socket %d (%s) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, uwsgi_sock->fd);
}
uwsgi_sock = uwsgi_sock->next;
}
// start the Emperor if needed
if (uwsgi.early_emperor && uwsgi.emperor_dir) {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
}
// run the pre-jail scripts
struct uwsgi_string_list *usl = uwsgi.exec_pre_jail;
while(usl) {
uwsgi_log("running \"%s\" (pre-jail)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
// call jail systems
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->jail) {
uwsgi.gp[i]->jail(uwsgi_start, uwsgi.argv);
}
}
// TODO pluginize basic Linux namespace support
#ifdef __linux__
if (uwsgi.ns) {
linux_namespace_start((void *) uwsgi.argv);
// never here
}
else {
#endif
uwsgi_start((void *) uwsgi.argv);
#ifdef __linux__
}
#endif
// never here
return 0;
}
int uwsgi_start(void *v_argv) {
#ifdef UWSGI_DEBUG
int so_bufsize;
socklen_t so_bufsize_len;
#endif
int i, j;
union uwsgi_sockaddr usa;
union uwsgi_sockaddr_ptr gsa;
socklen_t socket_type_len;
struct uwsgi_socket *uwsgi_sock;
#ifdef __linux__
uwsgi_set_cgroup();
if (uwsgi.ns) {
linux_namespace_jail();
}
#endif
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
uwsgi_as_root();
}
if (uwsgi.logto2) {
logto(uwsgi.logto2);
}
if (uwsgi.chdir) {
if (chdir(uwsgi.chdir)) {
uwsgi_error("chdir()");
exit(1);
}
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (!uwsgi.master_process && !uwsgi.command_mode) {
uwsgi_log_initial("*** WARNING: you are running uWSGI without its master process manager ***\n");
}
#ifndef __OpenBSD__
if (uwsgi.rl.rlim_max > 0) {
uwsgi.rl.rlim_cur = uwsgi.rl.rlim_max;
uwsgi_log("limiting address space of processes...\n");
if (setrlimit(RLIMIT_AS, &uwsgi.rl)) {
uwsgi_error("setrlimit()");
}
}
if (uwsgi.prio != 0) {
#ifdef __HAIKU__
if (set_thread_priority(find_thread(NULL), uwsgi.prio) == B_BAD_THREAD_ID) {
uwsgi_error("set_thread_priority()");
#else
if (setpriority(PRIO_PROCESS, 0, uwsgi.prio)) {
uwsgi_error("setpriority()");
#endif
}
else {
uwsgi_log("scheduler priority set to %d\n", uwsgi.prio);
}
}
if (!getrlimit(RLIMIT_AS, &uwsgi.rl)) {
//check for overflow
if (uwsgi.rl.rlim_max != (rlim_t) RLIM_INFINITY) {
uwsgi_log_initial("your process address space limit is %lld bytes (%lld MB)\n", (long long) uwsgi.rl.rlim_max, (long long) uwsgi.rl.rlim_max / 1024 / 1024);
}
}
#endif
uwsgi_log_initial("your memory page size is %d bytes\n", uwsgi.page_size);
if (uwsgi.buffer_size > 65536) {
uwsgi_log("invalid buffer size.\n");
exit(1);
}
sanitize_args();
// initialize workers
if (uwsgi.build_mime_dict) {
if (!uwsgi.mime_file) uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
struct uwsgi_string_list *umd = uwsgi.mime_file;
while(umd) {
if (!access(umd->value, R_OK)) {
uwsgi_build_mime_dict(umd->value);
}
else {
uwsgi_log("!!! no %s file found !!!\n", umd->value);
}
umd = umd->next;
}
}
if (uwsgi.static_offload_to_thread) {
pthread_attr_init(&uwsgi.static_offload_thread_attr);
pthread_attr_setdetachstate(&uwsgi.static_offload_thread_attr, PTHREAD_CREATE_DETACHED);
// 512K should be enough...
pthread_attr_setstacksize(&uwsgi.static_offload_thread_attr, 512*1024);
pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
}
// end of generic initialization
// start the Emperor if needed
if (!uwsgi.early_emperor && uwsgi.emperor_dir) {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
}
uwsgi_register_loop("simple", simple_loop);
#ifdef UWSGI_ASYNC
uwsgi_register_loop("async", async_loop);
// TODO rewrite to use uwsgi.max_fd
if (uwsgi.async > 1) {
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
if ((unsigned long) uwsgi.rl.rlim_cur < (unsigned long) uwsgi.async) {
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.rl.rlim_cur);
if (uwsgi.rl.rlim_cur < uwsgi.rl.rlim_max && (unsigned long) uwsgi.rl.rlim_max > (unsigned long) uwsgi.async) {
unsigned long tmp_nofile = (unsigned long) uwsgi.rl.rlim_cur;
uwsgi.rl.rlim_cur = uwsgi.async;
if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_log("max open files limit reset to %lu\n", (unsigned long) uwsgi.rl.rlim_cur);
uwsgi.async = uwsgi.rl.rlim_cur;
}
else {
uwsgi.async = (int) tmp_nofile;
}
}
else {
uwsgi.async = uwsgi.rl.rlim_cur;
}
uwsgi_log("- async cores set to %d -\n", uwsgi.async);
}
}
}
#endif
if (uwsgi.requested_max_fd) {
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_error("setrlimit()");
}
}
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi.max_fd = uwsgi.rl.rlim_cur;
uwsgi_log_initial("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
}
uwsgi.wsgi_requests = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.cores);
for (i = 0; i < uwsgi.cores; i++) {
uwsgi.wsgi_requests[i] = uwsgi_malloc(sizeof(struct wsgi_request));
memset(uwsgi.wsgi_requests[i], 0, sizeof(struct wsgi_request));
}
uwsgi.async_buf = uwsgi_malloc(sizeof(char *) * uwsgi.cores);
if (uwsgi.async > 1) {
uwsgi_log("async fd table size: %d\n", uwsgi.max_fd);
uwsgi.async_waiting_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
if (!uwsgi.async_waiting_fd_table) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi.async_waiting_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
uwsgi.async_proto_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
if (!uwsgi.async_proto_fd_table) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi.async_proto_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
}
if (uwsgi.post_buffering > 0) {
uwsgi_setup_post_buffering();
}
for (i = 0; i < uwsgi.cores; i++) {
uwsgi.async_buf[i] = uwsgi_malloc(uwsgi.buffer_size);
}
#ifdef UWSGI_DEBUG
uwsgi_log("cores allocated...\n");
#endif
//by default set wsgi_req to the first slot
uwsgi.wsgi_req = uwsgi.wsgi_requests[0];
if (uwsgi.cores > 1) {
uwsgi_log("allocated %llu bytes (%llu KB) for %d cores per worker.\n", (uint64_t) (sizeof(struct wsgi_request) * uwsgi.cores), (uint64_t) ((sizeof(struct wsgi_request) * uwsgi.cores) / 1024), uwsgi.cores);
}
if (uwsgi.vhost) {
uwsgi_log("VirtualHosting mode enabled.\n");
}
// setup locking
uwsgi_setup_locking();
// event queue lock (mitigate same event on multiple queues)
if (uwsgi.threads > 1) {
pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
}
// application generic lock
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks+1));
for(i=0;i<uwsgi.locks+1;i++) {
uwsgi.user_lock[i] = uwsgi_lock_init( uwsgi_concat2("user ", uwsgi_num2str(i)) );
}
if (uwsgi.master_process) {
// signal table lock
uwsgi.signal_table_lock = uwsgi_lock_init("signal");
// fmon table lock
uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
if (uwsgi.sharedareasize > 0) {
uwsgi.sharedarea = mmap(NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.sharedarea) {
uwsgi_log("shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea);
}
else {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.sa_lock = uwsgi_rwlock_init("sharedarea");
}
if (uwsgi.queue_size > 0) {
uwsgi_init_queue();
}
if (uwsgi.cache_max_items > 0) {
uwsgi_init_cache();
}
// create the cache server
if (uwsgi.master_process && uwsgi.cache_server) {
uwsgi.cache_server_fd = uwsgi_cache_server(uwsgi.cache_server, uwsgi.cache_server_threads);
}
/* plugin initialization */
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->init) {
uwsgi.gp[i]->init();
}
}
if (!uwsgi.no_server) {
// systemd/upstart/zerg socket activation
if (!uwsgi.is_a_reload) {
char *listen_pid = getenv("LISTEN_PID");
if (listen_pid) {
if (atoi(listen_pid) == (int) getpid()) {
char *listen_fds = getenv("LISTEN_FDS");
if (listen_fds) {
int systemd_fds = atoi(listen_fds);
if (systemd_fds > 0) {
uwsgi_log("- SystemD socket activation detected -\n");
for(i=3;i<3+systemd_fds;i++) {
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, i);
}
uwsgi.skip_zero = 1;
}
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
}
}
}
char *upstart_events = getenv("UPSTART_EVENTS");
if (upstart_events && !strcmp(upstart_events, "socket")) {
char *upstart_fds = getenv("UPSTART_FDS");
if (upstart_fds) {
uwsgi_log("- Upstart socket bridge detected (job: %s) -\n", getenv("UPSTART_JOB"));
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, atoi(upstart_fds));
uwsgi.skip_zero = 1;
}
unsetenv("UPSTART_EVENTS");
unsetenv("UPSTART_FDS");
}
struct uwsgi_string_list *zn = uwsgi.zerg_node;
while (zn) {
if (uwsgi_zerg_attach(zn->value)) {
if (!uwsgi.zerg_fallback) {
exit(1);
}
}
zn = zn->next;
}
if (uwsgi.zerg) {
#ifdef UWSGI_DEBUG
uwsgi_log("attaching zerg sockets...\n");
#endif
int zerg_fd;
i = 0;
for(;;) {
zerg_fd = uwsgi.zerg[i];
if (zerg_fd == -1) {
break;
}
uwsgi_sock = uwsgi_new_socket(NULL);
uwsgi_add_socket_from_fd(uwsgi_sock, zerg_fd);
i++;
}
uwsgi_log("zerg sockets attached\n");
}
}
//check for inherited sockets
if (uwsgi.is_a_reload) {
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
//a bit overengineering
if (uwsgi_sock->name[0] != 0 && !uwsgi_sock->bound) {
for (j = 3; j < (int) uwsgi.max_fd; j++) {
uwsgi_add_socket_from_fd(uwsgi_sock, j);
}
}
uwsgi_sock = uwsgi_sock->next;
}
//now close all the unbound fd
for (j = 3; j < (int)uwsgi.max_fd; j++) {
int useless = 1;
#ifdef UWSGI_MULTICAST
if (j == uwsgi.cluster_fd)
continue;
#endif
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
}
if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
if (j == uwsgi.cache_server_fd)
continue;
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
int found = 0;
while (ugs) {
if (ugs->fd == j) {
found = 1;break;
}
ugs = ugs->next;
}
if (found) continue;
int y;
found = 0;
for(y=0;y<ushared->gateways_cnt;y++) {
if (ushared->gateways[y].internal_subscription_pipe[0] == j) {
found = 1; break;
}
if (ushared->gateways[y].internal_subscription_pipe[1] == j) {
found = 1; break;
}
}
if (found) continue;
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!getsockname(j, gsa.sa, &socket_type_len)) {
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd == j && uwsgi_sock->bound) {
useless = 0;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
}
if (useless) {
close(j);
}
}
}
//now bind all the unbound sockets
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strchr(uwsgi_sock->name, ':');
if (tcp_port == NULL) {
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi_sock->family = AF_UNIX;
if (uwsgi.chown_socket) {
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
}
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
#ifdef UWSGI_SCTP
if (strchr(uwsgi_sock->name, ',') || (uwsgi_sock->proto_name && !strcmp(uwsgi_sock->proto_name, "sctp"))) {
uwsgi_sock->fd = -1;
uwsgi_sock->per_core = 1;
uwsgi_sock->proto_name = "sctp";
uwsgi_log("uwsgi persistent (SCTP) socket %d mapped to %s\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
#endif
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
#ifdef UWSGI_SCTP
}
#endif
uwsgi_sock->family = AF_INET;
}
if (uwsgi_sock->fd < 0 && !uwsgi_sock->per_core) {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
}
if (uwsgi.chown_socket) {
if (!uwsgi.master_as_root) {
uwsgi_as_root();
}
}
int zero_used = 0;
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
zero_used = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!zero_used) {
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(uwsgi_concat2("::",""));
uwsgi_sock->family = AF_INET;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
}
else if (!uwsgi.honour_stdin) {
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != 0) {
if (dup2(fd, 0)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
}
else if (uwsgi.honour_stdin) {
if (!tcgetattr(0, &uwsgi.termios)) {
uwsgi.restore_tc = 1;
}
}
}
// check for auto_port socket
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->auto_port) {
uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
uwsgi_sock = uwsgi_sock->next;
}
// put listening socket in non-blocking state and set the protocol
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (!uwsgi_sock->bound || uwsgi_sock->fd == -1) goto nextsock;
if (!uwsgi_sock->per_core) {
uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
if (uwsgi_sock->arg < 0) {
uwsgi_error("fcntl()");
exit(1);
}
uwsgi_sock->arg |= O_NONBLOCK;
if (fcntl(uwsgi_sock->fd, F_SETFL, uwsgi_sock->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
}
char *requested_protocol = uwsgi_sock->proto_name;
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) {
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
}
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
#ifdef UWSGI_SCTP
else if (requested_protocol && !strcmp("sctp", requested_protocol)) {
if (!uwsgi.post_buffering) {
uwsgi.post_buffering = 4096;
uwsgi_setup_post_buffering();
}
uwsgi_sock->proto = uwsgi_proto_sctp_parser;
uwsgi_sock->proto_accept = uwsgi_proto_sctp_accept;
uwsgi_sock->proto_write = uwsgi_proto_sctp_write;
uwsgi_sock->proto_writev = uwsgi_proto_sctp_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_sctp_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_sctp_writev_header;
uwsgi_sock->proto_sendfile = uwsgi_proto_sctp_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_sctp_close;
uwsgi_sock->proto_read_body = uwsgi_proto_sctp_read_body;
}
#endif
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
#ifdef UWSGI_ZEROMQ
if (uwsgi.zeromq) {
uwsgi.zmq_responder = strchr(uwsgi.zeromq, ',');
if (!uwsgi.zmq_responder) {
uwsgi_log("invalid zeromq address\n");
exit(1);
}
uwsgi.zmq_receiver = uwsgi_concat2n(uwsgi.zeromq, uwsgi.zmq_responder - uwsgi.zeromq, "", 0);
uwsgi.zmq_responder++;
uwsgi_log("zmq receiver: %s\n", uwsgi.zmq_receiver);
uwsgi_log("zmq responder: %s\n", uwsgi.zmq_responder);
uwsgi.zmq_socket = uwsgi_new_socket(uwsgi.zmq_receiver);
}
#endif
}
// initialize request plugin only if workers or master are available
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init) {
uwsgi.p[i]->init();
}
}
}
/* gp/plugin initialization */
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->post_init) {
uwsgi.gp[i]->post_init();
}
}
// again check for workers/sockets...
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_init) {
uwsgi.p[i]->post_init();
}
}
}
uwsgi.current_wsgi_req = simple_current_wsgi_req;
#ifdef UWSGI_THREADING
if (uwsgi.has_threads) {
if (uwsgi.threads > 1)
uwsgi.current_wsgi_req = threaded_current_wsgi_req;
(void) pthread_attr_init(&uwsgi.threads_attr);
if (uwsgi.threads_stacksize) {
if (pthread_attr_setstacksize(&uwsgi.threads_attr, uwsgi.threads_stacksize*1024) == 0) {
uwsgi_log("threads stack size set to %dk\n", uwsgi.threads_stacksize);
}
else {
uwsgi_log("!!! unable to set requested threads stacksize !!!\n");
}
}
pthread_mutex_init(&uwsgi.lock_static, NULL);
// again check for workers/sockets...
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->enable_threads)
uwsgi.p[i]->enable_threads();
}
}
}
#endif
#ifdef UWSGI_UDP
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor_dir && !uwsgi.command_mode) {
#else
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.emperor_dir && !uwsgi.command_mode) {
#endif
uwsgi_log("The -s/--socket option is missing and stdin is not a socket.\n");
exit(1);
}
else if (!uwsgi.sockets && ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.master_process) {
// here we will have a zombie... sorry
uwsgi_log("...you should enable the master process... really...\n");
exit(0);
}
if (!uwsgi.sockets)
uwsgi.numproc = 0;
if (uwsgi.command_mode) {
uwsgi.sockets = NULL;
uwsgi.numproc = 1;
uwsgi.to_hell = 1;
}
#ifdef UWSGI_DEBUG
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
so_bufsize_len = sizeof(int);
if (getsockopt(uwsgi_sock->fd, SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
else {
uwsgi_debug("uwsgi socket %d SO_RCVBUF size: %d\n", i, so_bufsize);
}
so_bufsize_len = sizeof(int);
if (getsockopt(uwsgi_sock->fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
else {
uwsgi_debug("uwsgi socket %d SO_SNDBUF size: %d\n", i, so_bufsize);
}
uwsgi_sock = uwsgi_sock->next;
}
#endif
#ifndef UNBIT
if (uwsgi.sockets)
uwsgi_log("your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
#endif
if (uwsgi.crons) {
struct uwsgi_cron *ucron = uwsgi.crons;
while(ucron) {
uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
ucron = ucron->next;
}
}
// apps are now per-worker
//memset(uwsgi.apps, 0, sizeof(uwsgi.apps));
uwsgi.workers = (struct uwsgi_worker *) mmap(NULL, sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.workers) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.workers, 0, sizeof(struct uwsgi_worker) * uwsgi.numproc + 1);
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].signal_pipe[0] = - 1;
uwsgi.workers[i].signal_pipe[1] = - 1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
}
if (uwsgi.master_process) {
for(i=1;i<=uwsgi.numproc;i++) {
create_signal_pipe(uwsgi.workers[i].signal_pipe);
}
}
uwsgi.mypid = getpid();
masterpid = uwsgi.mypid;
uwsgi.workers[0].pid = masterpid;
if (uwsgi.mules_cnt > 0) {
uwsgi.mules = (struct uwsgi_mule *) mmap(NULL, sizeof(struct uwsgi_mule) * uwsgi.mules_cnt, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.mules) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.mules, 0, sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
for(i=0;i<uwsgi.mules_cnt;i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
uwsgi.mules[i].id = i+1;
snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", i+1);
}
}
if (uwsgi.farms_cnt > 0) {
uwsgi.farms = (struct uwsgi_farm *) mmap(NULL, sizeof(struct uwsgi_farm) * uwsgi.farms_cnt, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.farms) {
uwsgi_error("mmap()");
exit(1);
}
memset(uwsgi.farms, 0, sizeof(struct uwsgi_farm) * uwsgi.farms_cnt);
struct uwsgi_string_list *farm_name = uwsgi.farms_list;
for(i=0;i<uwsgi.farms_cnt;i++) {
char *farm_value = uwsgi_str(farm_name->value);
char *mules_list = strchr(farm_value, ':');
if (!mules_list) {
uwsgi_log("invalid farm value (%s) must be in the form name:mule[,muleN].\n", farm_value);
exit(1);
}
mules_list[0] = 0;
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
char *p = strtok(mules_list, ",");
while(p != NULL) {
struct uwsgi_mule *um = get_mule_by_id( atoi( p ) );
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
exit(1);
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i+1, uwsgi.farms[i].name, strchr(farm_name->value, ':')+1);
farm_name = farm_name->next;
}
}
if (uwsgi.command_mode) {
uwsgi_log("*** Operational MODE: command ***\n");
}
else if (!uwsgi.numproc) {
uwsgi_log("*** Operational MODE: no-workers ***\n");
}
else if (uwsgi.threads > 1) {
if (uwsgi.numproc > 1) {
uwsgi_log("*** Operational MODE: preforking+threaded ***\n");
}
else {
uwsgi_log("*** Operational MODE: threaded ***\n");
}
}
#ifdef UWSGI_ASYNC
else if (uwsgi.async > 1) {
if (uwsgi.numproc > 1) {
uwsgi_log("*** Operational MODE: preforking+async ***\n");
}
else {
uwsgi_log("*** Operational MODE: async ***\n");
}
}
#endif
else if (uwsgi.numproc > 1) {
uwsgi_log("*** Operational MODE: preforking ***\n");
}
else {
uwsgi_log("*** Operational MODE: single process ***\n");
}
// even the master has cores..
uwsgi.core = uwsgi_malloc(sizeof(struct uwsgi_core *) * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
uwsgi.core[j] = uwsgi_malloc(sizeof(struct uwsgi_core));
memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core));
}
// preinit apps (create the language environment)
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->preinit_apps) {
uwsgi.p[i]->preinit_apps();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->preinit_apps) {
uwsgi.gp[i]->preinit_apps();
}
}
//init apps hook (if not lazy)
if (!uwsgi.lazy) {
uwsgi_init_all_apps();
}
if (uwsgi.daemonize2) {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize2);
}
else {
if (!uwsgi.is_a_reload) {
uwsgi_log("*** daemonizing uWSGI ***\n");
daemonize(uwsgi.daemonize2);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize2);
}
}
uwsgi.mypid = getpid();
masterpid = uwsgi.mypid;
uwsgi.workers[0].pid = masterpid;
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
}
if (uwsgi.no_server) {
uwsgi_log("no-server mode requested. Goodbye.\n");
exit(0);
}
if (!uwsgi.master_process && uwsgi.numproc == 0) {
exit(0);
}
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
}
#ifdef __linux__
#ifdef MADV_MERGEABLE
if (uwsgi.linux_ksm > 0) {
uwsgi_log("[uwsgi-KSM] enabled with frequency: %d\n", uwsgi.linux_ksm);
}
#endif
#endif
if (uwsgi.master_process) {
// initialize a mutex to avoid glibc problem with pthread+fork()
if (uwsgi.threaded_logger) {
pthread_mutex_init(&uwsgi.threaded_logger_lock, NULL);
}
if (uwsgi.is_a_reload) {
uwsgi_log("gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
}
else {
uwsgi_log("spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
}
}
// security in multiuser environment: allow only a subset of modifiers
if (uwsgi.allowed_modifiers) {
for (i = 0; i < 256; i++) {
if (!uwsgi_list_has_num(uwsgi.allowed_modifiers, i)) {
uwsgi.p[i]->request = unconfigured_hook;
uwsgi.p[i]->after_request = unconfigured_after_hook;
}
}
}
// master fixup
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(0);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spoolers != NULL && uwsgi.sockets) {
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
create_signal_pipe(uspool->signal_pipe);
uspool->lock = uwsgi_lock_init( uwsgi_concat2("spooler on ", uspool->dir) );
uspool->pid = spooler_start(uspool);
uspool = uspool->next;
}
}
#endif
if (!uwsgi.master_process) {
if (uwsgi.numproc == 1) {
uwsgi_log("spawned uWSGI worker 1 (and the only) (pid: %d, cores: %d)\n", masterpid, uwsgi.cores);
}
else {
uwsgi_log("spawned uWSGI worker 1 (pid: %d, cores: %d)\n", masterpid, uwsgi.cores);
}
uwsgi.workers[1].pid = masterpid;
uwsgi.workers[1].id = 1;
uwsgi.workers[1].last_spawn = time(NULL);
uwsgi.workers[1].manage_next_request = 1;
uwsgi.mywid = 1;
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
}
else {
// setup internal signalling system
create_signal_pipe(uwsgi.shared->worker_signal_pipe);
uwsgi.signal_socket = uwsgi.shared->worker_signal_pipe[1];
}
// uWSGI is ready
uwsgi_notify_ready();
uwsgi.current_time = time(NULL);
if (!uwsgi.cheap) {
if (uwsgi.cheaper && uwsgi.cheaper_count) {
for(i=1;i<=uwsgi.numproc;i++) {
if (i <= uwsgi.cheaper_count) {
if (uwsgi_respawn_worker(i)) break;
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
}
else {
uwsgi.workers[i].cheaped = 1;
}
}
}
else {
for (i = 2 - uwsgi.master_process; i < uwsgi.numproc + 1; i++) {
if (uwsgi_respawn_worker(i))
break;
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
}
}
}
if (getpid() == masterpid && uwsgi.master_process == 1) {
#ifdef UWSGI_AS_SHARED_LIBRARY
int ml_ret = master_loop(uwsgi.argv, uwsgi.environ);
if (ml_ret == -1) {
return 0;
}
#else
(void) master_loop(uwsgi.argv, uwsgi.environ);
#endif
//from now on the process is a real worker
}
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
struct uwsgi_string_list *usl = uwsgi.map_socket;
int enabled = 1;
while (usl) {
char *colon = strchr(usl->value, ':');
if ((int)uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon + 1, ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
if (w == uwsgi.mywid) {
enabled = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
}
usl = usl->next;
}
if (!enabled) {
close(uwsgi_sock->fd);
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_sock->disabled = 1;
}
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->disabled) {
uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
}
else {
uwsgi_sock = uwsgi_sock->next;
}
}
if (uwsgi.cpu_affinity) {
#ifdef __linux__
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
int ncpu = sysconf(_SC_NPROCESSORS_ONLN);
int base_cpu = (uwsgi.mywid - 1) * uwsgi.cpu_affinity;
if (base_cpu >= ncpu) {
base_cpu = base_cpu % ncpu;
}
uwsgi_log("set cpu affinity for worker %d to", uwsgi.mywid);
for (i = 0; i < uwsgi.cpu_affinity; i++) {
if (base_cpu >= ncpu)
base_cpu = 0;
CPU_SET(base_cpu, &cpuset);
uwsgi_log(" %d", base_cpu);
base_cpu++;
}
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) {
uwsgi_error("sched_setaffinity()");
}
uwsgi_log("\n");
#endif
}
if (uwsgi.worker_exec) {
char *w_argv[2];
w_argv[0] = uwsgi.worker_exec;
w_argv[1] = NULL;
uwsgi.sockets->arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.sockets->fd, F_SETFL, uwsgi.sockets->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
if (uwsgi.sockets->fd != 0) {
if (dup2(uwsgi.sockets->fd, 0)) {
uwsgi_error("dup2()");
}
}
execvp(w_argv[0], w_argv);
// never here
uwsgi_error("execvp()");
exit(1);
}
if (uwsgi.master_as_root) {
uwsgi_as_root();
}
if (uwsgi.lazy) {
uwsgi_init_all_apps();
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
#ifdef UWSGI_ZEROMQ
if (uwsgi.zmq_receiver && uwsgi.zmq_responder) {
uwsgi.zmq_context = zmq_init(1);
if (uwsgi.zmq_context == NULL) {
uwsgi_error("zmq_init()");
exit(1);
}
if (uwsgi.threads > 1) {
pthread_mutex_init(&uwsgi.zmq_lock, NULL);
}
uwsgi.zmq_pub = zmq_socket(uwsgi.zmq_context, ZMQ_PUB);
if (uwsgi.zmq_pub == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
uuid_t uuid_zmq;
char uuid_zmq_str[37];
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
uwsgi_log("%.*s\n", 36, uuid_zmq_str);
if (zmq_setsockopt(uwsgi.zmq_pub, ZMQ_IDENTITY, uuid_zmq_str, 36) < 0) {
uwsgi_error("zmq_setsockopt()");
exit(1);
}
if (zmq_connect(uwsgi.zmq_pub, uwsgi.zmq_responder) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
uwsgi.zmq_socket->proto = uwsgi_proto_zeromq_parser;
uwsgi.zmq_socket->proto_accept = uwsgi_proto_zeromq_accept;
uwsgi.zmq_socket->proto_close = uwsgi_proto_zeromq_close;
uwsgi.zmq_socket->proto_write = uwsgi_proto_zeromq_write;
uwsgi.zmq_socket->proto_writev = uwsgi_proto_zeromq_writev;
uwsgi.zmq_socket->proto_write_header = uwsgi_proto_zeromq_write_header;
uwsgi.zmq_socket->proto_writev_header = uwsgi_proto_zeromq_writev_header;
uwsgi.zmq_socket->proto_sendfile = uwsgi_proto_zeromq_sendfile;
uwsgi.zmq_socket->edge_trigger = 1;
if (pthread_key_create(&uwsgi.zmq_pull, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
if (tmp_zmq_pull == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
#ifdef ZMQ_FD
size_t zmq_socket_len = sizeof(int);
if (zmq_getsockopt(pthread_getspecific(uwsgi.zmq_pull), ZMQ_FD, &uwsgi.zmq_socket->fd, &zmq_socket_len) < 0) {
uwsgi_error("zmq_getsockopt()");
exit(1);
}
#else
uwsgi.zmq_socket->fd = -1;
#endif
uwsgi.zmq_socket->bound = 1;
uwsgi.zeromq_recv_flag = ZMQ_NOBLOCK;
}
#endif
//postpone the queue initialization as kevent
//do not pass kfd after fork()
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
uwsgi.async_queue = event_queue_init();
if (uwsgi.async_queue < 0) {
exit(1);
}
uwsgi_add_sockets_to_queue(uwsgi.async_queue);
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = uwsgi.wsgi_requests[i];
}
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
#endif
uwsgi.async_hvec = uwsgi_malloc(sizeof(struct iovec *) * uwsgi.cores);
for (i = 0; i < uwsgi.cores; i++) {
uwsgi.async_hvec[i] = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size);
}
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) {
signal(SIGALRM, (void *) &harakiri);
}
uwsgi_unix_signal(SIGHUP, gracefully_kill);
uwsgi_unix_signal(SIGINT, end_me);
uwsgi_unix_signal(SIGTERM, end_me);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, snapshot_me);
}
uwsgi_unix_signal(SIGUSR1, stats);
signal(SIGUSR2, (void *) &what_i_am_doing);
if (!uwsgi.ignore_sigpipe) {
signal(SIGPIPE, (void *) &warn_pipe);
}
//initialization done
// run fixup handler
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->fixup) {
uwsgi.p[i]->fixup();
}
}
if (uwsgi.chdir2) {
if (chdir(uwsgi.chdir2)) {
uwsgi_error("chdir()");
exit(1);
}
}
//re - initialize wsgi_req(can be full of init_uwsgi_app data)
for (i = 0; i < uwsgi.cores; i++) {
memset(uwsgi.wsgi_requests[i], 0, sizeof(struct wsgi_request));
uwsgi.wsgi_requests[i]->async_id = i;
}
// eventually remap plugins
if (uwsgi.remap_modifier) {
char *map = strtok(uwsgi.remap_modifier, ",");
while (map != NULL) {
char *colon = strchr(map, ':');
if (colon) {
colon[0] = 0;
int rm_src = atoi(map);
int rm_dst = atoi(colon + 1);
uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
}
map = strtok(NULL, ",");
}
}
#ifdef UWSGI_THREADING
if (uwsgi.cores > 1) {
uwsgi.core[0]->thread_id = pthread_self();
pthread_mutex_init(&uwsgi.six_feet_under_lock, NULL);
}
#endif
uwsgi_ignition();
// never here
exit(0);
}
void uwsgi_ignition() {
int i;
// snapshot workers do not enter the loop until a specific signal (SIGURG) is raised...
if (uwsgi.snapshot) {
wait_for_call_of_duty:
uwsgi_sig_pause();
if (uwsgi.snapshot)
goto wait_for_call_of_duty;
uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->hijack_worker) {
uwsgi.p[i]->hijack_worker();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->hijack_worker) {
uwsgi.gp[i]->hijack_worker();
}
}
if (uwsgi.loop) {
void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop);
if (!u_loop) {
uwsgi_log("unavailable loop engine !!!\n");
exit(1);
}
if (uwsgi.mywid == 1) {
uwsgi_log("*** running %s loop engine [addr:%p] ***\n", uwsgi.loop, u_loop);
}
u_loop();
uwsgi_log("your loop engine died. R.I.P.\n");
}
else {
#ifdef UWSGI_ZEROMQ
if (uwsgi.zeromq && uwsgi.async < 2 && !uwsgi.sockets->next) {
if (uwsgi.threads > 1) {
#ifdef UWSGI_THREADING
if (pthread_key_create(&uwsgi.tur_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
for (i = 1; i < uwsgi.threads; i++) {
long j = i;
pthread_create(&uwsgi.core[i]->thread_id, &uwsgi.threads_attr, zeromq_loop, (void *) j);
}
#endif
}
long y = 0;
zeromq_loop((void *) y);
}
else if (uwsgi.threads > 1) {
#else
if (uwsgi.threads > 1) {
#endif
#ifdef UWSGI_THREADING
if (pthread_key_create(&uwsgi.tur_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
for (i = 1; i < uwsgi.threads; i++) {
long j = i;
pthread_create(&uwsgi.core[i]->thread_id, &uwsgi.threads_attr, simple_loop, (void *) j);
}
#endif
}
if (uwsgi.async < 2) {
long y = 0;
simple_loop((void *) y);
}
#ifdef UWSGI_ASYNC
else {
async_loop(NULL);
}
#endif
}
if (uwsgi.snapshot) {
uwsgi_ignition();
}
// never here
pthread_exit(NULL);
}
/*
what happens here ?
we transform the uwsgi_option structure to a struct option
for passing it to getopt_long
A short options string is built.
This function could be called multiple times, so it will free previous areas
*/
void build_options() {
int options_count = 0;
int pos = 0;
int i;
// first count the base options
struct uwsgi_option *op = uwsgi_base_options;
while(op->name) {
options_count++;
op++;
}
for(i=0;i<256;i++) {
if (uwsgi.p[i]->options) {
options_count += uwsgi_count_options(uwsgi.p[i]->options);
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->options) {
options_count += uwsgi_count_options(uwsgi.gp[i]->options);
}
}
if (uwsgi.options) free(uwsgi.options);
uwsgi.options = uwsgi_calloc(sizeof(struct uwsgi_option) * (options_count+1));
op = uwsgi_base_options;
while(op->name) {
memcpy(&uwsgi.options[pos], op, sizeof(struct uwsgi_option));
pos++;
op++;
}
for(i=0;i<256;i++) {
if (uwsgi.p[i]->options) {
int c = uwsgi_count_options(uwsgi.p[i]->options);
memcpy(&uwsgi.options[pos], uwsgi.p[i]->options, sizeof(struct uwsgi_option) * c);
pos += c;
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
if (uwsgi.gp[i]->options) {
int c = uwsgi_count_options(uwsgi.gp[i]->options);
memcpy(&uwsgi.options[pos], uwsgi.gp[i]->options, sizeof(struct uwsgi_option) * c);
pos += c;
}
}
pos = 0;
if (uwsgi.long_options) free(uwsgi.long_options);
uwsgi.long_options = uwsgi_calloc(sizeof(struct option) * (options_count+1));
if (uwsgi.short_options) free(uwsgi.short_options);
uwsgi.short_options = uwsgi_calloc( (options_count * 2) + 1) ;
op = uwsgi.options;
while(op->name) {
uwsgi.long_options[pos].name = op->name;
uwsgi.long_options[pos].has_arg = op->type;
uwsgi.long_options[pos].flag = 0;
// add 1000 to avoid short_options collision
uwsgi.long_options[pos].val = 1000+pos;
if (op->shortcut) {
char shortcut = (char) op->shortcut;
// avoid duplicates in short_options
if (!strchr(uwsgi.short_options, shortcut)) {
strncat(uwsgi.short_options, &shortcut, 1);
if (op->type != no_argument) {
strcat(uwsgi.short_options, ":");
}
}
}
op++;
pos++;
}
}
void uwsgi_stdin_sendto(char *socket_name, uint8_t modifier1, uint8_t modifier2) {
char buf[4096];
ssize_t rlen;
size_t delta = 4096-4;
// leave space for uwsgi header
char *ptr = buf+4;
rlen = read(0, ptr, delta);
while (rlen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s\n", rlen, ptr);
#endif
ptr += rlen;
delta -= rlen;
if (delta <= 0)
break;
rlen = read(0, ptr, delta);
}
if (ptr > buf+4) {
send_udp_message(modifier1, modifier2, socket_name, buf, (ptr - buf)-4);
uwsgi_log("sent string \"%.*s\" to cluster node %s\n", (ptr - buf)-4, buf+4, socket_name);
}
}
/*
this function build the help output from the uwsgi.options structure
*/
void uwsgi_help(char *opt, char *val, void *none) {
size_t max_size = 0;
fprintf(stdout, "Usage: %s [options...]\n", uwsgi.binary_path);
struct uwsgi_option *op = uwsgi.options;
while(op && op->name) {
if (strlen(op->name) > max_size) {
max_size = strlen(op->name);
}
op++;
}
max_size++;
op = uwsgi.options;
while(op && op->name) {
if (op->shortcut) {
fprintf(stdout," -%c|--%-*s %s\n", op->shortcut, (int) max_size-3, op->name, op->help);
}
else {
fprintf(stdout," --%-*s %s\n", (int) max_size, op->name, op->help);
}
op++;
}
exit(0);
}
/*
initialize all apps
*/
void uwsgi_init_all_apps() {
int i, j;
// now run the pre-app scripts
struct uwsgi_string_list *usl = uwsgi.exec_pre_app;
while(usl) {