mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-07 06:06:08 +00:00
4073 lines
132 KiB
C
4073 lines
132 KiB
C
/*
|
|
|
|
*** 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) {
|
|
uwsgi_log("running \"%s\" (pre app)...\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;
|
|
}
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
if (uwsgi.p[i]->init_apps) {
|
|
uwsgi.p[i]->init_apps();
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
|
if (uwsgi.gp[i]->init_apps) {
|
|
uwsgi.gp[i]->init_apps();
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < uwsgi.mounts_cnt; i++) {
|
|
char *what = strchr(uwsgi.mounts[i], '=');
|
|
if (what) {
|
|
what[0] = 0;
|
|
what++;
|
|
uwsgi_log("mounting %s on %s\n", what, uwsgi.mounts[i]);
|
|
for (j = 0; j < 256; j++) {
|
|
if (uwsgi.p[j]->mount_app) {
|
|
if (!uwsgi_startswith(uwsgi.mounts[i], "regexp://", 9)) {
|
|
if (uwsgi.p[j]->mount_app(uwsgi.mounts[i]+9, what, 1) != -1)
|
|
break;
|
|
}
|
|
else {
|
|
if (uwsgi.p[j]->mount_app(uwsgi.mounts[i], what, 0) != -1)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
what--;
|
|
what[0] = '=';
|
|
}
|
|
else {
|
|
uwsgi_log("invalid mountpoint: %s\n", uwsgi.mounts[i]);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// no app initialized and virtualhosting enabled
|
|
if (uwsgi_apps_cnt == 0 && uwsgi.numproc > 0 && !uwsgi.command_mode) {
|
|
if (uwsgi.need_app) {
|
|
if (!uwsgi.lazy)
|
|
uwsgi_log("*** no app loaded. GAME OVER ***\n");
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
else {
|
|
uwsgi_log("*** no app loaded. going in full dynamic mode ***\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void uwsgi_opt_true(char *opt, char *value, void *key) {
|
|
|
|
int *ptr = (int *) key;
|
|
*ptr = 1;
|
|
if (value) {
|
|
if (!strcasecmp("false", value) || !strcasecmp("off", value) || !strcasecmp("no", value) || !strcmp("0", value)) {
|
|
*ptr = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_cluster_reload(char *opt, char *value, void *foobar) {
|
|
send_udp_message(98, 0, value, NULL, 0);
|
|
exit(0);
|
|
}
|
|
|
|
void uwsgi_opt_cluster_log(char *opt, char *value, void *foobar) {
|
|
uwsgi_stdin_sendto(value, 96, 0);
|
|
exit(0);
|
|
}
|
|
|
|
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
|
int *ptr = (int *) key;
|
|
if (value) {
|
|
*ptr = atoi((char *)value);
|
|
}
|
|
else {
|
|
*ptr = 1;
|
|
}
|
|
|
|
if (*ptr < 0) {
|
|
uwsgi_log("invalid value for option \"%s\": must be > 0\n", opt);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_set_rawint(char *opt, char *value, void *key) {
|
|
int *ptr = (int *) key;
|
|
if (value) {
|
|
*ptr = atoi((char *)value);
|
|
}
|
|
else {
|
|
*ptr = 1;
|
|
}
|
|
}
|
|
|
|
|
|
void uwsgi_opt_set_64bit(char *opt, char *value, void *key) {
|
|
uint64_t *ptr = (uint64_t *) key;
|
|
|
|
if (value) {
|
|
*ptr = (strtoul(value, NULL, 10)) ;
|
|
}
|
|
else {
|
|
*ptr = 1;
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_set_megabytes(char *opt, char *value, void *key) {
|
|
uint64_t *ptr = (uint64_t *) key;
|
|
*ptr = (strtoul(value, NULL, 10)) * 1024 * 1024;
|
|
}
|
|
|
|
void uwsgi_opt_set_dyn(char *opt, char *value, void *key) {
|
|
|
|
long *fake_ptr = (long *) key;
|
|
uint8_t dyn_opt_id = (long) fake_ptr;
|
|
uwsgi.shared->options[dyn_opt_id] = atoi(value);
|
|
}
|
|
|
|
void uwsgi_opt_dyn_true(char *opt, char *value, void *key) {
|
|
|
|
long *fake_ptr = (long *) key;
|
|
uint8_t dyn_opt_id = (long) fake_ptr;
|
|
uwsgi.shared->options[dyn_opt_id] = 1;
|
|
}
|
|
|
|
void uwsgi_opt_dyn_false(char *opt, char *value, void *key) {
|
|
|
|
long *fake_ptr = (long *) key;
|
|
uint8_t dyn_opt_id = (long) fake_ptr;
|
|
uwsgi.shared->options[dyn_opt_id] = 0;
|
|
}
|
|
|
|
void uwsgi_opt_set_str(char *opt, char *value, void *key) {
|
|
char **ptr = (char **) key;
|
|
*ptr = (char *) value;
|
|
}
|
|
|
|
void uwsgi_opt_set_logger(char *opt, char *value, void *prefix) {
|
|
|
|
if (!value) value = "";
|
|
|
|
if (prefix) {
|
|
uwsgi.requested_logger = uwsgi_concat3((char *)prefix, ":", value);
|
|
}
|
|
else {
|
|
uwsgi.requested_logger = uwsgi_str(value);
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_set_str_spaced(char *opt, char *value, void *key) {
|
|
char **ptr = (char **) key;
|
|
*ptr = uwsgi_concat2((char *) value, " ");
|
|
}
|
|
|
|
void uwsgi_opt_add_string_list(char *opt, char *value, void *list) {
|
|
struct uwsgi_string_list **ptr = (struct uwsgi_string_list **) list;
|
|
uwsgi_string_new_list(ptr, value);
|
|
}
|
|
|
|
void uwsgi_opt_add_shared_socket(char *opt, char *value, void *protocol) {
|
|
uwsgi_new_shared_socket(generate_socket_name(value));
|
|
}
|
|
|
|
void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
|
|
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
|
|
uwsgi_sock->proto_name = protocol;
|
|
}
|
|
|
|
void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
|
|
|
|
char *p = strchr(value, '=');
|
|
if (!p) {
|
|
uwsgi_log("invalid placeholder/--set value\n");
|
|
exit(1);
|
|
}
|
|
|
|
p[0] = 0;
|
|
add_exported_option(uwsgi_str(value), p+1, 1);
|
|
p[0] = '=';
|
|
|
|
}
|
|
|
|
void uwsgi_opt_set_umask(char *opt, char *value, void *mode) {
|
|
|
|
mode_t umask_mode = 0;
|
|
|
|
if (strlen(value) < 3) {
|
|
uwsgi_log("invalid umask: %s\n", value);
|
|
}
|
|
umask_mode = 0;
|
|
if (strlen(value) == 3) {
|
|
umask_mode = (umask_mode << 3) + (value[0] - '0');
|
|
umask_mode = (umask_mode << 3) + (value[1] - '0');
|
|
umask_mode = (umask_mode << 3) + (value[2] - '0');
|
|
}
|
|
else {
|
|
umask_mode = (umask_mode << 3) + (value[1] - '0');
|
|
umask_mode = (umask_mode << 3) + (value[2] - '0');
|
|
umask_mode = (umask_mode << 3) + (value[3] - '0');
|
|
}
|
|
umask(umask_mode);
|
|
|
|
uwsgi.do_not_change_umask = 1;
|
|
|
|
}
|
|
|
|
void uwsgi_opt_print(char *opt, char *value, void *str) {
|
|
if (str) {
|
|
fprintf(stdout, "%s\n", (char *) str);
|
|
exit(0);
|
|
}
|
|
fprintf(stdout, "%s\n", value);
|
|
}
|
|
|
|
void uwsgi_opt_set_uid(char *opt, char *value, void *none) {
|
|
|
|
uwsgi.uid = atoi(value);
|
|
if (!uwsgi.uid)
|
|
uwsgi.uidname = value;
|
|
}
|
|
|
|
void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
|
|
|
|
uwsgi.gid = atoi(value);
|
|
if (!uwsgi.gid)
|
|
uwsgi.gidname = value;
|
|
}
|
|
|
|
#ifdef UWSGI_CAP
|
|
void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
|
|
uwsgi_build_cap(value);
|
|
}
|
|
#endif
|
|
#ifdef __linux__
|
|
void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
|
|
uwsgi_build_unshare(value);
|
|
}
|
|
#endif
|
|
|
|
void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
|
uwsgi_daemon_new(&uwsgi.daemons, value);
|
|
}
|
|
|
|
void uwsgi_opt_set_env(char *opt, char *value, void *none) {
|
|
if (putenv(value)) {
|
|
uwsgi_error("putenv()");
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
|
|
if (unsetenv(value)) {
|
|
uwsgi_error("unsetenv()");
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
|
|
|
long *signum_fake_ptr = (long *) sig;
|
|
int signum = (long) signum_fake_ptr;
|
|
signal_pidfile(signum, pidfile);
|
|
exit(0);
|
|
}
|
|
|
|
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
|
|
|
char *p = strtok(uwsgi_concat2(value, ""), ",");
|
|
while (p != NULL) {
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_debug("loading plugin %s\n", p);
|
|
#endif
|
|
if (uwsgi_load_plugin(-1, p, NULL)) {
|
|
build_options();
|
|
}
|
|
p = strtok(NULL, ",");
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_add_app(char *opt, char *value, void *regexp) {
|
|
if (uwsgi.mounts_cnt < MAX_APPS) {
|
|
if (regexp) {
|
|
uwsgi.mounts[uwsgi.mounts_cnt] = uwsgi_concat2("regexp://", value);
|
|
}
|
|
else {
|
|
uwsgi.mounts[uwsgi.mounts_cnt] = value;
|
|
}
|
|
uwsgi.mounts_cnt++;
|
|
}
|
|
else {
|
|
uwsgi_log("you can specify at most %d --%s options\n", opt, MAX_APPS);
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_check_static(char *opt, char *value, void *foobar) {
|
|
|
|
uwsgi_dyn_dict_new(&uwsgi.check_static, value, strlen(value), NULL, 0);
|
|
uwsgi_log("[uwsgi-static] added check for %s\n", value);
|
|
uwsgi.build_mime_dict = 1;
|
|
|
|
}
|
|
|
|
void uwsgi_opt_add_dyn_dict(char *opt, char *value, void *dict) {
|
|
|
|
char *equal = strchr(value, '=');
|
|
if (!equal) {
|
|
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
|
exit(1);
|
|
}
|
|
|
|
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
|
|
|
uwsgi_dyn_dict_new(udd, value, equal-value, equal+1, strlen(equal+1));
|
|
|
|
}
|
|
|
|
#ifdef UWSGI_PCRE
|
|
void uwsgi_opt_add_regexp_dyn_dict(char *opt, char *value, void *dict) {
|
|
|
|
char *space = strchr(value, ' ');
|
|
if (!space) {
|
|
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
|
exit(1);
|
|
}
|
|
|
|
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
|
|
|
struct uwsgi_dyn_dict *new_udd = uwsgi_dyn_dict_new(udd, value, space-value, space+1, strlen(space+1));
|
|
|
|
char *regexp = uwsgi_concat2n(value, space-value, "", 0);
|
|
|
|
if (uwsgi_regexp_build(regexp, &new_udd->pattern, &new_udd->pattern_extra)) {
|
|
exit(1);
|
|
}
|
|
|
|
free(regexp);
|
|
}
|
|
#endif
|
|
|
|
|
|
void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
|
|
|
|
if (!strcasecmp("x-sendfile", value)) {
|
|
uwsgi.file_serve_mode = 2;
|
|
}
|
|
else if (!strcasecmp("xsendfile", value)) {
|
|
uwsgi.file_serve_mode = 2;
|
|
}
|
|
else if (!strcasecmp("x-accel-redirect", value)) {
|
|
uwsgi.file_serve_mode = 1;
|
|
}
|
|
else if (!strcasecmp("xaccelredirect", value)) {
|
|
uwsgi.file_serve_mode = 1;
|
|
}
|
|
else if (!strcasecmp("nginx", value)) {
|
|
uwsgi.file_serve_mode = 1;
|
|
}
|
|
|
|
}
|
|
|
|
void uwsgi_opt_static_map(char *opt, char *value, void *static_maps) {
|
|
|
|
struct uwsgi_dyn_dict **maps = (struct uwsgi_dyn_dict **) static_maps;
|
|
char *mountpoint = uwsgi_str(value);
|
|
|
|
char *docroot = strchr(mountpoint, '=');
|
|
|
|
if (!docroot) {
|
|
uwsgi_log("invalid document root in static map, syntax mountpoint=docroot\n");
|
|
exit(1);
|
|
}
|
|
docroot[0] = 0;
|
|
docroot++;
|
|
uwsgi_dyn_dict_new(maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
|
|
uwsgi_log("[uwsgi-static] added mapping for %s => %s\n", mountpoint, docroot);
|
|
uwsgi.build_mime_dict = 1;
|
|
}
|
|
|
|
|
|
int uwsgi_zerg_attach(char *value) {
|
|
|
|
int count = 8;
|
|
int zerg_fd = uwsgi_connect(value, 30, 0);
|
|
if (zerg_fd < 0) {
|
|
uwsgi_log("--- unable to connect to zerg server %s ---\n", value);
|
|
return -1;
|
|
}
|
|
|
|
int last_count = count;
|
|
|
|
int *zerg = uwsgi_attach_fd(zerg_fd, &count, "uwsgi-zerg", 10);
|
|
if (zerg == NULL) {
|
|
if (last_count != count) {
|
|
close(zerg_fd);
|
|
zerg_fd = uwsgi_connect(value, 30, 0);
|
|
if (zerg_fd < 0) {
|
|
uwsgi_log("--- unable to connect to zerg server %s ---\n", value);
|
|
return -1;
|
|
}
|
|
zerg = uwsgi_attach_fd(zerg_fd, &count, "uwsgi-zerg", 10);
|
|
}
|
|
}
|
|
|
|
if (zerg == NULL) {
|
|
uwsgi_log("--- invalid data received from zerg-server ---\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!uwsgi.zerg) {
|
|
uwsgi.zerg = zerg;
|
|
}
|
|
else {
|
|
int pos = 0;
|
|
for(;;) {
|
|
if (uwsgi.zerg[pos] == -1) {
|
|
uwsgi.zerg = realloc(uwsgi.zerg, (sizeof(int) * (pos)) + (sizeof(int) * count+1));
|
|
if (!uwsgi.zerg) {
|
|
uwsgi_error("realloc()");
|
|
exit(1);
|
|
}
|
|
memcpy(&uwsgi.zerg[pos], zerg, (sizeof(int) * count+1));
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
close(zerg_fd);
|
|
return 0;
|
|
}
|
|
|
|
void uwsgi_opt_signal(char *opt, char *value, void *foobar) {
|
|
uwsgi_command_signal(value);
|
|
}
|
|
|
|
void uwsgi_opt_log_date(char *opt, char *value, void *foobar) {
|
|
|
|
uwsgi.logdate = 1;
|
|
if (value) {
|
|
if (strcasecmp("true", value) && strcasecmp("1", value) && strcasecmp("on", value) && strcasecmp("yes", value)) {
|
|
uwsgi.log_strftime = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_chmod_socket(char *opt, char *value, void *foobar) {
|
|
|
|
int i;
|
|
|
|
uwsgi.chmod_socket = 1;
|
|
if (value) {
|
|
if (strlen(value) == 1 && *value == '1') {
|
|
return;
|
|
}
|
|
if (strlen(value) != 3) {
|
|
uwsgi_log("invalid chmod value: %s\n", value);
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
if (value[i] < '0' || value[i] > '7') {
|
|
uwsgi_log("invalid chmod value: %s\n", value);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[0] - '0');
|
|
uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[1] - '0');
|
|
uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[2] - '0');
|
|
}
|
|
|
|
}
|
|
|
|
void uwsgi_opt_logfile_chmod(char *opt, char *value, void *foobar) {
|
|
|
|
int i;
|
|
|
|
if (strlen(value) != 3) {
|
|
uwsgi_log("invalid chmod value: %s\n", value);
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
if (value[i] < '0' || value[i] > '7') {
|
|
uwsgi_log("invalid chmod value: %s\n", value);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[0] - '0');
|
|
uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[1] - '0');
|
|
uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[2] - '0');
|
|
|
|
}
|
|
|
|
void uwsgi_opt_max_vars(char *opt, char *value, void *foobar) {
|
|
|
|
uwsgi.max_vars = atoi(value);
|
|
uwsgi.vec_size = 4 + 1 + (4 * uwsgi.max_vars);
|
|
}
|
|
|
|
void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
|
|
uwsgi_log("[WARNING] option \"%s\" is deprecated: %s\n", opt, (char *)message);
|
|
}
|
|
|
|
void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
|
|
|
#ifdef UWSGI_INI
|
|
if (uwsgi_endswith(filename, ".ini")) { uwsgi_opt_load_ini(opt, filename, none); return;}
|
|
#endif
|
|
#ifdef UWSGI_XML
|
|
if (uwsgi_endswith(filename, ".xml")) { uwsgi_opt_load_xml(opt, filename, none); return;}
|
|
#endif
|
|
#ifdef UWSGI_YAML
|
|
if (uwsgi_endswith(filename, ".yaml")) { uwsgi_opt_load_yml(opt, filename, none); return;}
|
|
if (uwsgi_endswith(filename, ".yml")) { uwsgi_opt_load_yml(opt, filename, none); return;}
|
|
#endif
|
|
#ifdef UWSGI_JSON
|
|
if (uwsgi_endswith(filename, ".json")) { uwsgi_opt_load_json(opt, filename, none); return;}
|
|
if (uwsgi_endswith(filename, ".js")) { uwsgi_opt_load_json(opt, filename, none); return;}
|
|
#endif
|
|
}
|
|
|
|
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
|
|
|
if (uwsgi.logic_opt) {
|
|
uwsgi_log("recursive logic in options is not supported (option = %s)\n", opt);
|
|
exit(1);
|
|
}
|
|
uwsgi.logic_opt = (int (*)(char *, char *)) func;
|
|
uwsgi.logic_opt_cycles = 0;
|
|
if (arg) {
|
|
uwsgi.logic_opt_arg = uwsgi_str(arg);
|
|
}
|
|
else {
|
|
uwsgi.logic_opt_arg = NULL;
|
|
}
|
|
}
|
|
|
|
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
|
|
}
|
|
|
|
#ifdef UWSGI_INI
|
|
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
|
config_magic_table_fill(filename, uwsgi.magic_table);
|
|
uwsgi_ini_config(filename, uwsgi.magic_table);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UWSGI_XML
|
|
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
|
config_magic_table_fill(filename, uwsgi.magic_table);
|
|
uwsgi_xml_config(filename, uwsgi.wsgi_req, uwsgi.magic_table);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UWSGI_YAML
|
|
void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
|
|
config_magic_table_fill(filename, uwsgi.magic_table);
|
|
uwsgi_yaml_config(filename, uwsgi.magic_table);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UWSGI_SQLITE3
|
|
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
|
config_magic_table_fill(filename, uwsgi.magic_table);
|
|
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UWSGI_JSON
|
|
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
|
config_magic_table_fill(filename, uwsgi.magic_table);
|
|
uwsgi_json_config(filename, uwsgi.magic_table);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UWSGI_LDAP
|
|
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
|
uwsgi_ldap_config(url);
|
|
}
|
|
#endif
|
|
|
|
void uwsgi_opt_flock(char *opt, char *filename, void *none) {
|
|
|
|
int fd = open(filename, O_RDWR);
|
|
if (fd < 0) {
|
|
uwsgi_error_open(filename);
|
|
exit(1);
|
|
}
|
|
|
|
if (uwsgi_fcntl_is_locked(fd)) {
|
|
uwsgi_log("uWSGI ERROR: %s is locked by another instance\n", filename);
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
|
|
|
int fd = open(filename, O_RDWR);
|
|
if (fd < 0) {
|
|
uwsgi_error_open(filename);
|
|
exit(1);
|
|
}
|
|
|
|
if (uwsgi_fcntl_lock(fd)) {
|
|
exit(1);
|
|
}
|
|
|
|
}
|