PageRenderTime 5225ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 1ms

/uwsgi-1.2.4/uwsgi.c

#
C | 4104 lines | 3225 code | 720 blank | 159 comment | 837 complexity | c49f69869a8273d53b71d59d53ff765b MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. *** uWSGI ***
  3. Copyright (C) 2009-2012 Unbit S.a.s. <info@unbit.it>
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. */
  16. #include "uwsgi.h"
  17. struct uwsgi_server uwsgi;
  18. #if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
  19. #include <crt_externs.h>
  20. char **environ;
  21. #else
  22. extern char **environ;
  23. #endif
  24. UWSGI_DECLARE_EMBEDDED_PLUGINS;
  25. static struct uwsgi_option uwsgi_base_options[] = {
  26. {"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL,0},
  27. {"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi",0},
  28. {"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http",0},
  29. {"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi",0},
  30. #ifdef UWSGI_SCTP
  31. {"sctp-socket", required_argument, 's', "bind to the specified SCTP socket using uwsgi protocol", uwsgi_opt_add_socket, "sctp",0},
  32. #endif
  33. {"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol,0},
  34. {"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol,0},
  35. {"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL,0},
  36. {"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc,0},
  37. {"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc,0},
  38. {"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI ,0},
  39. {"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose,0},
  40. {"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
  41. {"no-harakiri-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
  42. {"no-harakiri-after-req-hook", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh,0},
  43. {"backtrace-depth", no_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
  44. {"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SPOOLER_HARAKIRI,0},
  45. {"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MULE_HARAKIRI,0},
  46. #ifdef UWSGI_XML
  47. {"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
  48. {"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
  49. #endif
  50. {"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero,0},
  51. {"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
  52. {"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
  53. {"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
  54. {"if-env", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
  55. {"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},
  56. {"ifenv", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
  57. {"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
  58. {"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
  59. {"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
  60. {"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},
  61. {"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
  62. {"if-file", required_argument, 0, "(opt logic) check for file existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_file, UWSGI_OPT_IMMEDIATE},
  63. {"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},
  64. {"if-dir", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
  65. {"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},
  66. {"ifdir", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
  67. {"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
  68. {"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
  69. {"ignore-sigpipe", no_argument, 0, "do not report (annoying) SIGPIPE", uwsgi_opt_true, &uwsgi.ignore_sigpipe,0},
  70. {"ignore-write-errors", no_argument, 0, "do not report (annoying) write()/writev() errors", uwsgi_opt_true, &uwsgi.ignore_write_errors,0},
  71. {"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},
  72. {"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},
  73. {"disable-write-exception", no_argument, 0, "disable exception generation on write()/writev()", uwsgi_opt_true, &uwsgi.disable_write_exception,0},
  74. {"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL,0},
  75. {"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
  76. {"daemonize2", required_argument, 0, "daemonize uWSGI after app loading", uwsgi_opt_set_str, &uwsgi.daemonize2, 0},
  77. {"stop", required_argument, 0, "stop an instance", uwsgi_opt_pidfile_signal, (void *) SIGINT, UWSGI_OPT_IMMEDIATE},
  78. {"reload", required_argument, 0, "reload an instance", uwsgi_opt_pidfile_signal, (void *) SIGHUP, UWSGI_OPT_IMMEDIATE},
  79. {"pause", required_argument, 0, "pause an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
  80. {"suspend", required_argument, 0, "suspend an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP,UWSGI_OPT_IMMEDIATE},
  81. {"resume", required_argument, 0, "resume an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP,UWSGI_OPT_IMMEDIATE},
  82. {"listen", required_argument, 'l', "set the socket listen queue size", uwsgi_opt_set_int, &uwsgi.listen_queue,0},
  83. {"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL,0},
  84. {"buffer-size", required_argument, 'b', "set internal buffer size", uwsgi_opt_set_int, &uwsgi.buffer_size,0},
  85. {"memory-report", no_argument, 'm', "enable memory report", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_MEMORY_DEBUG,0},
  86. {"profiler", required_argument, 0, "enable the specified profiler", uwsgi_opt_set_str, &uwsgi.profiler,0},
  87. {"cgi-mode", no_argument, 'c', "force CGI-mode for plugins supporting it", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_CGI_MODE,0},
  88. {"abstract-socket", no_argument, 'a', "force UNIX socket in abstract mode (Linux only)", uwsgi_opt_true, &uwsgi.abstract_socket,0},
  89. {"chmod-socket", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL,0},
  90. {"chmod", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL,0},
  91. {"chown-socket", required_argument, 0, "chown unix sockets", uwsgi_opt_set_str, &uwsgi.chown_socket, 0},
  92. {"umask", required_argument, 0, "set umask", uwsgi_opt_set_umask, NULL, UWSGI_OPT_IMMEDIATE},
  93. #ifdef __linux__
  94. {"freebind", no_argument, 0, "put socket in freebind mode", uwsgi_opt_true, &uwsgi.freebind,0},
  95. #endif
  96. {"map-socket", required_argument, 0, "map sockets to specific workers", uwsgi_opt_add_string_list, &uwsgi.map_socket,0},
  97. #ifdef UWSGI_THREADING
  98. {"enable-threads", no_argument, 'T', "enable threads", uwsgi_opt_true, &uwsgi.has_threads, 0},
  99. #endif
  100. {"auto-procname", no_argument, 0, "automatically set processes name to something meaningful", uwsgi_opt_true, &uwsgi.auto_procname,0},
  101. {"procname-prefix", required_argument, 0, "add a prefix to the process names", uwsgi_opt_set_str, &uwsgi.procname_prefix, UWSGI_OPT_PROCNAME},
  102. {"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},
  103. {"procname-append", required_argument, 0, "append a string to process names", uwsgi_opt_set_str, &uwsgi.procname_append, UWSGI_OPT_PROCNAME},
  104. {"procname", required_argument, 0, "set process names", uwsgi_opt_set_str, &uwsgi.procname, UWSGI_OPT_PROCNAME},
  105. {"procname-master", required_argument, 0, "set master process name", uwsgi_opt_set_str, &uwsgi.procname_master, UWSGI_OPT_PROCNAME},
  106. {"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
  107. {"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
  108. {"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process,0},
  109. {"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_set_str, &uwsgi.emperor_dir,0},
  110. {"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant,0},
  111. {"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
  112. {"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
  113. {"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
  114. {"emperor-broodlord", required_argument, 0, "run the emperor in BroodLord mode", uwsgi_opt_set_int, &uwsgi.emperor_broodlord, 0},
  115. {"emperor-amqp-vhost", required_argument, 0, "set emperor amqp virtualhost", uwsgi_opt_set_str, &uwsgi.emperor_amqp_vhost, 0},
  116. {"emperor-amqp-username", required_argument, 0, "set emperor amqp username", uwsgi_opt_set_str, &uwsgi.emperor_amqp_username, 0},
  117. {"emperor-amqp-password", required_argument, 0, "set emperor amqp password", uwsgi_opt_set_str, &uwsgi.emperor_amqp_password, 0},
  118. {"emperor-throttle", required_argument, 0, "throttle each vassal spawn (in seconds)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
  119. {"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},
  120. {"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
  121. {"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
  122. {"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook,0},
  123. {"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},
  124. {"auto-snapshot", optional_argument, 0, "automatically make workers snaphost after reload", uwsgi_opt_set_int, &uwsgi.auto_snapshot, UWSGI_OPT_LAZY},
  125. {"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},
  126. {"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload,0},
  127. {"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
  128. {"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
  129. {"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
  130. {"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER ,0},
  131. {"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS,0},
  132. {"socket-timeout", required_argument, 'z', "set internal sockets timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SOCKET_TIMEOUT, 0},
  133. {"no-fd-passing", no_argument, 0, "disable file descriptor passing", uwsgi_opt_true, &uwsgi.no_fd_passing, 0},
  134. {"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
  135. {"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
  136. {"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
  137. {"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
  138. {"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_int, &uwsgi.cache_max_items, 0},
  139. {"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_int, &uwsgi.cache_blocksize, 0},
  140. {"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store , UWSGI_OPT_MASTER},
  141. {"cache-store-sync", required_argument, 0, "set frequency of sync for persistent cache", uwsgi_opt_set_int, &uwsgi.cache_store_sync,0},
  142. {"cache-server", required_argument, 0, "enable the threaded cache server", uwsgi_opt_set_str, &uwsgi.cache_server, 0},
  143. {"cache-server-threads", required_argument, 0, "set the number of threads for the cache server", uwsgi_opt_set_int, &uwsgi.cache_server_threads,0},
  144. {"cache-no-expire", no_argument, 0, "disable auto sweep of expired items", uwsgi_opt_true, &uwsgi.cache_no_expire,0},
  145. {"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},
  146. {"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},
  147. {"queue", required_argument, 0, "enable shared queue", uwsgi_opt_set_int, &uwsgi.queue_size, 0},
  148. {"queue-blocksize", required_argument, 0, "set queue blocksize", uwsgi_opt_set_int, &uwsgi.queue_store_sync, 0},
  149. {"queue-store", required_argument, 0, "enable persistent queue to disk", uwsgi_opt_set_str, &uwsgi.queue_store, UWSGI_OPT_MASTER},
  150. {"queue-store-sync", required_argument, 0, "set frequency of sync for persistent queue", uwsgi_opt_set_int, &uwsgi.queue_store_sync,0},
  151. #ifdef UWSGI_SPOOLER
  152. {"spooler", required_argument, 'Q', "run a spooler on the specified directory", uwsgi_opt_add_spooler, NULL, UWSGI_OPT_MASTER},
  153. {"spooler-ordered", no_argument, 0, "try to order the execution of spooler tasks", uwsgi_opt_true, &uwsgi.spooler_ordered,0},
  154. {"spooler-chdir", required_argument, 0, "chdir() to specified directory before each spooler task", uwsgi_opt_set_str, &uwsgi.spooler_chdir,0},
  155. {"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, 0},
  156. {"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
  157. {"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},
  158. #endif
  159. {"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
  160. {"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
  161. {"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
  162. {"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
  163. {"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
  164. {"signals-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
  165. {"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_dyn_false, (void *) UWSGI_OPTION_LOGGING, 0},
  166. {"flock", required_argument, 0, "lock the specified file before starting, exit if locked", uwsgi_opt_flock, NULL, UWSGI_OPT_IMMEDIATE},
  167. {"flock-wait", required_argument, 0, "lock the specified file before starting, wait if locked", uwsgi_opt_flock_wait, NULL, UWSGI_OPT_IMMEDIATE},
  168. {"flock2", required_argument, 0, "lock the specified file after logging/daemon setup, exit if locked", uwsgi_opt_set_str, &uwsgi.flock2, UWSGI_OPT_IMMEDIATE},
  169. {"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},
  170. {"pidfile", required_argument, 0, "create pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile,0},
  171. {"pidfile2", required_argument, 0, "create pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile2,0},
  172. {"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot,0},
  173. {"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
  174. {"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
  175. {"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
  176. #ifdef UWSGI_CAP
  177. {"cap", required_argument,0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
  178. #endif
  179. #ifdef __linux__
  180. {"unshare", required_argument,0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0},
  181. #endif
  182. {"exec-pre-jail", required_argument,0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail ,0},
  183. {"exec-post-jail", required_argument,0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail,0},
  184. {"exec-in-jail", required_argument,0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail,0},
  185. {"exec-as-root", required_argument,0, "run the specified command before privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_root,0},
  186. {"exec-as-user", required_argument,0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user,0},
  187. {"exec-as-user-atexit", required_argument,0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit,0},
  188. {"exec-pre-app", required_argument,0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app,0},
  189. #ifdef UWSGI_INI
  190. {"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
  191. #endif
  192. #ifdef UWSGI_YAML
  193. {"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL,UWSGI_OPT_IMMEDIATE},
  194. {"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL,UWSGI_OPT_IMMEDIATE},
  195. #endif
  196. #ifdef UWSGI_JSON
  197. {"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL,0},
  198. {"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL,0},
  199. #endif
  200. #ifdef UWSGI_SQLITE3
  201. {"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
  202. {"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
  203. #endif
  204. #ifdef UWSGI_ZEROMQ
  205. {"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_set_str, &uwsgi.zeromq,0},
  206. {"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_set_str, &uwsgi.zeromq,0},
  207. #endif
  208. #ifdef UWSGI_LDAP
  209. {"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
  210. {"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
  211. {"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
  212. #endif
  213. {"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
  214. {"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
  215. {"no-server", no_argument, 0, "force no-server mode", uwsgi_opt_true, &uwsgi.no_server,0},
  216. {"command-mode", no_argument, 0, "force command mode", uwsgi_opt_true, &uwsgi.command_mode, UWSGI_OPT_IMMEDIATE},
  217. {"no-defer-accept", no_argument, 0, "disable deferred-accept on sockets", uwsgi_opt_true, &uwsgi.no_defer_accept,0},
  218. {"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max,0},
  219. {"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},
  220. {"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 },
  221. {"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},
  222. {"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},
  223. #ifdef __linux__
  224. #ifdef MADV_MERGEABLE
  225. {"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
  226. #endif
  227. #endif
  228. {"never-swap", no_argument, 0, "lock all memory pages avoiding swapping", uwsgi_opt_true, &uwsgi.never_swap, 0},
  229. {"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},
  230. {"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},
  231. {"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},
  232. {"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
  233. {"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
  234. {"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
  235. {"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
  236. {"cpu-affinity", required_argument, 0, "set cpu affinity", uwsgi_opt_set_int, &uwsgi.cpu_affinity, 0},
  237. {"post-buffering", required_argument, 0, "enable post buffering", uwsgi_opt_set_64bit, &uwsgi.post_buffering, 0},
  238. {"post-buffering-bufsize", required_argument, 0, "set buffer size for read() in post buffering mode", uwsgi_opt_set_64bit, &uwsgi.post_buffering_bufsize,0},
  239. {"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},
  240. {"no-default-app", no_argument, 0, "do not fallback to default app", uwsgi_opt_true, &uwsgi.no_default_app, 0},
  241. {"manage-script-name", no_argument, 0, "automatically rewrite SCRIPT_NAME and PATH_INFO", uwsgi_opt_true, &uwsgi.manage_script_name, 0},
  242. {"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &uwsgi.ignore_script_name, 0},
  243. {"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &uwsgi.catch_exceptions, 0},
  244. {"reload-on-exception", no_argument, 0, "reload a worker when an exception is raised", uwsgi_opt_true, &uwsgi.reload_on_exception, 0},
  245. {"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},
  246. {"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},
  247. {"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},
  248. #ifdef UWSGI_UDP
  249. {"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
  250. #endif
  251. {"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
  252. {"stats-server", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
  253. #ifdef UWSGI_MULTICAST
  254. {"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
  255. {"cluster", required_argument, 0, "join specified uWSGI cluster", uwsgi_opt_set_str, &uwsgi.cluster, UWSGI_OPT_MASTER},
  256. {"cluster-nodes", required_argument, 0, "get nodes list from the specified cluster", uwsgi_opt_true, &uwsgi.cluster_nodes, UWSGI_OPT_MASTER|UWSGI_OPT_CLUSTER},
  257. {"cluster-reload", required_argument, 0, "send a reload message to the cluster", uwsgi_opt_cluster_reload, NULL, UWSGI_OPT_IMMEDIATE},
  258. {"cluster-log", required_argument, 0, "send a log line to the cluster", uwsgi_opt_cluster_log, NULL, UWSGI_OPT_IMMEDIATE},
  259. #endif
  260. {"subscribe-to", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
  261. {"st", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
  262. {"subscribe", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
  263. {"subscribe-freq", required_argument, 0, "send subscription announce at the specified interval", uwsgi_opt_set_int, &uwsgi.subscribe_freq, 0},
  264. {"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
  265. {"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
  266. #ifdef UWSGI_SNMP
  267. {"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
  268. {"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
  269. #endif
  270. {"check-interval", required_argument, 0, "set the interval (in seconds) of master checks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MASTER_INTERVAL, 0},
  271. {"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},
  272. {"binary-path", required_argument, 0, "force binary path", uwsgi_opt_set_str, &uwsgi.binary_path, 0},
  273. #ifdef UWSGI_ASYNC
  274. {"async", required_argument, 0, "enable async mode with specified cores", uwsgi_opt_set_int, &uwsgi.async, 0},
  275. #endif
  276. {"max-fd", required_argument, 0, "set maximum number of file descriptors (requires root privileges)", uwsgi_opt_set_int, &uwsgi.requested_max_fd, 0},
  277. {"logto", required_argument, 0, "set logfile/udp address", uwsgi_opt_set_str, &uwsgi.logfile, 0},
  278. {"logto2", required_argument, 0, "log to specified file or udp address after privileges drop", uwsgi_opt_set_str, &uwsgi.logto2, 0},
  279. {"logfile-chown", no_argument, 0, "chown logfiles", uwsgi_opt_true, &uwsgi.logfile_chown, 0},
  280. {"logfile-chmod", required_argument, 0, "chmod logfiles", uwsgi_opt_logfile_chmod, NULL, 0},
  281. {"log-syslog", optional_argument, 0, "log to syslog", uwsgi_opt_set_logger, "syslog", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
  282. {"log-socket", required_argument, 0, "send logs to the specified socket", uwsgi_opt_set_logger, "socket", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
  283. {"logger", required_argument, 0, "set logger system", uwsgi_opt_set_logger, NULL, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER },
  284. {"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
  285. #ifdef UWSGI_ZEROMQ
  286. {"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
  287. #endif
  288. {"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, 0},
  289. {"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
  290. {"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
  291. {"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_int, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
  292. {"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
  293. {"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
  294. {"log-date", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
  295. {"log-prefix", optional_argument, 0, "prefix logs with a string", uwsgi_opt_log_date, NULL, 0},
  296. {"log-zero", no_argument, 0, "log responses without body", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_ZERO,0},
  297. {"log-slow", required_argument, 0, "log requestes slower than the specified number of milliseconds", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_SLOW, 0},
  298. {"log-4xx", no_argument, 0, "log requests with a 4xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_4xx,0},
  299. {"log-5xx", no_argument, 0, "log requests with a 5xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_5xx,0},
  300. {"log-big", required_argument, 0, "log requestes bigger than the specified size", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_BIG, 0},
  301. {"log-sendfile", required_argument, 0, "log sendfile requests", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_SENDFILE, 0},
  302. {"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
  303. {"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},
  304. {"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root,0},
  305. {"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
  306. {"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
  307. {"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
  308. {"cheap", no_argument, 0, "set cheap mode (spawn workers only after the first request)", uwsgi_opt_true, &uwsgi.cheap, UWSGI_OPT_MASTER},
  309. {"cheaper", required_argument, 0, "set cheaper mode (adaptive process spawning)", uwsgi_opt_set_int, &uwsgi.cheaper_count, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
  310. {"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning)", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
  311. {"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},
  312. {"cheaper-overload", required_argument, 0, "increase workers after specified overload", uwsgi_opt_set_64bit, &uwsgi.cheaper_overload, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
  313. {"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, UWSGI_OPT_MASTER},
  314. {"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
  315. {"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_app, NULL,0},
  316. #ifdef UWSGI_PCRE
  317. {"regexp-mount", required_argument, 0, "load application under a regexp-based mountpoint", uwsgi_opt_add_app, (void *) 1, 0},
  318. #endif
  319. {"grunt", no_argument, 0, "enable grunt mode (in-request fork)", uwsgi_opt_true, &uwsgi.grunt, 0},
  320. {"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},
  321. {"thread-stacksize", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
  322. {"threads-stacksize", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
  323. {"thread-stack-size", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
  324. {"threads-stack-size", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
  325. {"vhost", no_argument, 0, "enable virtualhosting mode (based on SERVER_NAME variable)", uwsgi_opt_true, &uwsgi.vhost, 0},
  326. {"vhost-host", no_argument, 0, "enable virtualhosting mode (based on HTTP_HOST variable)", uwsgi_opt_true, &uwsgi.vhost_host, UWSGI_OPT_VHOST},
  327. #ifdef UWSGI_ROUTING
  328. {"route", required_argument, 0, "add a route", uwsgi_opt_add_route, "path_info", 0},
  329. {"route-host", required_argument, 0, "add a route based on Host header", uwsgi_opt_add_route, "http_host", 0},
  330. {"route-uri", required_argument, 0, "add a route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
  331. {"route-qs", required_argument, 0, "add a route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
  332. #endif
  333. {"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
  334. {"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
  335. {"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},
  336. {"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
  337. {"static-map", required_argument, 0, "map mountpoint to static directory (or file)", uwsgi_opt_static_map, &uwsgi.static_maps, UWSGI_OPT_MIME},
  338. {"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},
  339. {"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, UWSGI_OPT_MIME},
  340. {"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},
  341. {"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
  342. {"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},
  343. {"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},
  344. {"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},
  345. #ifdef UWSGI_PCRE
  346. {"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},
  347. {"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},
  348. #endif
  349. {"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},
  350. {"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
  351. {"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
  352. {"check-cache", no_argument, 0, "check for response data in the cache", uwsgi_opt_true, &uwsgi.check_cache, 0},
  353. {"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},
  354. {"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode,0},
  355. {"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
  356. {"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
  357. {"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum,0},
  358. #ifdef __linux__
  359. {"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup,0},
  360. {"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt,0},
  361. {"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns,0},
  362. {"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns,0},
  363. {"namespace-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
  364. {"ns-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
  365. #endif
  366. {"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
  367. {"zerg", required_argument, 0, "attach to a zerg server", uwsgi_opt_add_string_list, &uwsgi.zerg_node, 0},
  368. {"zerg-fallback", no_argument, 0, "fallback to normal sockets if the zerg server is not available", uwsgi_opt_true, &uwsgi.zerg_fallback, 0},
  369. {"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
  370. {"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
  371. {"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
  372. {"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
  373. {"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},
  374. {"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
  375. {"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
  376. {"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
  377. {"plugin-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
  378. {"autoload", no_argument, 0, "try to automatically load plugins when unknown options are found", uwsgi_opt_true, &uwsgi.autoload, UWSGI_OPT_IMMEDIATE},
  379. {"allowed-modifiers", required_argument, 0,"comma separated list of allowed modifiers", uwsgi_opt_set_str, &uwsgi.allowed_modifiers, 0},
  380. {"remap-modifier", required_argument, 0, "remap request modifier from one id to another", uwsgi_opt_set_str, &uwsgi.remap_modifier, 0},
  381. {"app", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "use the more advanced \"mount\" option",0},
  382. {"dump-options", no_argument, 0, "dump the full list of available options", uwsgi_opt_true, &uwsgi.dump_options,0},
  383. {"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config,0},
  384. {"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL,0},
  385. {"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
  386. {0, 0, 0, 0, 0, 0, 0}
  387. };
  388. void show_config(void) {
  389. int i;
  390. fprintf(stdout, "\n;uWSGI instance configuration\n[uwsgi]\n");
  391. for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
  392. if (uwsgi.exported_opts[i]->value) {
  393. fprintf(stdout, "%s = %s\n", uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
  394. }
  395. else {
  396. fprintf(stdout, "%s = true\n", uwsgi.exported_opts[i]->key);
  397. }
  398. }
  399. fprintf(stdout, ";end of configuration\n\n");
  400. }
  401. int uwsgi_manage_opt(char *key, char *value) {
  402. struct uwsgi_option *op = uwsgi.options;
  403. while(op->name) {
  404. if (!strcmp(key, op->name)) {
  405. op->func(key, value, op->data);
  406. return 1;
  407. }
  408. op++;
  409. }
  410. return 0;
  411. }
  412. void uwsgi_configure() {
  413. int i;
  414. // and now apply the remaining configs
  415. restart:
  416. for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
  417. if (uwsgi.exported_opts[i]->configured)
  418. continue;
  419. uwsgi.dirty_config = 0;
  420. uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
  421. if (uwsgi.exported_opts[i]->configured == 0 && uwsgi.autoload) {
  422. uwsgi.dirty_config = uwsgi_try_autoload(uwsgi.exported_opts[i]->key);
  423. }
  424. if (uwsgi.dirty_config) goto restart;
  425. }
  426. }
  427. void config_magic_table_fill(char *filename, char **magic_table) {
  428. char *tmp = NULL;
  429. magic_table['o'] = filename;
  430. if (filename[0] == '/') {
  431. magic_table['p'] = filename;
  432. }
  433. else {
  434. magic_table['p'] = uwsgi_concat3(uwsgi.cwd, "/", filename);
  435. }
  436. magic_table['s'] = uwsgi_get_last_char(magic_table['p'], '/') + 1;
  437. magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
  438. if (magic_table['d'][strlen(magic_table['d'])-1] == '/') {
  439. tmp = magic_table['d'] + (strlen(magic_table['d']) -1) ;
  440. #ifdef UWSGI_DEBUG
  441. uwsgi_log("tmp = %c\n", *tmp);
  442. #endif
  443. *tmp = 0;
  444. }
  445. if (uwsgi_get_last_char(magic_table['d'], '/'))
  446. magic_table['c'] = uwsgi_get_last_char(magic_table['d'], '/') + 1;
  447. if (tmp) *tmp = '/';
  448. if (uwsgi_get_last_char(filename, '.'))
  449. magic_table['e'] = uwsgi_get_last_char(filename, '.') + 1;
  450. if (uwsgi_get_last_char(magic_table['s'], '.'))
  451. magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
  452. }
  453. int find_worker_id(pid_t pid) {
  454. int i;
  455. for (i = 1; i <= uwsgi.numproc; i++) {
  456. if (uwsgi.workers[i].pid == pid)
  457. return i;
  458. }
  459. return -1;
  460. }
  461. void warn_pipe() {
  462. struct wsgi_request *wsgi_req = current_wsgi_req();
  463. if (uwsgi.threads < 2 && wsgi_req->uri_len > 0) {
  464. 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);
  465. }
  466. else {
  467. uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
  468. }
  469. }
  470. #ifdef UWSGI_THREADING
  471. // in threading mode we need to use the cancel pthread subsystem
  472. void wait_for_threads() {
  473. int i, ret;
  474. pthread_mutex_lock(&uwsgi.six_feet_under_lock);
  475. for (i = 0; i < uwsgi.threads; i++) {
  476. if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
  477. pthread_cancel(uwsgi.core[i]->thread_id);
  478. }
  479. }
  480. // wait for thread termination
  481. for (i = 0; i < uwsgi.threads; i++) {
  482. if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
  483. ret = pthread_join(uwsgi.core[i]->thread_id, NULL);
  484. if (ret) {
  485. uwsgi_log("pthread_join() = %d\n", ret);
  486. }
  487. }
  488. }
  489. pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
  490. }
  491. #endif
  492. void gracefully_kill(int signum) {
  493. uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
  494. uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
  495. #ifdef UWSGI_THREADING
  496. if (uwsgi.threads > 1) {
  497. struct wsgi_request *wsgi_req = current_wsgi_req();
  498. wait_for_threads();
  499. if (!uwsgi.core[wsgi_req->async_id]->in_request) {
  500. exit(UWSGI_RELOAD_CODE);
  501. }
  502. return;
  503. // never here
  504. }
  505. #endif
  506. // still not found a way to gracefully reload in async mode
  507. if (uwsgi.async > 1) {
  508. exit(UWSGI_RELOAD_CODE);
  509. }
  510. if (!uwsgi.core[0]->in_request) {
  511. exit(UWSGI_RELOAD_CODE);
  512. }
  513. }
  514. void end_me(int signum) {
  515. exit(UWSGI_END_CODE);
  516. }
  517. void goodbye_cruel_world() {
  518. #ifdef UWSGI_THREADING
  519. if (uwsgi.threads > 1 && !uwsgi.to_hell) {
  520. wait_for_threads();
  521. }
  522. #endif
  523. uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
  524. uwsgi_log("...The work of process %d is done. Seeya!\n", getpid());
  525. exit(0);
  526. }
  527. #ifdef UWSGI_SPOOLER
  528. static void uwsgi_signal_spoolers(int signum) {
  529. struct uwsgi_spooler *uspool = uwsgi.spoolers;
  530. while(uspool) {
  531. if (uspool->pid > 0) {
  532. kill(uspool->pid, SIGKILL);
  533. uwsgi_log("killing the spooler with pid %d\n", uspool->pid);
  534. }
  535. uspool = uspool->next;
  536. }
  537. }
  538. #endif
  539. void kill_them_all(int signum) {
  540. int i;
  541. if (uwsgi.to_hell == 1) return;
  542. uwsgi.to_hell = 1;
  543. if (uwsgi.reload_mercy > 0) {
  544. uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
  545. }
  546. else {
  547. uwsgi.master_mercy = time(NULL) + 5;
  548. }
  549. uwsgi_log("SIGINT/SIGQUIT received...killing workers...\n");
  550. // unsubscribe if needed
  551. struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
  552. while(subscriptions) {
  553. uwsgi_log("unsubscribing from %s\n", subscriptions->value);
  554. uwsgi_subscribe(subscriptions->value, 1);
  555. subscriptions = subscriptions->next;
  556. }
  557. for (i = 1; i <= uwsgi.numproc; i++) {
  558. if (uwsgi.workers[i].pid > 0)
  559. kill(uwsgi.workers[i].pid, SIGINT);
  560. }
  561. #ifdef UWSGI_SPOOLER
  562. uwsgi_signal_spoolers(SIGKILL);
  563. #endif
  564. if (uwsgi.emperor_pid >= 0) {
  565. kill(uwsgi.emperor_pid, SIGKILL);
  566. waitpid(uwsgi.emperor_pid, &i, 0);
  567. uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
  568. }
  569. struct uwsgi_daemon *ud = uwsgi.daemons;
  570. while(ud) {
  571. if (ud->pid > 0)
  572. kill(-ud->pid, SIGKILL);
  573. ud = ud->next;
  574. }
  575. for (i = 0; i < ushared->gateways_cnt; i++) {
  576. if (ushared->gateways[i].pid > 0)
  577. kill(ushared->gateways[i].pid, SIGKILL);
  578. }
  579. for (i = 0; i < uwsgi.mules_cnt; i++) {
  580. if (uwsgi.mules[i].pid > 0)
  581. kill(uwsgi.mules[i].pid, SIGKILL);
  582. }
  583. }
  584. void grace_them_all(int signum) {
  585. int i;
  586. int waitpid_status;
  587. if (uwsgi.to_heaven == 1 || uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0) return;
  588. if (!uwsgi.lazy)
  589. uwsgi.to_heaven = 1;
  590. else uwsgi.to_outworld = 1;
  591. if (uwsgi.reload_mercy > 0) {
  592. uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
  593. }
  594. else {
  595. // wait max 60 seconds for graceful reload
  596. uwsgi.master_mercy = time(NULL) + 60;
  597. }
  598. #ifdef UWSGI_SPOOLER
  599. uwsgi_signal_spoolers(SIGKILL);
  600. #endif
  601. if (uwsgi.emperor_pid >= 0) {
  602. kill(uwsgi.emperor_pid, SIGKILL);
  603. waitpid(uwsgi.emperor_pid, &i, 0);
  604. uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
  605. }
  606. struct uwsgi_daemon *ud = uwsgi.daemons;
  607. while(ud) {
  608. if (ud->pid > 0)
  609. kill(-ud->pid, SIGKILL);
  610. ud = ud->next;
  611. }
  612. for (i = 0; i < ushared->gateways_cnt; i++) {
  613. if (ushared->gateways[i].pid > 0)
  614. kill(ushared->gateways[i].pid, SIGKILL);
  615. }
  616. for (i = 0; i < uwsgi.mules_cnt; i++) {
  617. if (uwsgi.mules[i].pid > 0)
  618. kill(uwsgi.mules[i].pid, SIGKILL);
  619. }
  620. uwsgi_log("...gracefully killing workers...\n");
  621. if (uwsgi.unsubscribe_on_graceful_reload) {
  622. struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
  623. while(subscriptions) {
  624. uwsgi_log("unsubscribing from %s\n", subscriptions->value);
  625. uwsgi_subscribe(subscriptions->value, 1);
  626. subscriptions = subscriptions->next;
  627. }
  628. }
  629. for (i = 1; i <= uwsgi.numproc; i++) {
  630. if (uwsgi.auto_snapshot) {
  631. if (uwsgi.workers[i].snapshot > 0) {
  632. kill(uwsgi.workers[i].snapshot, SIGKILL);
  633. if (waitpid(uwsgi.workers[i].snapshot, &waitpid_status, 0) < 0) {
  634. uwsgi_error("waitpid()");
  635. }
  636. }
  637. if (uwsgi.workers[i].pid > 0) {
  638. if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
  639. uwsgi.workers[i].snapshot = 0;
  640. kill(uwsgi.workers[i].pid, SIGHUP);
  641. }
  642. else {
  643. uwsgi.workers[i].snapshot = uwsgi.workers[i].pid;
  644. kill(uwsgi.workers[i].pid, SIGURG);
  645. }
  646. }
  647. }
  648. else if (uwsgi.workers[i].pid > 0) {
  649. if (uwsgi.lazy) uwsgi.workers[i].destroy = 1;
  650. kill(uwsgi.workers[i].pid, SIGHUP);
  651. }
  652. }
  653. if (uwsgi.auto_snapshot) {
  654. uwsgi.respawn_workers = 1;
  655. }
  656. }
  657. void uwsgi_nuclear_blast() {
  658. if (!uwsgi.workers) {
  659. reap_them_all(0);
  660. }
  661. else if (uwsgi.master_process) {
  662. if (getpid() == uwsgi.workers[0].pid) {
  663. reap_them_all(0);
  664. }
  665. }
  666. exit(1);
  667. }
  668. void reap_them_all(int signum) {
  669. int i;
  670. // avoid reace condition in lazy mode
  671. if (uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0) return;
  672. if (!uwsgi.lazy)
  673. uwsgi.to_heaven = 1;
  674. else uwsgi.to_outworld = 1;
  675. struct uwsgi_daemon *ud = uwsgi.daemons;
  676. while(ud) {
  677. if (ud->pid > 0)
  678. kill(-ud->pid, SIGKILL);
  679. ud = ud->next;
  680. }
  681. for (i = 0; i < ushared->gateways_cnt; i++) {
  682. if (ushared->gateways[i].pid > 0)
  683. kill(ushared->gateways[i].pid, SIGKILL);
  684. }
  685. for (i = 0; i < uwsgi.mules_cnt; i++) {
  686. if (!uwsgi.mules) break;
  687. if (uwsgi.mules[i].pid > 0)
  688. kill(uwsgi.mules[i].pid, SIGKILL);
  689. }
  690. if (uwsgi.emperor_pid >= 0) {
  691. kill(uwsgi.emperor_pid, SIGKILL);
  692. waitpid(uwsgi.emperor_pid, &i, 0);
  693. uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
  694. }
  695. if (!uwsgi.workers)
  696. return;
  697. uwsgi_log("...brutally killing workers...\n");
  698. // unsubscribe if needed
  699. struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
  700. while(subscriptions) {
  701. uwsgi_log("unsubscribing from %s\n", subscriptions->value);
  702. uwsgi_subscribe(subscriptions->value, 1);
  703. subscriptions = subscriptions->next;
  704. }
  705. for (i = 1; i <= uwsgi.numproc; i++) {
  706. if (uwsgi.workers[i].pid > 0)
  707. kill(uwsgi.workers[i].pid, SIGTERM);
  708. }
  709. }
  710. void harakiri() {
  711. uwsgi_log("\nF*CK !!! i must kill myself (pid: %d app_id: %d)...\n", uwsgi.mypid, uwsgi.wsgi_req->app_id);
  712. if (!uwsgi.master_process) {
  713. uwsgi_log("*** if you want your workers to be automatically respawned consider enabling the uWSGI master process ***\n");
  714. }
  715. exit(0);
  716. }
  717. void snapshot_me(int signum) {
  718. // wakeup !!!
  719. if (uwsgi.snapshot) {
  720. uwsgi.snapshot = 0;
  721. return;
  722. }
  723. uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
  724. #ifdef UWSGI_THREADING
  725. if (uwsgi.threads > 1) {
  726. wait_for_threads();
  727. }
  728. #endif
  729. uwsgi.snapshot = 1;
  730. uwsgi_log("[snapshot] process %d taken\n", (int) getpid());
  731. }
  732. void stats(int signum) {
  733. //fix this for better logging(this cause races)
  734. struct uwsgi_app *ua = NULL;
  735. int i, j;
  736. if (uwsgi.mywid == 0) {
  737. show_config();
  738. uwsgi_log("\tworkers total requests: %llu\n", uwsgi.workers[0].requests);
  739. uwsgi_log("-----------------\n");
  740. for(j=1;j<=uwsgi.numproc;j++) {
  741. for (i = 0; i < uwsgi.workers[j].apps_cnt; i++) {
  742. ua = &uwsgi.workers[j].apps[i];
  743. if (ua) {
  744. uwsgi_log("\tworker %d app %d [%.*s] requests: %d exceptions: %d\n", j, i, ua->mountpoint_len, ua->mountpoint, ua->requests, ua->exceptions);
  745. }
  746. }
  747. uwsgi_log("-----------------\n");
  748. }
  749. }
  750. else {
  751. uwsgi_log("worker %d total requests: %llu\n", uwsgi.mywid, uwsgi.workers[0].requests);
  752. for (i = 0; i < uwsgi.workers[uwsgi.mywid].apps_cnt; i++) {
  753. ua = &uwsgi.workers[uwsgi.mywid].apps[i];
  754. if (ua) {
  755. uwsgi_log("\tapp %d [%.*s] requests: %d exceptions: %d\n", i, ua->mountpoint_len, ua->mountpoint, ua->requests, ua->exceptions);
  756. }
  757. }
  758. uwsgi_log("-----------------\n");
  759. }
  760. uwsgi_log("\n");
  761. }
  762. void what_i_am_doing() {
  763. struct wsgi_request *wsgi_req;
  764. int i;
  765. char ctime_storage[26];
  766. uwsgi_backtrace(uwsgi.backtrace_depth);
  767. if (uwsgi.cores > 1) {
  768. for (i = 0; i < uwsgi.cores; i++) {
  769. wsgi_req = uwsgi.wsgi_requests[i];
  770. if (wsgi_req->uri_len > 0) {
  771. #ifdef __sun__
  772. ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
  773. #else
  774. ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
  775. #endif
  776. if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
  777. 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);
  778. }
  779. else {
  780. 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);
  781. }
  782. }
  783. }
  784. }
  785. else {
  786. wsgi_req = uwsgi.wsgi_requests[0];
  787. if (wsgi_req->uri_len > 0) {
  788. #ifdef __sun__
  789. ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
  790. #else
  791. ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
  792. #endif
  793. if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
  794. 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);
  795. }
  796. else {
  797. 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);
  798. }
  799. }
  800. else if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL) && uwsgi.workers[uwsgi.mywid].sig) {
  801. uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS handling signal %d ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, uwsgi.workers[uwsgi.mywid].signum);
  802. }
  803. }
  804. }
  805. pid_t masterpid;
  806. struct timeval last_respawn;
  807. int unconfigured_hook(struct wsgi_request *wsgi_req) {
  808. uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh.modifier1);
  809. return -1;
  810. }
  811. static void unconfigured_after_hook(struct wsgi_request *wsgi_req) {
  812. return;
  813. }
  814. struct uwsgi_plugin unconfigured_plugin = {
  815. .name = "unconfigured",
  816. .request = unconfigured_hook,
  817. .after_request = unconfigured_after_hook,
  818. };
  819. void uwsgi_exec_atexit(void) {
  820. if (getpid() == masterpid) {
  821. // now run exit scripts needed by the user
  822. struct uwsgi_string_list *usl = uwsgi.exec_as_user_atexit;
  823. while(usl) {
  824. uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
  825. int ret = uwsgi_run_command_and_wait(NULL, usl->value);
  826. if (ret != 0) {
  827. uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
  828. }
  829. usl = usl->next;
  830. }
  831. }
  832. }
  833. static void vacuum(void) {
  834. struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
  835. if (uwsgi.restore_tc) {
  836. if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
  837. uwsgi_error("tcsetattr()");
  838. }
  839. }
  840. if (uwsgi.vacuum) {
  841. if (getpid() == masterpid) {
  842. if (chdir(uwsgi.cwd)) {
  843. uwsgi_error("chdir()");
  844. }
  845. if (uwsgi.pidfile && !uwsgi.uid) {
  846. if (unlink(uwsgi.pidfile)) {
  847. uwsgi_error("unlink()");
  848. }
  849. else {
  850. uwsgi_log("VACUUM: pidfile removed.\n");
  851. }
  852. }
  853. if (uwsgi.pidfile2) {
  854. if (unlink(uwsgi.pidfile2)) {
  855. uwsgi_error("unlink()");
  856. }
  857. else {
  858. uwsgi_log("VACUUM: pidfile2 removed.\n");
  859. }
  860. }
  861. if (uwsgi.chdir) {
  862. if (chdir(uwsgi.chdir)) {
  863. uwsgi_error("chdir()");
  864. }
  865. }
  866. while (uwsgi_sock) {
  867. if (uwsgi_sock->family == AF_UNIX) {
  868. if (unlink(uwsgi_sock->name)) {
  869. uwsgi_error("unlink()");
  870. }
  871. else {
  872. uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
  873. }
  874. }
  875. uwsgi_sock = uwsgi_sock->next;
  876. }
  877. }
  878. }
  879. }
  880. void signal_pidfile(int sig, char *filename) {
  881. int size = 0;
  882. char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
  883. if (size > 0) {
  884. if (kill((pid_t) atoi(buffer), sig)) {
  885. uwsgi_error("kill()");
  886. }
  887. }
  888. else {
  889. uwsgi_log("error: invalid pidfile\n");
  890. }
  891. }
  892. /*static*/ void uwsgi_command_signal(char *opt) {
  893. int tmp_signal;
  894. char *colon = strchr(opt, ',');
  895. if (!colon) {
  896. uwsgi_log("invalid syntax for signal, must be addr,signal\n");
  897. exit(1);
  898. }
  899. colon[0] = 0;
  900. tmp_signal = atoi(colon+1);
  901. if (tmp_signal < 0 || tmp_signal > 255) {
  902. uwsgi_log("invalid signal number\n");
  903. exit(3);
  904. }
  905. uint8_t uwsgi_signal = tmp_signal;
  906. int ret = uwsgi_remote_signal_send(opt, uwsgi_signal);
  907. if (ret < 0) {
  908. uwsgi_log("unable to deliver signal %d to node %s\n", uwsgi_signal, opt);
  909. exit(1);
  910. }
  911. if (ret == 0) {
  912. uwsgi_log("node %s rejected signal %d\n", opt, uwsgi_signal);
  913. exit(2);
  914. }
  915. uwsgi_log("signal %d delivered to node %s\n", uwsgi_signal, opt);
  916. exit(0);
  917. }
  918. void fixup_argv_and_environ(int argc, char **argv, char **environ) {
  919. uwsgi.orig_argv = argv;
  920. uwsgi.argv = argv;
  921. uwsgi.argc = argc;
  922. uwsgi.environ = environ;
  923. #if defined(__linux__) || defined(__sun__)
  924. int i;
  925. int env_count = 0;
  926. uwsgi.argv = uwsgi_malloc( sizeof(char *) * (argc+1));
  927. for(i=0;i<argc;i++) {
  928. if (i==0 || argv[0] + uwsgi.max_procname + 1 == argv[i]) {
  929. uwsgi.max_procname += strlen(argv[i]) + 1;
  930. }
  931. uwsgi.argv[i] = strdup(argv[i]);
  932. }
  933. // required by execve
  934. uwsgi.argv[i] = NULL;
  935. uwsgi.max_procname++;
  936. for (i = 0; environ[i] != NULL; i++) {
  937. // useless
  938. //if ((environ[0] + uwsgi.max_procname + 1) == environ[i]) {
  939. uwsgi.max_procname += strlen(environ[i]) + 1;
  940. //}
  941. env_count++;
  942. }
  943. uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
  944. for(i=0;i<env_count;i++) {
  945. uwsgi.environ[i] = strdup(environ[i]);
  946. #ifdef UWSGI_DEBUG
  947. uwsgi_log("ENVIRON: %s\n", uwsgi.environ[i]);
  948. #endif
  949. environ[i] = uwsgi.environ[i];
  950. }
  951. #ifdef UWSGI_DEBUG
  952. uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
  953. #endif
  954. //environ = uwsgi.environ;
  955. #endif
  956. }
  957. void uwsgi_plugins_atexit(void) {
  958. int j;
  959. if (!uwsgi.workers) return;
  960. // the master cannot run atexit handlers...
  961. if (uwsgi.master_process && uwsgi.workers[0].pid == getpid())
  962. return;
  963. for (j = 0; j< uwsgi.gp_cnt; j++) {
  964. if (uwsgi.gp[j]->atexit) {
  965. uwsgi.gp[j]->atexit();
  966. }
  967. }
  968. for (j = 0; j<256; j++) {
  969. if (uwsgi.p[j]->atexit) {
  970. uwsgi.p[j]->atexit();
  971. }
  972. }
  973. }
  974. void uwsgi_backtrace(int depth) {
  975. #if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
  976. #include <execinfo.h>
  977. void **btrace = uwsgi_malloc(sizeof(void *) * depth);
  978. size_t bt_size, i;
  979. char **bt_strings;
  980. bt_size = backtrace(btrace, depth);
  981. bt_strings = backtrace_symbols(btrace, bt_size);
  982. uwsgi_log("*** backtrace of %d ***\n", (int) getpid());
  983. for(i=0;i<bt_size;i++) {
  984. uwsgi_log("%s\n", bt_strings[i]);
  985. }
  986. free(btrace);
  987. uwsgi_log("*** end of backtrace ***\n");
  988. #endif
  989. }
  990. void uwsgi_segfault(int signum) {
  991. uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
  992. uwsgi_backtrace(uwsgi.backtrace_depth);
  993. // restore default handler to generate core
  994. signal(signum, SIG_DFL);
  995. kill(getpid(), signum);
  996. // never here...
  997. exit(1);
  998. }
  999. void uwsgi_fpe(int signum) {
  1000. uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
  1001. uwsgi_backtrace(uwsgi.backtrace_depth);
  1002. // restore default handler to generate core
  1003. signal(signum, SIG_DFL);
  1004. kill(getpid(), signum);
  1005. // never here...
  1006. exit(1);
  1007. }
  1008. void uwsgi_flush_logs() {
  1009. struct pollfd pfd;
  1010. if (!uwsgi.master_process) return;
  1011. if (!uwsgi.log_master) return;
  1012. if (uwsgi.workers) {
  1013. if (uwsgi.workers[0].pid == getpid()) {
  1014. goto check;
  1015. }
  1016. }
  1017. if (uwsgi.mywid == 0)
  1018. goto check;
  1019. return ;
  1020. check:
  1021. // check for data in logpipe
  1022. pfd.events = POLLIN;
  1023. pfd.fd = uwsgi.shared->worker_log_pipe[0];
  1024. if (pfd.fd == -1) pfd.fd = 2;
  1025. while(poll(&pfd, 1, 0) > 0) {
  1026. if (uwsgi_master_log()) {
  1027. break;
  1028. }
  1029. }
  1030. }
  1031. #ifdef UWSGI_AS_SHARED_LIBRARY
  1032. int uwsgi_init(int argc, char *argv[], char *envp[]) {
  1033. #ifdef __APPLE__
  1034. char*** envPtr = _NSGetEnviron();
  1035. environ = *envPtr;
  1036. #endif
  1037. #else
  1038. int main(int argc, char *argv[], char *envp[]) {
  1039. #endif
  1040. int i;
  1041. int rlen;
  1042. char *env_reloads;
  1043. char env_reload_buf[11];
  1044. char *plugins_requested;
  1045. #ifdef UNBIT
  1046. //struct uidsec_struct us;
  1047. #endif
  1048. #ifdef UWSGI_DEBUG
  1049. struct utsname uuts;
  1050. #endif
  1051. char *emperor_env;
  1052. //char *optname;
  1053. signal(SIGSEGV, uwsgi_segfault);
  1054. signal(SIGFPE, uwsgi_fpe);
  1055. signal(SIGHUP, SIG_IGN);
  1056. signal(SIGTERM, SIG_IGN);
  1057. signal(SIGPIPE, SIG_IGN);
  1058. //initialize masterpid with a default value
  1059. masterpid = getpid();
  1060. memset(&uwsgi, 0, sizeof(struct uwsgi_server));
  1061. uwsgi.cwd = uwsgi_get_cwd();
  1062. init_magic_table(uwsgi.magic_table);
  1063. // manage/flush logs
  1064. atexit(uwsgi_flush_logs);
  1065. // clear sockets, pidfiles...
  1066. atexit(vacuum);
  1067. // call user scripts
  1068. atexit(uwsgi_exec_atexit);
  1069. // call plugin specific exit hooks
  1070. atexit(uwsgi_plugins_atexit);
  1071. #ifdef UWSGI_DEBUG
  1072. #ifdef __sun__
  1073. if (uname(&uuts) < 0) {
  1074. #else
  1075. if (uname(&uuts)) {
  1076. #endif
  1077. uwsgi_error("uname()");
  1078. }
  1079. else {
  1080. uwsgi_log("SYSNAME: %s\nNODENAME: %s\nRELEASE: %s\nVERSION: %s\nMACHINE: %s\n", uuts.sysname, uuts.nodename, uuts.release, uuts.version, uuts.machine);
  1081. }
  1082. #endif
  1083. uwsgi.shared = (struct uwsgi_shared *) mmap(NULL, sizeof(struct uwsgi_shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  1084. if (!uwsgi.shared) {
  1085. uwsgi_error("mmap()");
  1086. exit(1);
  1087. }
  1088. memset(uwsgi.shared, 0, sizeof(struct uwsgi_shared));
  1089. #ifdef UWSGI_SPOOLER
  1090. //set the spooler frequency to 30 seconds by default
  1091. uwsgi.shared->spooler_frequency = 30;
  1092. #endif
  1093. for (i = 0; i < 256; i++) {
  1094. uwsgi.p[i] = &unconfigured_plugin;
  1095. }
  1096. uwsgi.backtrace_depth = 64;
  1097. uwsgi.master_queue = -1;
  1098. uwsgi.signal_socket = -1;
  1099. uwsgi.my_signal_socket = -1;
  1100. uwsgi.cache_server_fd = -1;
  1101. uwsgi.stats_fd = -1;
  1102. uwsgi.original_log_fd = -1;
  1103. uwsgi.emperor_fd_config = -1;
  1104. uwsgi.emperor_throttle = 1000;
  1105. uwsgi.emperor_pid = -1;
  1106. uwsgi.subscribe_freq = 10;
  1107. uwsgi.subscription_tolerance = 17;
  1108. uwsgi.cluster_fd = -1;
  1109. uwsgi.cores = 1;
  1110. uwsgi.threads = 1;
  1111. uwsgi.default_app = -1;
  1112. uwsgi.buffer_size = 4096;
  1113. uwsgi.numproc = 1;
  1114. uwsgi.forkbomb_delay = 2;
  1115. uwsgi.async = 1;
  1116. uwsgi.listen_queue = 100;
  1117. uwsgi.cheaper_overload = 3;
  1118. uwsgi.max_vars = MAX_VARS;
  1119. uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
  1120. uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
  1121. uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
  1122. #ifdef UWSGI_SPOOLER
  1123. uwsgi.shared->spooler_signal_pipe[0] = -1;
  1124. uwsgi.shared->spooler_signal_pipe[1] = -1;
  1125. #endif
  1126. uwsgi.shared->mule_signal_pipe[0] = -1;
  1127. uwsgi.shared->mule_signal_pipe[1] = -1;
  1128. uwsgi.shared->mule_queue_pipe[0] = -1;
  1129. uwsgi.shared->mule_queue_pipe[1] = -1;
  1130. uwsgi.shared->worker_log_pipe[0] = -1;
  1131. uwsgi.shared->worker_log_pipe[1] = -1;
  1132. #ifdef UWSGI_BLACKLIST
  1133. if (!uwsgi_file_to_string_list(UWSGI_BLACKLIST, &uwsgi.blacklist)) {
  1134. uwsgi_log("you cannot run this build of uWSGI without a blacklist file\n");
  1135. exit(1);
  1136. }
  1137. #endif
  1138. #ifdef UWSGI_WHITELIST
  1139. if (!uwsgi_file_to_string_list(UWSGI_WHITELIST, &uwsgi.whitelist)) {
  1140. uwsgi_log("you cannot run this build of uWSGI without a whitelist file\n");
  1141. exit(1);
  1142. }
  1143. #endif
  1144. gettimeofday(&uwsgi.start_tv, NULL);
  1145. setlinebuf(stdout);
  1146. uwsgi.rl.rlim_cur = 0;
  1147. uwsgi.rl.rlim_max = 0;
  1148. // are we under systemd ?
  1149. char *notify_socket = getenv("NOTIFY_SOCKET");
  1150. if (notify_socket) {
  1151. uwsgi_systemd_init(notify_socket);
  1152. }
  1153. uwsgi_notify("initializing uWSGI");
  1154. emperor_env = getenv("UWSGI_EMPEROR_FD");
  1155. if (emperor_env) {
  1156. uwsgi.has_emperor = 1;
  1157. uwsgi.emperor_fd = atoi(emperor_env);
  1158. uwsgi.master_process = 1;
  1159. uwsgi.no_orphans = 1;
  1160. uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
  1161. if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
  1162. uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
  1163. }
  1164. }
  1165. char *screen_env = getenv("TERM");
  1166. if (screen_env) {
  1167. if (!strcmp(screen_env, "screen")) {
  1168. uwsgi.screen_session = getenv("STY");
  1169. }
  1170. }
  1171. env_reloads = getenv("UWSGI_RELOADS");
  1172. if (env_reloads) {
  1173. //convert env value to int
  1174. uwsgi.reloads = atoi(env_reloads);
  1175. uwsgi.reloads++;
  1176. //convert reloads to string
  1177. rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
  1178. if (rlen > 0) {
  1179. env_reload_buf[rlen] = 0;
  1180. if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
  1181. uwsgi_error("setenv()");
  1182. }
  1183. }
  1184. uwsgi.is_a_reload = 1;
  1185. }
  1186. else {
  1187. if (setenv("UWSGI_RELOADS", "0", 1)) {
  1188. uwsgi_error("setenv()");
  1189. }
  1190. }
  1191. uwsgi.page_size = getpagesize();
  1192. uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
  1193. // ok we can now safely play with argv and environ
  1194. fixup_argv_and_environ(argc, argv, environ);
  1195. if (gethostname(uwsgi.hostname, 255)) {
  1196. uwsgi_error("gethostname()");
  1197. }
  1198. uwsgi.hostname_len = strlen(uwsgi.hostname);
  1199. #ifdef UWSGI_ZEROMQ
  1200. uwsgi_register_logger("zeromq", uwsgi_zeromq_logger);
  1201. uwsgi_register_logger("zmq", uwsgi_zeromq_logger);
  1202. #endif
  1203. //initialize embedded plugins
  1204. UWSGI_LOAD_EMBEDDED_PLUGINS
  1205. // now a bit of magic, if the executable basename contains a 'uwsgi_' string,
  1206. // try to automatically load a plugin
  1207. #ifdef UWSGI_DEBUG
  1208. uwsgi_log("executable name: %s\n", uwsgi.binary_path);
  1209. #endif
  1210. char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
  1211. if (!original_proc_name) {
  1212. // here we use argv[0];
  1213. original_proc_name = argv[0];
  1214. setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
  1215. }
  1216. char *p = strrchr(original_proc_name, '/');
  1217. if (p == NULL) p = original_proc_name;
  1218. p = strstr(p, "uwsgi_");
  1219. if (p != NULL) {
  1220. plugins_requested = strtok(uwsgi_str(p+6), "_");
  1221. while(plugins_requested) {
  1222. uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
  1223. uwsgi_load_plugin(-1, plugins_requested, NULL);
  1224. plugins_requested = strtok(NULL, "_");
  1225. }
  1226. }
  1227. plugins_requested = getenv("UWSGI_PLUGINS");
  1228. if (plugins_requested) {
  1229. plugins_requested = uwsgi_concat2(plugins_requested, "");
  1230. char *p = strtok(plugins_requested, ",");
  1231. while (p != NULL) {
  1232. uwsgi_load_plugin(-1, p, NULL);
  1233. p = strtok(NULL, ",");
  1234. }
  1235. }
  1236. build_options();
  1237. uwsgi.magic_table['v'] = uwsgi.cwd;
  1238. uwsgi.magic_table['h'] = uwsgi.hostname;
  1239. #ifdef UWSGI_EMBED_CONFIG
  1240. uwsgi_ini_config("", uwsgi.magic_table);
  1241. #endif
  1242. //parse environ
  1243. parse_sys_envs(environ);
  1244. uwsgi.option_index = -1;
  1245. char *optname;
  1246. while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
  1247. if (i == '?') { uwsgi_log("getopt_long() error\n"); exit(1); }
  1248. if (uwsgi.option_index > -1) {
  1249. optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
  1250. }
  1251. else {
  1252. optname = uwsgi_get_optname_by_index(i);
  1253. }
  1254. if (!optname) {
  1255. uwsgi_log("unable to parse command line options\n");
  1256. exit(1);
  1257. }
  1258. uwsgi.option_index = -1;
  1259. add_exported_option(optname, optarg, 0);
  1260. }
  1261. #ifdef UWSGI_DEBUG
  1262. uwsgi_log("optind:%d argc:%d\n", optind,argc);
  1263. #endif
  1264. if (optind < argc) {
  1265. for(i=optind;i<uwsgi.argc;i++) {
  1266. char *lazy = uwsgi.argv[i];
  1267. if (lazy[0] != '[') {
  1268. uwsgi_opt_load(NULL, lazy, NULL);
  1269. // manage magic mountpoint
  1270. int magic = 0;
  1271. int j;
  1272. for (j = 0; j< uwsgi.gp_cnt; j++) {
  1273. if (uwsgi.gp[j]->magic) {
  1274. if (uwsgi.gp[j]->magic(NULL, lazy)) {
  1275. magic = 1;
  1276. break;
  1277. }
  1278. }
  1279. }
  1280. if (!magic) {
  1281. for (j = 0; j < 256; j++) {
  1282. if (uwsgi.p[j]->magic) {
  1283. if (uwsgi.p[j]->magic(NULL, lazy)) {
  1284. magic = 1;
  1285. break;
  1286. }
  1287. }
  1288. }
  1289. }
  1290. }
  1291. }
  1292. }
  1293. // second pass: ENVs
  1294. uwsgi_apply_config_pass('$', (char *(*)(char *))getenv);
  1295. // third pass: FILEs
  1296. uwsgi_apply_config_pass('@', uwsgi_simple_file_read);
  1297. // last pass: REFERENCEs
  1298. uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
  1299. // ok, the options dictionary is available, lets manage it
  1300. uwsgi_configure();
  1301. if (uwsgi.daemonize) {
  1302. if (uwsgi.has_emperor) {
  1303. logto(uwsgi.daemonize);
  1304. }
  1305. else {
  1306. if (!uwsgi.is_a_reload) {
  1307. daemonize(uwsgi.daemonize);
  1308. }
  1309. else if (uwsgi.log_reopen) {
  1310. logto(uwsgi.daemonize);
  1311. }
  1312. }
  1313. }
  1314. else if (uwsgi.logfile) {
  1315. if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
  1316. logto(uwsgi.logfile);
  1317. }
  1318. }
  1319. if (uwsgi.never_swap) {
  1320. if (mlockall( MCL_CURRENT | MCL_FUTURE )) {
  1321. uwsgi_error("mlockall()");
  1322. }
  1323. }
  1324. if (uwsgi.flock2) {
  1325. uwsgi_opt_flock(NULL, uwsgi.flock2, NULL);
  1326. }
  1327. if (uwsgi.flock_wait2) {
  1328. uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
  1329. }
  1330. // setup master logging
  1331. if (uwsgi.log_master) {
  1332. if (uwsgi.requested_logger) {
  1333. char *colon = strchr(uwsgi.requested_logger, ':');
  1334. if (colon) {
  1335. *colon = 0;
  1336. }
  1337. uwsgi.choosen_logger = uwsgi_get_logger(uwsgi.requested_logger);
  1338. if (!uwsgi.choosen_logger) {
  1339. uwsgi_log("unable to find logger %s\n", uwsgi.requested_logger);
  1340. exit(1);
  1341. }
  1342. if (colon) {
  1343. uwsgi.choosen_logger_arg = colon+1;
  1344. if (*uwsgi.choosen_logger_arg == 0) {
  1345. uwsgi.choosen_logger_arg = NULL;
  1346. }
  1347. *colon = ':';
  1348. }
  1349. }
  1350. uwsgi.original_log_fd = dup(1);
  1351. create_logpipe();
  1352. }
  1353. /* uWSGI IS CONFIGURED !!! */
  1354. if (uwsgi.dump_options) {
  1355. struct option *lopt = uwsgi.long_options;
  1356. while (lopt && lopt->name) {
  1357. fprintf(stdout, "%s\n", lopt->name);
  1358. lopt++;
  1359. }
  1360. exit(0);
  1361. }
  1362. if (uwsgi.show_config) show_config();
  1363. // call cluster initialization procedures
  1364. #ifdef UWSGI_MULTICAST
  1365. cluster_setup();
  1366. #endif
  1367. if (uwsgi.binary_path == uwsgi.argv[0]) {
  1368. uwsgi.binary_path = uwsgi_str(uwsgi.argv[0]);
  1369. }
  1370. 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));
  1371. #ifdef UWSGI_DEBUG
  1372. uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, please disable debug in your build profile and recompile it ***\n***\n");
  1373. #endif
  1374. uwsgi_log_initial("compiled with version: %s on %s\n", __VERSION__, UWSGI_BUILD_DATE);
  1375. #ifdef __BIG_ENDIAN__
  1376. uwsgi_log_initial("*** big endian arch detected ***\n");
  1377. #endif
  1378. #if defined(_SC_NPROCESSORS_ONLN)
  1379. uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_ONLN));
  1380. #elif defined(_SC_NPROCESSORS_CONF)
  1381. uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_CONF));
  1382. #endif
  1383. uwsgi_log_initial("current working directory: %s\n", uwsgi.cwd);
  1384. if (uwsgi.screen_session) {
  1385. uwsgi_log("*** running under screen session %s ***\n", uwsgi.screen_session);
  1386. }
  1387. if (uwsgi.pidfile && !uwsgi.is_a_reload) {
  1388. uwsgi_write_pidfile(uwsgi.pidfile);
  1389. }
  1390. uwsgi_log_initial("detected binary path: %s\n", uwsgi.binary_path);
  1391. struct uwsgi_socket *shared_sock = uwsgi.shared_sockets;
  1392. while (shared_sock) {
  1393. char *tcp_port = strchr(shared_sock->name, ':');
  1394. if (tcp_port == NULL) {
  1395. shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
  1396. shared_sock->family = AF_UNIX;
  1397. 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);
  1398. }
  1399. else {
  1400. shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
  1401. shared_sock->family = AF_INET;
  1402. 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);
  1403. }
  1404. if (shared_sock->fd < 0) {
  1405. uwsgi_log("unable to create shared socket on: %s\n", shared_sock->name);
  1406. exit(1);
  1407. }
  1408. shared_sock->bound = 1;
  1409. shared_sock = shared_sock->next;
  1410. }
  1411. struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
  1412. while(uwsgi_sock) {
  1413. if (uwsgi_sock->shared) {
  1414. shared_sock = uwsgi_get_shared_socket_by_num(uwsgi_sock->from_shared);
  1415. if (!shared_sock) {
  1416. uwsgi_log("unable to find shared socket %d\n", uwsgi_sock->from_shared);
  1417. exit(1);
  1418. }
  1419. uwsgi_sock->fd = shared_sock->fd;
  1420. uwsgi_sock->family = shared_sock->family;
  1421. uwsgi_sock->name = shared_sock->name;
  1422. 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);
  1423. }
  1424. uwsgi_sock = uwsgi_sock->next;
  1425. }
  1426. // start the Emperor if needed
  1427. if (uwsgi.early_emperor && uwsgi.emperor_dir) {
  1428. if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
  1429. uwsgi_notify_ready();
  1430. emperor_loop();
  1431. // never here
  1432. exit(1);
  1433. }
  1434. uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
  1435. if (uwsgi.emperor_pid < 0) {
  1436. uwsgi_error("pid()");
  1437. exit(1);
  1438. }
  1439. else if (uwsgi.emperor_pid == 0) {
  1440. #ifdef __linux__
  1441. if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
  1442. uwsgi_error("prctl()");
  1443. }
  1444. #endif
  1445. emperor_loop();
  1446. // never here
  1447. exit(1);
  1448. }
  1449. }
  1450. // run the pre-jail scripts
  1451. struct uwsgi_string_list *usl = uwsgi.exec_pre_jail;
  1452. while(usl) {
  1453. uwsgi_log("running \"%s\" (pre-jail)...\n", usl->value);
  1454. int ret = uwsgi_run_command_and_wait(NULL, usl->value);
  1455. if (ret != 0) {
  1456. uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
  1457. exit(1);
  1458. }
  1459. usl = usl->next;
  1460. }
  1461. // call jail systems
  1462. for (i = 0; i < uwsgi.gp_cnt; i++) {
  1463. if (uwsgi.gp[i]->jail) {
  1464. uwsgi.gp[i]->jail(uwsgi_start, uwsgi.argv);
  1465. }
  1466. }
  1467. // TODO pluginize basic Linux namespace support
  1468. #ifdef __linux__
  1469. if (uwsgi.ns) {
  1470. linux_namespace_start((void *) uwsgi.argv);
  1471. // never here
  1472. }
  1473. else {
  1474. #endif
  1475. uwsgi_start((void *) uwsgi.argv);
  1476. #ifdef __linux__
  1477. }
  1478. #endif
  1479. // never here
  1480. return 0;
  1481. }
  1482. int uwsgi_start(void *v_argv) {
  1483. #ifdef UWSGI_DEBUG
  1484. int so_bufsize;
  1485. socklen_t so_bufsize_len;
  1486. #endif
  1487. int i, j;
  1488. union uwsgi_sockaddr usa;
  1489. union uwsgi_sockaddr_ptr gsa;
  1490. socklen_t socket_type_len;
  1491. struct uwsgi_socket *uwsgi_sock;
  1492. #ifdef __linux__
  1493. uwsgi_set_cgroup();
  1494. if (uwsgi.ns) {
  1495. linux_namespace_jail();
  1496. }
  1497. #endif
  1498. if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
  1499. uwsgi_as_root();
  1500. }
  1501. if (uwsgi.logto2) {
  1502. if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
  1503. logto(uwsgi.logto2);
  1504. }
  1505. }
  1506. if (uwsgi.chdir) {
  1507. if (chdir(uwsgi.chdir)) {
  1508. uwsgi_error("chdir()");
  1509. exit(1);
  1510. }
  1511. }
  1512. if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
  1513. uwsgi_write_pidfile(uwsgi.pidfile2);
  1514. }
  1515. if (!uwsgi.master_process && !uwsgi.command_mode) {
  1516. uwsgi_log_initial("*** WARNING: you are running uWSGI without its master process manager ***\n");
  1517. }
  1518. #ifndef __OpenBSD__
  1519. if (uwsgi.rl.rlim_max > 0) {
  1520. uwsgi.rl.rlim_cur = uwsgi.rl.rlim_max;
  1521. uwsgi_log("limiting address space of processes...\n");
  1522. if (setrlimit(RLIMIT_AS, &uwsgi.rl)) {
  1523. uwsgi_error("setrlimit()");
  1524. }
  1525. }
  1526. if (uwsgi.prio != 0) {
  1527. #ifdef __HAIKU__
  1528. if (set_thread_priority(find_thread(NULL), uwsgi.prio) == B_BAD_THREAD_ID) {
  1529. uwsgi_error("set_thread_priority()");
  1530. #else
  1531. if (setpriority(PRIO_PROCESS, 0, uwsgi.prio)) {
  1532. uwsgi_error("setpriority()");
  1533. #endif
  1534. }
  1535. else {
  1536. uwsgi_log("scheduler priority set to %d\n", uwsgi.prio);
  1537. }
  1538. }
  1539. if (!getrlimit(RLIMIT_AS, &uwsgi.rl)) {
  1540. //check for overflow
  1541. if (uwsgi.rl.rlim_max != (rlim_t) RLIM_INFINITY) {
  1542. 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);
  1543. }
  1544. }
  1545. #endif
  1546. uwsgi_log_initial("your memory page size is %d bytes\n", uwsgi.page_size);
  1547. if (uwsgi.buffer_size > 65536) {
  1548. uwsgi_log("invalid buffer size.\n");
  1549. exit(1);
  1550. }
  1551. sanitize_args();
  1552. // initialize workers
  1553. if (uwsgi.build_mime_dict) {
  1554. if (!uwsgi.mime_file) uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
  1555. struct uwsgi_string_list *umd = uwsgi.mime_file;
  1556. while(umd) {
  1557. if (!access(umd->value, R_OK)) {
  1558. uwsgi_build_mime_dict(umd->value);
  1559. }
  1560. else {
  1561. uwsgi_log("!!! no %s file found !!!\n", umd->value);
  1562. }
  1563. umd = umd->next;
  1564. }
  1565. }
  1566. if (uwsgi.static_offload_to_thread) {
  1567. pthread_attr_init(&uwsgi.static_offload_thread_attr);
  1568. pthread_attr_setdetachstate(&uwsgi.static_offload_thread_attr, PTHREAD_CREATE_DETACHED);
  1569. // 512K should be enough...
  1570. pthread_attr_setstacksize(&uwsgi.static_offload_thread_attr, 512*1024);
  1571. pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
  1572. }
  1573. // end of generic initialization
  1574. // start the Emperor if needed
  1575. if (!uwsgi.early_emperor && uwsgi.emperor_dir) {
  1576. if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
  1577. uwsgi_notify_ready();
  1578. emperor_loop();
  1579. // never here
  1580. exit(1);
  1581. }
  1582. uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
  1583. if (uwsgi.emperor_pid < 0) {
  1584. uwsgi_error("pid()");
  1585. exit(1);
  1586. }
  1587. else if (uwsgi.emperor_pid == 0) {
  1588. #ifdef __linux__
  1589. if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
  1590. uwsgi_error("prctl()");
  1591. }
  1592. #endif
  1593. emperor_loop();
  1594. // never here
  1595. exit(1);
  1596. }
  1597. }
  1598. uwsgi_register_loop("simple", simple_loop);
  1599. #ifdef UWSGI_ASYNC
  1600. uwsgi_register_loop("async", async_loop);
  1601. // TODO rewrite to use uwsgi.max_fd
  1602. if (uwsgi.async > 1) {
  1603. if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
  1604. if ((unsigned long) uwsgi.rl.rlim_cur < (unsigned long) uwsgi.async) {
  1605. uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.rl.rlim_cur);
  1606. if (uwsgi.rl.rlim_cur < uwsgi.rl.rlim_max && (unsigned long) uwsgi.rl.rlim_max > (unsigned long) uwsgi.async) {
  1607. unsigned long tmp_nofile = (unsigned long) uwsgi.rl.rlim_cur;
  1608. uwsgi.rl.rlim_cur = uwsgi.async;
  1609. if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
  1610. uwsgi_log("max open files limit reset to %lu\n", (unsigned long) uwsgi.rl.rlim_cur);
  1611. uwsgi.async = uwsgi.rl.rlim_cur;
  1612. }
  1613. else {
  1614. uwsgi.async = (int) tmp_nofile;
  1615. }
  1616. }
  1617. else {
  1618. uwsgi.async = uwsgi.rl.rlim_cur;
  1619. }
  1620. uwsgi_log("- async cores set to %d -\n", uwsgi.async);
  1621. }
  1622. }
  1623. }
  1624. #endif
  1625. if (uwsgi.requested_max_fd) {
  1626. uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
  1627. uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
  1628. if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
  1629. uwsgi_error("setrlimit()");
  1630. }
  1631. }
  1632. if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
  1633. uwsgi.max_fd = uwsgi.rl.rlim_cur;
  1634. uwsgi_log_initial("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
  1635. }
  1636. uwsgi.wsgi_requests = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.cores);
  1637. for (i = 0; i < uwsgi.cores; i++) {
  1638. uwsgi.wsgi_requests[i] = uwsgi_malloc(sizeof(struct wsgi_request));
  1639. memset(uwsgi.wsgi_requests[i], 0, sizeof(struct wsgi_request));
  1640. }
  1641. uwsgi.async_buf = uwsgi_malloc(sizeof(char *) * uwsgi.cores);
  1642. if (uwsgi.async > 1) {
  1643. uwsgi_log("async fd table size: %d\n", uwsgi.max_fd);
  1644. uwsgi.async_waiting_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
  1645. if (!uwsgi.async_waiting_fd_table) {
  1646. uwsgi_error("malloc()");
  1647. exit(1);
  1648. }
  1649. memset(uwsgi.async_waiting_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
  1650. uwsgi.async_proto_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
  1651. if (!uwsgi.async_proto_fd_table) {
  1652. uwsgi_error("malloc()");
  1653. exit(1);
  1654. }
  1655. memset(uwsgi.async_proto_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
  1656. }
  1657. if (uwsgi.post_buffering > 0) {
  1658. uwsgi_setup_post_buffering();
  1659. }
  1660. for (i = 0; i < uwsgi.cores; i++) {
  1661. uwsgi.async_buf[i] = uwsgi_malloc(uwsgi.buffer_size);
  1662. }
  1663. #ifdef UWSGI_DEBUG
  1664. uwsgi_log("cores allocated...\n");
  1665. #endif
  1666. //by default set wsgi_req to the first slot
  1667. uwsgi.wsgi_req = uwsgi.wsgi_requests[0];
  1668. if (uwsgi.cores > 1) {
  1669. 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);
  1670. }
  1671. if (uwsgi.vhost) {
  1672. uwsgi_log("VirtualHosting mode enabled.\n");
  1673. }
  1674. // setup locking
  1675. uwsgi_setup_locking();
  1676. // event queue lock (mitigate same event on multiple queues)
  1677. if (uwsgi.threads > 1) {
  1678. pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
  1679. }
  1680. // application generic lock
  1681. uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks+1));
  1682. for(i=0;i<uwsgi.locks+1;i++) {
  1683. uwsgi.user_lock[i] = uwsgi_lock_init( uwsgi_concat2("user ", uwsgi_num2str(i)) );
  1684. }
  1685. if (uwsgi.master_process) {
  1686. // signal table lock
  1687. uwsgi.signal_table_lock = uwsgi_lock_init("signal");
  1688. // fmon table lock
  1689. uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
  1690. // timer table lock
  1691. uwsgi.timer_table_lock = uwsgi_lock_init("timer");
  1692. // probe table lock
  1693. uwsgi.probe_table_lock = uwsgi_lock_init("probe");
  1694. // rb_timer table lock
  1695. uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
  1696. // cron table lock
  1697. uwsgi.cron_table_lock = uwsgi_lock_init("cron");
  1698. }
  1699. uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
  1700. if (uwsgi.sharedareasize > 0) {
  1701. uwsgi.sharedarea = mmap(NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  1702. if (uwsgi.sharedarea) {
  1703. uwsgi_log("shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea);
  1704. }
  1705. else {
  1706. uwsgi_error("mmap()");
  1707. exit(1);
  1708. }
  1709. uwsgi.sa_lock = uwsgi_rwlock_init("sharedarea");
  1710. }
  1711. if (uwsgi.queue_size > 0) {
  1712. uwsgi_init_queue();
  1713. }
  1714. if (uwsgi.cache_max_items > 0) {
  1715. uwsgi_init_cache();
  1716. }
  1717. // create the cache server
  1718. if (uwsgi.master_process && uwsgi.cache_server) {
  1719. uwsgi.cache_server_fd = uwsgi_cache_server(uwsgi.cache_server, uwsgi.cache_server_threads);
  1720. }
  1721. /* plugin initialization */
  1722. for (i = 0; i < uwsgi.gp_cnt; i++) {
  1723. if (uwsgi.gp[i]->init) {
  1724. uwsgi.gp[i]->init();
  1725. }
  1726. }
  1727. if (!uwsgi.no_server) {
  1728. // systemd/upstart/zerg socket activation
  1729. if (!uwsgi.is_a_reload) {
  1730. char *listen_pid = getenv("LISTEN_PID");
  1731. if (listen_pid) {
  1732. if (atoi(listen_pid) == (int) getpid()) {
  1733. char *listen_fds = getenv("LISTEN_FDS");
  1734. if (listen_fds) {
  1735. int systemd_fds = atoi(listen_fds);
  1736. if (systemd_fds > 0) {
  1737. uwsgi_log("- SystemD socket activation detected -\n");
  1738. for(i=3;i<3+systemd_fds;i++) {
  1739. uwsgi_sock = uwsgi_new_socket(NULL);
  1740. uwsgi_add_socket_from_fd(uwsgi_sock, i);
  1741. }
  1742. uwsgi.skip_zero = 1;
  1743. }
  1744. unsetenv("LISTEN_PID");
  1745. unsetenv("LISTEN_FDS");
  1746. }
  1747. }
  1748. }
  1749. char *upstart_events = getenv("UPSTART_EVENTS");
  1750. if (upstart_events && !strcmp(upstart_events, "socket")) {
  1751. char *upstart_fds = getenv("UPSTART_FDS");
  1752. if (upstart_fds) {
  1753. uwsgi_log("- Upstart socket bridge detected (job: %s) -\n", getenv("UPSTART_JOB"));
  1754. uwsgi_sock = uwsgi_new_socket(NULL);
  1755. uwsgi_add_socket_from_fd(uwsgi_sock, atoi(upstart_fds));
  1756. uwsgi.skip_zero = 1;
  1757. }
  1758. unsetenv("UPSTART_EVENTS");
  1759. unsetenv("UPSTART_FDS");
  1760. }
  1761. struct uwsgi_string_list *zn = uwsgi.zerg_node;
  1762. while (zn) {
  1763. if (uwsgi_zerg_attach(zn->value)) {
  1764. if (!uwsgi.zerg_fallback) {
  1765. exit(1);
  1766. }
  1767. }
  1768. zn = zn->next;
  1769. }
  1770. if (uwsgi.zerg) {
  1771. #ifdef UWSGI_DEBUG
  1772. uwsgi_log("attaching zerg sockets...\n");
  1773. #endif
  1774. int zerg_fd;
  1775. i = 0;
  1776. for(;;) {
  1777. zerg_fd = uwsgi.zerg[i];
  1778. if (zerg_fd == -1) {
  1779. break;
  1780. }
  1781. uwsgi_sock = uwsgi_new_socket(NULL);
  1782. uwsgi_add_socket_from_fd(uwsgi_sock, zerg_fd);
  1783. i++;
  1784. }
  1785. uwsgi_log("zerg sockets attached\n");
  1786. }
  1787. }
  1788. //check for inherited sockets
  1789. if (uwsgi.is_a_reload) {
  1790. uwsgi_sock = uwsgi.sockets;
  1791. while (uwsgi_sock) {
  1792. //a bit overengineering
  1793. if (uwsgi_sock->name[0] != 0 && !uwsgi_sock->bound) {
  1794. for (j = 3; j < (int) uwsgi.max_fd; j++) {
  1795. uwsgi_add_socket_from_fd(uwsgi_sock, j);
  1796. }
  1797. }
  1798. uwsgi_sock = uwsgi_sock->next;
  1799. }
  1800. //now close all the unbound fd
  1801. for (j = 3; j < (int)uwsgi.max_fd; j++) {
  1802. int useless = 1;
  1803. #ifdef UWSGI_MULTICAST
  1804. if (j == uwsgi.cluster_fd)
  1805. continue;
  1806. #endif
  1807. if (uwsgi.has_emperor) {
  1808. if (j == uwsgi.emperor_fd)
  1809. continue;
  1810. }
  1811. if (uwsgi.shared->worker_log_pipe[0] > -1) {
  1812. if (j == uwsgi.shared->worker_log_pipe[0])
  1813. continue;
  1814. }
  1815. if (uwsgi.shared->worker_log_pipe[1] > -1) {
  1816. if (j == uwsgi.shared->worker_log_pipe[1])
  1817. continue;
  1818. }
  1819. if (uwsgi.original_log_fd > -1) {
  1820. if (j == uwsgi.original_log_fd)
  1821. continue;
  1822. }
  1823. if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
  1824. if (j == uwsgi.cache_server_fd)
  1825. continue;
  1826. }
  1827. struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
  1828. int found = 0;
  1829. while (ugs) {
  1830. if (ugs->fd == j) {
  1831. found = 1;break;
  1832. }
  1833. ugs = ugs->next;
  1834. }
  1835. if (found) continue;
  1836. int y;
  1837. found = 0;
  1838. for(y=0;y<ushared->gateways_cnt;y++) {
  1839. if (ushared->gateways[y].internal_subscription_pipe[0] == j) {
  1840. found = 1; break;
  1841. }
  1842. if (ushared->gateways[y].internal_subscription_pipe[1] == j) {
  1843. found = 1; break;
  1844. }
  1845. }
  1846. if (found) continue;
  1847. socket_type_len = sizeof(struct sockaddr_un);
  1848. gsa.sa = (struct sockaddr *) &usa;
  1849. if (!getsockname(j, gsa.sa, &socket_type_len)) {
  1850. uwsgi_sock = uwsgi.sockets;
  1851. while (uwsgi_sock) {
  1852. if (uwsgi_sock->fd == j && uwsgi_sock->bound) {
  1853. useless = 0;
  1854. break;
  1855. }
  1856. uwsgi_sock = uwsgi_sock->next;
  1857. }
  1858. }
  1859. if (useless) {
  1860. close(j);
  1861. }
  1862. }
  1863. }
  1864. //now bind all the unbound sockets
  1865. uwsgi_sock = uwsgi.sockets;
  1866. while (uwsgi_sock) {
  1867. if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
  1868. char *tcp_port = strchr(uwsgi_sock->name, ':');
  1869. if (tcp_port == NULL) {
  1870. uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
  1871. uwsgi_sock->family = AF_UNIX;
  1872. if (uwsgi.chown_socket) {
  1873. uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
  1874. }
  1875. 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);
  1876. }
  1877. else {
  1878. #ifdef UWSGI_SCTP
  1879. if (strchr(uwsgi_sock->name, ',') || (uwsgi_sock->proto_name && !strcmp(uwsgi_sock->proto_name, "sctp"))) {
  1880. uwsgi_sock->fd = -1;
  1881. uwsgi_sock->per_core = 1;
  1882. uwsgi_sock->proto_name = "sctp";
  1883. uwsgi_log("uwsgi persistent (SCTP) socket %d mapped to %s\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
  1884. }
  1885. else {
  1886. #endif
  1887. uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
  1888. 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);
  1889. #ifdef UWSGI_SCTP
  1890. }
  1891. #endif
  1892. uwsgi_sock->family = AF_INET;
  1893. }
  1894. if (uwsgi_sock->fd < 0 && !uwsgi_sock->per_core) {
  1895. uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
  1896. exit(1);
  1897. }
  1898. }
  1899. uwsgi_sock->bound = 1;
  1900. uwsgi_sock = uwsgi_sock->next;
  1901. }
  1902. if (uwsgi.chown_socket) {
  1903. if (!uwsgi.master_as_root) {
  1904. uwsgi_as_root();
  1905. }
  1906. }
  1907. int zero_used = 0;
  1908. uwsgi_sock = uwsgi.sockets;
  1909. while (uwsgi_sock) {
  1910. if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
  1911. zero_used = 1;
  1912. break;
  1913. }
  1914. uwsgi_sock = uwsgi_sock->next;
  1915. }
  1916. if (!zero_used) {
  1917. socket_type_len = sizeof(struct sockaddr_un);
  1918. gsa.sa = (struct sockaddr *) &usa;
  1919. if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
  1920. if (gsa.sa->sa_family == AF_UNIX) {
  1921. uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
  1922. uwsgi_sock->family = AF_UNIX;
  1923. uwsgi_sock->fd = 0;
  1924. uwsgi_sock->bound = 1;
  1925. uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
  1926. }
  1927. else {
  1928. uwsgi_sock = uwsgi_new_socket(uwsgi_concat2("::",""));
  1929. uwsgi_sock->family = AF_INET;
  1930. uwsgi_sock->fd = 0;
  1931. uwsgi_sock->bound = 1;
  1932. uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
  1933. }
  1934. }
  1935. else if (!uwsgi.honour_stdin) {
  1936. int fd = open("/dev/null", O_RDONLY);
  1937. if (fd < 0) {
  1938. uwsgi_error_open("/dev/null");
  1939. exit(1);
  1940. }
  1941. if (fd != 0) {
  1942. if (dup2(fd, 0)) {
  1943. uwsgi_error("dup2()");
  1944. exit(1);
  1945. }
  1946. close(fd);
  1947. }
  1948. }
  1949. else if (uwsgi.honour_stdin) {
  1950. if (!tcgetattr(0, &uwsgi.termios)) {
  1951. uwsgi.restore_tc = 1;
  1952. }
  1953. }
  1954. }
  1955. // check for auto_port socket
  1956. uwsgi_sock = uwsgi.sockets;
  1957. while (uwsgi_sock) {
  1958. if (uwsgi_sock->auto_port) {
  1959. 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);
  1960. }
  1961. uwsgi_sock = uwsgi_sock->next;
  1962. }
  1963. // put listening socket in non-blocking state and set the protocol
  1964. uwsgi_sock = uwsgi.sockets;
  1965. while (uwsgi_sock) {
  1966. if (!uwsgi_sock->bound || uwsgi_sock->fd == -1) goto nextsock;
  1967. if (!uwsgi_sock->per_core) {
  1968. uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
  1969. if (uwsgi_sock->arg < 0) {
  1970. uwsgi_error("fcntl()");
  1971. exit(1);
  1972. }
  1973. uwsgi_sock->arg |= O_NONBLOCK;
  1974. if (fcntl(uwsgi_sock->fd, F_SETFL, uwsgi_sock->arg) < 0) {
  1975. uwsgi_error("fcntl()");
  1976. exit(1);
  1977. }
  1978. }
  1979. char *requested_protocol = uwsgi_sock->proto_name;
  1980. if (!requested_protocol) {
  1981. requested_protocol = uwsgi.protocol;
  1982. }
  1983. if (requested_protocol && !strcmp("http", requested_protocol)) {
  1984. uwsgi_sock->proto = uwsgi_proto_http_parser;
  1985. uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
  1986. uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
  1987. uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
  1988. uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
  1989. uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
  1990. uwsgi_sock->proto_sendfile = NULL;
  1991. uwsgi_sock->proto_close = uwsgi_proto_base_close;
  1992. }
  1993. else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
  1994. if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) {
  1995. uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
  1996. }
  1997. uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
  1998. uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
  1999. uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
  2000. uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
  2001. uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
  2002. uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
  2003. uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
  2004. uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
  2005. }
  2006. #ifdef UWSGI_SCTP
  2007. else if (requested_protocol && !strcmp("sctp", requested_protocol)) {
  2008. if (!uwsgi.post_buffering) {
  2009. uwsgi.post_buffering = 4096;
  2010. uwsgi_setup_post_buffering();
  2011. }
  2012. uwsgi_sock->proto = uwsgi_proto_sctp_parser;
  2013. uwsgi_sock->proto_accept = uwsgi_proto_sctp_accept;
  2014. uwsgi_sock->proto_write = uwsgi_proto_sctp_write;
  2015. uwsgi_sock->proto_writev = uwsgi_proto_sctp_writev;
  2016. uwsgi_sock->proto_write_header = uwsgi_proto_sctp_write_header;
  2017. uwsgi_sock->proto_writev_header = uwsgi_proto_sctp_writev_header;
  2018. uwsgi_sock->proto_sendfile = uwsgi_proto_sctp_sendfile;
  2019. uwsgi_sock->proto_close = uwsgi_proto_sctp_close;
  2020. uwsgi_sock->proto_read_body = uwsgi_proto_sctp_read_body;
  2021. }
  2022. #endif
  2023. else {
  2024. uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
  2025. uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
  2026. uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
  2027. uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
  2028. uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
  2029. uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
  2030. uwsgi_sock->proto_sendfile = NULL;
  2031. uwsgi_sock->proto_close = uwsgi_proto_base_close;
  2032. }
  2033. nextsock:
  2034. uwsgi_sock = uwsgi_sock->next;
  2035. }
  2036. #ifdef UWSGI_ZEROMQ
  2037. if (uwsgi.zeromq) {
  2038. uwsgi.zmq_responder = strchr(uwsgi.zeromq, ',');
  2039. if (!uwsgi.zmq_responder) {
  2040. uwsgi_log("invalid zeromq address\n");
  2041. exit(1);
  2042. }
  2043. uwsgi.zmq_receiver = uwsgi_concat2n(uwsgi.zeromq, uwsgi.zmq_responder - uwsgi.zeromq, "", 0);
  2044. uwsgi.zmq_responder++;
  2045. uwsgi_log("zmq receiver: %s\n", uwsgi.zmq_receiver);
  2046. uwsgi_log("zmq responder: %s\n", uwsgi.zmq_responder);
  2047. uwsgi.zmq_socket = uwsgi_new_socket(uwsgi.zmq_receiver);
  2048. }
  2049. #endif
  2050. }
  2051. // initialize request plugin only if workers or master are available
  2052. if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
  2053. for (i = 0; i < 256; i++) {
  2054. if (uwsgi.p[i]->init) {
  2055. uwsgi.p[i]->init();
  2056. }
  2057. }
  2058. }
  2059. /* gp/plugin initialization */
  2060. for (i = 0; i < uwsgi.gp_cnt; i++) {
  2061. if (uwsgi.gp[i]->post_init) {
  2062. uwsgi.gp[i]->post_init();
  2063. }
  2064. }
  2065. // again check for workers/sockets...
  2066. if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
  2067. for (i = 0; i < 256; i++) {
  2068. if (uwsgi.p[i]->post_init) {
  2069. uwsgi.p[i]->post_init();
  2070. }
  2071. }
  2072. }
  2073. uwsgi.current_wsgi_req = simple_current_wsgi_req;
  2074. #ifdef UWSGI_THREADING
  2075. if (uwsgi.has_threads) {
  2076. if (uwsgi.threads > 1)
  2077. uwsgi.current_wsgi_req = threaded_current_wsgi_req;
  2078. (void) pthread_attr_init(&uwsgi.threads_attr);
  2079. if (uwsgi.threads_stacksize) {
  2080. if (pthread_attr_setstacksize(&uwsgi.threads_attr, uwsgi.threads_stacksize*1024) == 0) {
  2081. uwsgi_log("threads stack size set to %dk\n", uwsgi.threads_stacksize);
  2082. }
  2083. else {
  2084. uwsgi_log("!!! unable to set requested threads stacksize !!!\n");
  2085. }
  2086. }
  2087. pthread_mutex_init(&uwsgi.lock_static, NULL);
  2088. // again check for workers/sockets...
  2089. if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
  2090. for (i = 0; i < 256; i++) {
  2091. if (uwsgi.p[i]->enable_threads)
  2092. uwsgi.p[i]->enable_threads();
  2093. }
  2094. }
  2095. }
  2096. #endif
  2097. #ifdef UWSGI_UDP
  2098. if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor_dir && !uwsgi.command_mode) {
  2099. #else
  2100. if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.emperor_dir && !uwsgi.command_mode) {
  2101. #endif
  2102. uwsgi_log("The -s/--socket option is missing and stdin is not a socket.\n");
  2103. exit(1);
  2104. }
  2105. else if (!uwsgi.sockets && ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.master_process) {
  2106. // here we will have a zombie... sorry
  2107. uwsgi_log("...you should enable the master process... really...\n");
  2108. exit(0);
  2109. }
  2110. if (!uwsgi.sockets)
  2111. uwsgi.numproc = 0;
  2112. if (uwsgi.command_mode) {
  2113. uwsgi.sockets = NULL;
  2114. uwsgi.numproc = 1;
  2115. uwsgi.to_hell = 1;
  2116. }
  2117. #ifdef UWSGI_DEBUG
  2118. uwsgi_sock = uwsgi.sockets;
  2119. while (uwsgi_sock) {
  2120. so_bufsize_len = sizeof(int);
  2121. if (getsockopt(uwsgi_sock->fd, SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
  2122. uwsgi_error("getsockopt()");
  2123. }
  2124. else {
  2125. uwsgi_debug("uwsgi socket %d SO_RCVBUF size: %d\n", i, so_bufsize);
  2126. }
  2127. so_bufsize_len = sizeof(int);
  2128. if (getsockopt(uwsgi_sock->fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
  2129. uwsgi_error("getsockopt()");
  2130. }
  2131. else {
  2132. uwsgi_debug("uwsgi socket %d SO_SNDBUF size: %d\n", i, so_bufsize);
  2133. }
  2134. uwsgi_sock = uwsgi_sock->next;
  2135. }
  2136. #endif
  2137. #ifndef UNBIT
  2138. if (uwsgi.sockets)
  2139. uwsgi_log("your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
  2140. #endif
  2141. if (uwsgi.crons) {
  2142. struct uwsgi_cron *ucron = uwsgi.crons;
  2143. while(ucron) {
  2144. uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
  2145. ucron = ucron->next;
  2146. }
  2147. }
  2148. // apps are now per-worker
  2149. //memset(uwsgi.apps, 0, sizeof(uwsgi.apps));
  2150. 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);
  2151. if (!uwsgi.workers) {
  2152. uwsgi_error("mmap()");
  2153. exit(1);
  2154. }
  2155. memset(uwsgi.workers, 0, sizeof(struct uwsgi_worker) * uwsgi.numproc + 1);
  2156. for(i=1;i<=uwsgi.numproc;i++) {
  2157. uwsgi.workers[i].signal_pipe[0] = - 1;
  2158. uwsgi.workers[i].signal_pipe[1] = - 1;
  2159. snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
  2160. }
  2161. if (uwsgi.master_process) {
  2162. for(i=1;i<=uwsgi.numproc;i++) {
  2163. create_signal_pipe(uwsgi.workers[i].signal_pipe);
  2164. }
  2165. }
  2166. uwsgi.mypid = getpid();
  2167. masterpid = uwsgi.mypid;
  2168. uwsgi.workers[0].pid = masterpid;
  2169. if (uwsgi.mules_cnt > 0) {
  2170. uwsgi.mules = (struct uwsgi_mule *) mmap(NULL, sizeof(struct uwsgi_mule) * uwsgi.mules_cnt, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  2171. if (!uwsgi.mules) {
  2172. uwsgi_error("mmap()");
  2173. exit(1);
  2174. }
  2175. memset(uwsgi.mules, 0, sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
  2176. create_signal_pipe(uwsgi.shared->mule_signal_pipe);
  2177. create_signal_pipe(uwsgi.shared->mule_queue_pipe);
  2178. for(i=0;i<uwsgi.mules_cnt;i++) {
  2179. // create the socket pipe
  2180. create_signal_pipe(uwsgi.mules[i].signal_pipe);
  2181. create_signal_pipe(uwsgi.mules[i].queue_pipe);
  2182. uwsgi.mules[i].id = i+1;
  2183. snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", i+1);
  2184. }
  2185. }
  2186. if (uwsgi.farms_cnt > 0) {
  2187. uwsgi.farms = (struct uwsgi_farm *) mmap(NULL, sizeof(struct uwsgi_farm) * uwsgi.farms_cnt, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  2188. if (!uwsgi.farms) {
  2189. uwsgi_error("mmap()");
  2190. exit(1);
  2191. }
  2192. memset(uwsgi.farms, 0, sizeof(struct uwsgi_farm) * uwsgi.farms_cnt);
  2193. struct uwsgi_string_list *farm_name = uwsgi.farms_list;
  2194. for(i=0;i<uwsgi.farms_cnt;i++) {
  2195. char *farm_value = uwsgi_str(farm_name->value);
  2196. char *mules_list = strchr(farm_value, ':');
  2197. if (!mules_list) {
  2198. uwsgi_log("invalid farm value (%s) must be in the form name:mule[,muleN].\n", farm_value);
  2199. exit(1);
  2200. }
  2201. mules_list[0] = 0;
  2202. mules_list++;
  2203. strncpy(uwsgi.farms[i].name, farm_value, 0xff);
  2204. // create the socket pipe
  2205. create_signal_pipe(uwsgi.farms[i].signal_pipe);
  2206. create_signal_pipe(uwsgi.farms[i].queue_pipe);
  2207. char *p = strtok(mules_list, ",");
  2208. while(p != NULL) {
  2209. struct uwsgi_mule *um = get_mule_by_id( atoi( p ) );
  2210. if (!um) {
  2211. uwsgi_log("invalid mule id: %s\n", p);
  2212. exit(1);
  2213. }
  2214. uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
  2215. p = strtok(NULL, ",");
  2216. }
  2217. uwsgi_log("created farm %d name: %s mules:%s\n", i+1, uwsgi.farms[i].name, strchr(farm_name->value, ':')+1);
  2218. farm_name = farm_name->next;
  2219. }
  2220. }
  2221. if (uwsgi.command_mode) {
  2222. uwsgi_log("*** Operational MODE: command ***\n");
  2223. }
  2224. else if (!uwsgi.numproc) {
  2225. uwsgi_log("*** Operational MODE: no-workers ***\n");
  2226. }
  2227. else if (uwsgi.threads > 1) {
  2228. if (uwsgi.numproc > 1) {
  2229. uwsgi_log("*** Operational MODE: preforking+threaded ***\n");
  2230. }
  2231. else {
  2232. uwsgi_log("*** Operational MODE: threaded ***\n");
  2233. }
  2234. }
  2235. #ifdef UWSGI_ASYNC
  2236. else if (uwsgi.async > 1) {
  2237. if (uwsgi.numproc > 1) {
  2238. uwsgi_log("*** Operational MODE: preforking+async ***\n");
  2239. }
  2240. else {
  2241. uwsgi_log("*** Operational MODE: async ***\n");
  2242. }
  2243. }
  2244. #endif
  2245. else if (uwsgi.numproc > 1) {
  2246. uwsgi_log("*** Operational MODE: preforking ***\n");
  2247. }
  2248. else {
  2249. uwsgi_log("*** Operational MODE: single process ***\n");
  2250. }
  2251. // even the master has cores..
  2252. uwsgi.core = uwsgi_malloc(sizeof(struct uwsgi_core *) * uwsgi.cores);
  2253. for (j = 0; j < uwsgi.cores; j++) {
  2254. uwsgi.core[j] = uwsgi_malloc(sizeof(struct uwsgi_core));
  2255. memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core));
  2256. }
  2257. // preinit apps (create the language environment)
  2258. for (i = 0; i < 256; i++) {
  2259. if (uwsgi.p[i]->preinit_apps) {
  2260. uwsgi.p[i]->preinit_apps();
  2261. }
  2262. }
  2263. for (i = 0; i < uwsgi.gp_cnt; i++) {
  2264. if (uwsgi.gp[i]->preinit_apps) {
  2265. uwsgi.gp[i]->preinit_apps();
  2266. }
  2267. }
  2268. //init apps hook (if not lazy)
  2269. if (!uwsgi.lazy) {
  2270. uwsgi_init_all_apps();
  2271. }
  2272. if (uwsgi.daemonize2) {
  2273. if (uwsgi.has_emperor) {
  2274. logto(uwsgi.daemonize2);
  2275. }
  2276. else {
  2277. if (!uwsgi.is_a_reload) {
  2278. uwsgi_log("*** daemonizing uWSGI ***\n");
  2279. daemonize(uwsgi.daemonize2);
  2280. }
  2281. else if (uwsgi.log_reopen) {
  2282. logto(uwsgi.daemonize2);
  2283. }
  2284. }
  2285. uwsgi.mypid = getpid();
  2286. masterpid = uwsgi.mypid;
  2287. uwsgi.workers[0].pid = masterpid;
  2288. if (uwsgi.pidfile && !uwsgi.is_a_reload) {
  2289. uwsgi_write_pidfile(uwsgi.pidfile);
  2290. }
  2291. if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
  2292. uwsgi_write_pidfile(uwsgi.pidfile2);
  2293. }
  2294. }
  2295. if (uwsgi.no_server) {
  2296. uwsgi_log("no-server mode requested. Goodbye.\n");
  2297. exit(0);
  2298. }
  2299. if (!uwsgi.master_process && uwsgi.numproc == 0) {
  2300. exit(0);
  2301. }
  2302. if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
  2303. uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
  2304. }
  2305. #ifdef __linux__
  2306. #ifdef MADV_MERGEABLE
  2307. if (uwsgi.linux_ksm > 0) {
  2308. uwsgi_log("[uwsgi-KSM] enabled with frequency: %d\n", uwsgi.linux_ksm);
  2309. }
  2310. #endif
  2311. #endif
  2312. if (uwsgi.master_process) {
  2313. // initialize a mutex to avoid glibc problem with pthread+fork()
  2314. if (uwsgi.threaded_logger) {
  2315. pthread_mutex_init(&uwsgi.threaded_logger_lock, NULL);
  2316. }
  2317. if (uwsgi.is_a_reload) {
  2318. uwsgi_log("gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
  2319. }
  2320. else {
  2321. uwsgi_log("spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
  2322. }
  2323. }
  2324. // security in multiuser environment: allow only a subset of modifiers
  2325. if (uwsgi.allowed_modifiers) {
  2326. for (i = 0; i < 256; i++) {
  2327. if (!uwsgi_list_has_num(uwsgi.allowed_modifiers, i)) {
  2328. uwsgi.p[i]->request = unconfigured_hook;
  2329. uwsgi.p[i]->after_request = unconfigured_after_hook;
  2330. }
  2331. }
  2332. }
  2333. // master fixup
  2334. for (i = 0; i < 256; i++) {
  2335. if (uwsgi.p[i]->master_fixup) {
  2336. uwsgi.p[i]->master_fixup(0);
  2337. }
  2338. }
  2339. #ifdef UWSGI_SPOOLER
  2340. if (uwsgi.spoolers != NULL && uwsgi.sockets) {
  2341. create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
  2342. struct uwsgi_spooler *uspool = uwsgi.spoolers;
  2343. while(uspool) {
  2344. create_signal_pipe(uspool->signal_pipe);
  2345. uspool->lock = uwsgi_lock_init( uwsgi_concat2("spooler on ", uspool->dir) );
  2346. uspool->pid = spooler_start(uspool);
  2347. uspool = uspool->next;
  2348. }
  2349. }
  2350. #endif
  2351. if (!uwsgi.master_process) {
  2352. if (uwsgi.numproc == 1) {
  2353. uwsgi_log("spawned uWSGI worker 1 (and the only) (pid: %d, cores: %d)\n", masterpid, uwsgi.cores);
  2354. }
  2355. else {
  2356. uwsgi_log("spawned uWSGI worker 1 (pid: %d, cores: %d)\n", masterpid, uwsgi.cores);
  2357. }
  2358. uwsgi.workers[1].pid = masterpid;
  2359. uwsgi.workers[1].id = 1;
  2360. uwsgi.workers[1].last_spawn = time(NULL);
  2361. uwsgi.workers[1].manage_next_request = 1;
  2362. uwsgi.mywid = 1;
  2363. gettimeofday(&last_respawn, NULL);
  2364. uwsgi.respawn_delta = last_respawn.tv_sec;
  2365. }
  2366. else {
  2367. // setup internal signalling system
  2368. create_signal_pipe(uwsgi.shared->worker_signal_pipe);
  2369. uwsgi.signal_socket = uwsgi.shared->worker_signal_pipe[1];
  2370. }
  2371. // uWSGI is ready
  2372. uwsgi_notify_ready();
  2373. uwsgi.current_time = time(NULL);
  2374. if (!uwsgi.cheap) {
  2375. if (uwsgi.cheaper && uwsgi.cheaper_count) {
  2376. for(i=1;i<=uwsgi.numproc;i++) {
  2377. if (i <= uwsgi.cheaper_count) {
  2378. if (uwsgi_respawn_worker(i)) break;
  2379. gettimeofday(&last_respawn, NULL);
  2380. uwsgi.respawn_delta = last_respawn.tv_sec;
  2381. }
  2382. else {
  2383. uwsgi.workers[i].cheaped = 1;
  2384. }
  2385. }
  2386. }
  2387. else {
  2388. for (i = 2 - uwsgi.master_process; i < uwsgi.numproc + 1; i++) {
  2389. if (uwsgi_respawn_worker(i))
  2390. break;
  2391. gettimeofday(&last_respawn, NULL);
  2392. uwsgi.respawn_delta = last_respawn.tv_sec;
  2393. }
  2394. }
  2395. }
  2396. if (getpid() == masterpid && uwsgi.master_process == 1) {
  2397. #ifdef UWSGI_AS_SHARED_LIBRARY
  2398. int ml_ret = master_loop(uwsgi.argv, uwsgi.environ);
  2399. if (ml_ret == -1) {
  2400. return 0;
  2401. }
  2402. #else
  2403. (void) master_loop(uwsgi.argv, uwsgi.environ);
  2404. #endif
  2405. //from now on the process is a real worker
  2406. }
  2407. uwsgi_sock = uwsgi.sockets;
  2408. while (uwsgi_sock) {
  2409. struct uwsgi_string_list *usl = uwsgi.map_socket;
  2410. int enabled = 1;
  2411. while (usl) {
  2412. char *colon = strchr(usl->value, ':');
  2413. if ((int)uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
  2414. enabled = 0;
  2415. char *p = strtok(colon + 1, ",");
  2416. while (p != NULL) {
  2417. int w = atoi(p);
  2418. if (w < 1 || w > uwsgi.numproc) {
  2419. uwsgi_log("invalid worker num: %d\n", w);
  2420. exit(1);
  2421. }
  2422. if (w == uwsgi.mywid) {
  2423. enabled = 1;
  2424. uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
  2425. break;
  2426. }
  2427. p = strtok(NULL, ",");
  2428. }
  2429. }
  2430. usl = usl->next;
  2431. }
  2432. if (!enabled) {
  2433. close(uwsgi_sock->fd);
  2434. int fd = open("/dev/null", O_RDONLY);
  2435. if (fd < 0) {
  2436. uwsgi_error_open("/dev/null");
  2437. exit(1);
  2438. }
  2439. if (fd != uwsgi_sock->fd) {
  2440. if (dup2(fd, uwsgi_sock->fd)) {
  2441. uwsgi_error("dup2()");
  2442. exit(1);
  2443. }
  2444. close(fd);
  2445. }
  2446. uwsgi_sock->disabled = 1;
  2447. }
  2448. uwsgi_sock = uwsgi_sock->next;
  2449. }
  2450. uwsgi_sock = uwsgi.sockets;
  2451. while (uwsgi_sock) {
  2452. if (uwsgi_sock->disabled) {
  2453. uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
  2454. }
  2455. else {
  2456. uwsgi_sock = uwsgi_sock->next;
  2457. }
  2458. }
  2459. if (uwsgi.cpu_affinity) {
  2460. #ifdef __linux__
  2461. cpu_set_t cpuset;
  2462. CPU_ZERO(&cpuset);
  2463. int ncpu = sysconf(_SC_NPROCESSORS_ONLN);
  2464. int base_cpu = (uwsgi.mywid - 1) * uwsgi.cpu_affinity;
  2465. if (base_cpu >= ncpu) {
  2466. base_cpu = base_cpu % ncpu;
  2467. }
  2468. uwsgi_log("set cpu affinity for worker %d to", uwsgi.mywid);
  2469. for (i = 0; i < uwsgi.cpu_affinity; i++) {
  2470. if (base_cpu >= ncpu)
  2471. base_cpu = 0;
  2472. CPU_SET(base_cpu, &cpuset);
  2473. uwsgi_log(" %d", base_cpu);
  2474. base_cpu++;
  2475. }
  2476. if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) {
  2477. uwsgi_error("sched_setaffinity()");
  2478. }
  2479. uwsgi_log("\n");
  2480. #endif
  2481. }
  2482. if (uwsgi.worker_exec) {
  2483. char *w_argv[2];
  2484. w_argv[0] = uwsgi.worker_exec;
  2485. w_argv[1] = NULL;
  2486. uwsgi.sockets->arg &= (~O_NONBLOCK);
  2487. if (fcntl(uwsgi.sockets->fd, F_SETFL, uwsgi.sockets->arg) < 0) {
  2488. uwsgi_error("fcntl()");
  2489. exit(1);
  2490. }
  2491. if (uwsgi.sockets->fd != 0) {
  2492. if (dup2(uwsgi.sockets->fd, 0)) {
  2493. uwsgi_error("dup2()");
  2494. }
  2495. }
  2496. execvp(w_argv[0], w_argv);
  2497. // never here
  2498. uwsgi_error("execvp()");
  2499. exit(1);
  2500. }
  2501. if (uwsgi.master_as_root) {
  2502. uwsgi_as_root();
  2503. }
  2504. if (uwsgi.lazy) {
  2505. uwsgi_init_all_apps();
  2506. }
  2507. for (i = 0; i < 256; i++) {
  2508. if (uwsgi.p[i]->post_fork) {
  2509. uwsgi.p[i]->post_fork();
  2510. }
  2511. }
  2512. #ifdef UWSGI_ZEROMQ
  2513. if (uwsgi.zmq_receiver && uwsgi.zmq_responder) {
  2514. uwsgi.zmq_context = zmq_init(1);
  2515. if (uwsgi.zmq_context == NULL) {
  2516. uwsgi_error("zmq_init()");
  2517. exit(1);
  2518. }
  2519. if (uwsgi.threads > 1) {
  2520. pthread_mutex_init(&uwsgi.zmq_lock, NULL);
  2521. }
  2522. uwsgi.zmq_pub = zmq_socket(uwsgi.zmq_context, ZMQ_PUB);
  2523. if (uwsgi.zmq_pub == NULL) {
  2524. uwsgi_error("zmq_socket()");
  2525. exit(1);
  2526. }
  2527. uuid_t uuid_zmq;
  2528. char uuid_zmq_str[37];
  2529. uuid_generate(uuid_zmq);
  2530. uuid_unparse(uuid_zmq, uuid_zmq_str);
  2531. uwsgi_log("%.*s\n", 36, uuid_zmq_str);
  2532. if (zmq_setsockopt(uwsgi.zmq_pub, ZMQ_IDENTITY, uuid_zmq_str, 36) < 0) {
  2533. uwsgi_error("zmq_setsockopt()");
  2534. exit(1);
  2535. }
  2536. if (zmq_connect(uwsgi.zmq_pub, uwsgi.zmq_responder) < 0) {
  2537. uwsgi_error("zmq_connect()");
  2538. exit(1);
  2539. }
  2540. uwsgi.zmq_socket->proto = uwsgi_proto_zeromq_parser;
  2541. uwsgi.zmq_socket->proto_accept = uwsgi_proto_zeromq_accept;
  2542. uwsgi.zmq_socket->proto_close = uwsgi_proto_zeromq_close;
  2543. uwsgi.zmq_socket->proto_write = uwsgi_proto_zeromq_write;
  2544. uwsgi.zmq_socket->proto_writev = uwsgi_proto_zeromq_writev;
  2545. uwsgi.zmq_socket->proto_write_header = uwsgi_proto_zeromq_write_header;
  2546. uwsgi.zmq_socket->proto_writev_header = uwsgi_proto_zeromq_writev_header;
  2547. uwsgi.zmq_socket->proto_sendfile = uwsgi_proto_zeromq_sendfile;
  2548. uwsgi.zmq_socket->edge_trigger = 1;
  2549. if (pthread_key_create(&uwsgi.zmq_pull, NULL)) {
  2550. uwsgi_error("pthread_key_create()");
  2551. exit(1);
  2552. }
  2553. void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
  2554. if (tmp_zmq_pull == NULL) {
  2555. uwsgi_error("zmq_socket()");
  2556. exit(1);
  2557. }
  2558. if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
  2559. uwsgi_error("zmq_connect()");
  2560. exit(1);
  2561. }
  2562. pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
  2563. #ifdef ZMQ_FD
  2564. size_t zmq_socket_len = sizeof(int);
  2565. if (zmq_getsockopt(pthread_getspecific(uwsgi.zmq_pull), ZMQ_FD, &uwsgi.zmq_socket->fd, &zmq_socket_len) < 0) {
  2566. uwsgi_error("zmq_getsockopt()");
  2567. exit(1);
  2568. }
  2569. #else
  2570. uwsgi.zmq_socket->fd = -1;
  2571. #endif
  2572. uwsgi.zmq_socket->bound = 1;
  2573. uwsgi.zeromq_recv_flag = ZMQ_NOBLOCK;
  2574. }
  2575. #endif
  2576. //postpone the queue initialization as kevent
  2577. //do not pass kfd after fork()
  2578. #ifdef UWSGI_ASYNC
  2579. if (uwsgi.async > 1) {
  2580. uwsgi.async_queue = event_queue_init();
  2581. if (uwsgi.async_queue < 0) {
  2582. exit(1);
  2583. }
  2584. uwsgi_add_sockets_to_queue(uwsgi.async_queue);
  2585. uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
  2586. uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
  2587. for (i = 0; i < uwsgi.async; i++) {
  2588. uwsgi.async_queue_unused[i] = uwsgi.wsgi_requests[i];
  2589. }
  2590. uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
  2591. }
  2592. #endif
  2593. uwsgi.async_hvec = uwsgi_malloc(sizeof(struct iovec *) * uwsgi.cores);
  2594. for (i = 0; i < uwsgi.cores; i++) {
  2595. uwsgi.async_hvec[i] = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size);
  2596. }
  2597. if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) {
  2598. signal(SIGALRM, (void *) &harakiri);
  2599. }
  2600. uwsgi_unix_signal(SIGHUP, gracefully_kill);
  2601. uwsgi_unix_signal(SIGINT, end_me);
  2602. uwsgi_unix_signal(SIGTERM, end_me);
  2603. if (uwsgi.auto_snapshot) {
  2604. uwsgi_unix_signal(SIGURG, snapshot_me);
  2605. }
  2606. uwsgi_unix_signal(SIGUSR1, stats);
  2607. signal(SIGUSR2, (void *) &what_i_am_doing);
  2608. if (!uwsgi.ignore_sigpipe) {
  2609. signal(SIGPIPE, (void *) &warn_pipe);
  2610. }
  2611. //initialization done
  2612. // run fixup handler
  2613. for (i = 0; i < 256; i++) {
  2614. if (uwsgi.p[i]->fixup) {
  2615. uwsgi.p[i]->fixup();
  2616. }
  2617. }
  2618. if (uwsgi.chdir2) {
  2619. if (chdir(uwsgi.chdir2)) {
  2620. uwsgi_error("chdir()");
  2621. exit(1);
  2622. }
  2623. }
  2624. //re - initialize wsgi_req(can be full of init_uwsgi_app data)
  2625. for (i = 0; i < uwsgi.cores; i++) {
  2626. memset(uwsgi.wsgi_requests[i], 0, sizeof(struct wsgi_request));
  2627. uwsgi.wsgi_requests[i]->async_id = i;
  2628. }
  2629. // eventually remap plugins
  2630. if (uwsgi.remap_modifier) {
  2631. char *map = strtok(uwsgi.remap_modifier, ",");
  2632. while (map != NULL) {
  2633. char *colon = strchr(map, ':');
  2634. if (colon) {
  2635. colon[0] = 0;
  2636. int rm_src = atoi(map);
  2637. int rm_dst = atoi(colon + 1);
  2638. uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
  2639. uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
  2640. }
  2641. map = strtok(NULL, ",");
  2642. }
  2643. }
  2644. #ifdef UWSGI_THREADING
  2645. if (uwsgi.cores > 1) {
  2646. uwsgi.core[0]->thread_id = pthread_self();
  2647. pthread_mutex_init(&uwsgi.six_feet_under_lock, NULL);
  2648. }
  2649. #endif
  2650. uwsgi_ignition();
  2651. // never here
  2652. exit(0);
  2653. }
  2654. void uwsgi_ignition() {
  2655. int i;
  2656. // snapshot workers do not enter the loop until a specific signal (SIGURG) is raised...
  2657. if (uwsgi.snapshot) {
  2658. wait_for_call_of_duty:
  2659. uwsgi_sig_pause();
  2660. if (uwsgi.snapshot)
  2661. goto wait_for_call_of_duty;
  2662. uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
  2663. }
  2664. for (i = 0; i < 256; i++) {
  2665. if (uwsgi.p[i]->hijack_worker) {
  2666. uwsgi.p[i]->hijack_worker();
  2667. }
  2668. }
  2669. for (i = 0; i < uwsgi.gp_cnt; i++) {
  2670. if (uwsgi.gp[i]->hijack_worker) {
  2671. uwsgi.gp[i]->hijack_worker();
  2672. }
  2673. }
  2674. if (uwsgi.loop) {
  2675. void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop);
  2676. if (!u_loop) {
  2677. uwsgi_log("unavailable loop engine !!!\n");
  2678. exit(1);
  2679. }
  2680. if (uwsgi.mywid == 1) {
  2681. uwsgi_log("*** running %s loop engine [addr:%p] ***\n", uwsgi.loop, u_loop);
  2682. }
  2683. u_loop();
  2684. uwsgi_log("your loop engine died. R.I.P.\n");
  2685. }
  2686. else {
  2687. #ifdef UWSGI_ZEROMQ
  2688. if (uwsgi.zeromq && uwsgi.async < 2 && !uwsgi.sockets->next) {
  2689. if (uwsgi.threads > 1) {
  2690. #ifdef UWSGI_THREADING
  2691. if (pthread_key_create(&uwsgi.tur_key, NULL)) {
  2692. uwsgi_error("pthread_key_create()");
  2693. exit(1);
  2694. }
  2695. for (i = 1; i < uwsgi.threads; i++) {
  2696. long j = i;
  2697. pthread_create(&uwsgi.core[i]->thread_id, &uwsgi.threads_attr, zeromq_loop, (void *) j);
  2698. }
  2699. #endif
  2700. }
  2701. long y = 0;
  2702. zeromq_loop((void *) y);
  2703. }
  2704. else if (uwsgi.threads > 1) {
  2705. #else
  2706. if (uwsgi.threads > 1) {
  2707. #endif
  2708. #ifdef UWSGI_THREADING
  2709. if (pthread_key_create(&uwsgi.tur_key, NULL)) {
  2710. uwsgi_error("pthread_key_create()");
  2711. exit(1);
  2712. }
  2713. for (i = 1; i < uwsgi.threads; i++) {
  2714. long j = i;
  2715. pthread_create(&uwsgi.core[i]->thread_id, &uwsgi.threads_attr, simple_loop, (void *) j);
  2716. }
  2717. #endif
  2718. }
  2719. if (uwsgi.async < 2) {
  2720. long y = 0;
  2721. simple_loop((void *) y);
  2722. }
  2723. #ifdef UWSGI_ASYNC
  2724. else {
  2725. async_loop(NULL);
  2726. }
  2727. #endif
  2728. }
  2729. if (uwsgi.snapshot) {
  2730. uwsgi_ignition();
  2731. }
  2732. // never here
  2733. pthread_exit(NULL);
  2734. }
  2735. /*
  2736. what happens here ?
  2737. we transform the uwsgi_option structure to a struct option
  2738. for passing it to getopt_long
  2739. A short options string is built.
  2740. This function could be called multiple times, so it will free previous areas
  2741. */
  2742. void build_options() {
  2743. int options_count = 0;
  2744. int pos = 0;
  2745. int i;
  2746. // first count the base options
  2747. struct uwsgi_option *op = uwsgi_base_options;
  2748. while(op->name) {
  2749. options_count++;
  2750. op++;
  2751. }
  2752. for(i=0;i<256;i++) {
  2753. if (uwsgi.p[i]->options) {
  2754. options_count += uwsgi_count_options(uwsgi.p[i]->options);
  2755. }
  2756. }
  2757. for(i=0;i<uwsgi.gp_cnt;i++) {
  2758. if (uwsgi.gp[i]->options) {
  2759. options_count += uwsgi_count_options(uwsgi.gp[i]->options);
  2760. }
  2761. }
  2762. if (uwsgi.options) free(uwsgi.options);
  2763. uwsgi.options = uwsgi_calloc(sizeof(struct uwsgi_option) * (options_count+1));
  2764. op = uwsgi_base_options;
  2765. while(op->name) {
  2766. memcpy(&uwsgi.options[pos], op, sizeof(struct uwsgi_option));
  2767. pos++;
  2768. op++;
  2769. }
  2770. for(i=0;i<256;i++) {
  2771. if (uwsgi.p[i]->options) {
  2772. int c = uwsgi_count_options(uwsgi.p[i]->options);
  2773. memcpy(&uwsgi.options[pos], uwsgi.p[i]->options, sizeof(struct uwsgi_option) * c);
  2774. pos += c;
  2775. }
  2776. }
  2777. for(i=0;i<uwsgi.gp_cnt;i++) {
  2778. if (uwsgi.gp[i]->options) {
  2779. int c = uwsgi_count_options(uwsgi.gp[i]->options);
  2780. memcpy(&uwsgi.options[pos], uwsgi.gp[i]->options, sizeof(struct uwsgi_option) * c);
  2781. pos += c;
  2782. }
  2783. }
  2784. pos = 0;
  2785. if (uwsgi.long_options) free(uwsgi.long_options);
  2786. uwsgi.long_options = uwsgi_calloc(sizeof(struct option) * (options_count+1));
  2787. if (uwsgi.short_options) free(uwsgi.short_options);
  2788. uwsgi.short_options = uwsgi_calloc( (options_count * 3) + 1) ;
  2789. op = uwsgi.options;
  2790. while(op->name) {
  2791. uwsgi.long_options[pos].name = op->name;
  2792. uwsgi.long_options[pos].has_arg = op->type;
  2793. uwsgi.long_options[pos].flag = 0;
  2794. // add 1000 to avoid short_options collision
  2795. uwsgi.long_options[pos].val = 1000+pos;
  2796. if (op->shortcut) {
  2797. char shortcut = (char) op->shortcut;
  2798. // avoid duplicates in short_options
  2799. if (!strchr(uwsgi.short_options, shortcut)) {
  2800. strncat(uwsgi.short_options, &shortcut, 1);
  2801. if (op->type == optional_argument) {
  2802. strcat(uwsgi.short_options, "::");
  2803. }
  2804. else if (op->type == required_argument) {
  2805. strcat(uwsgi.short_options, ":");
  2806. }
  2807. }
  2808. }
  2809. op++;
  2810. pos++;
  2811. }
  2812. }
  2813. void uwsgi_stdin_sendto(char *socket_name, uint8_t modifier1, uint8_t modifier2) {
  2814. char buf[4096];
  2815. ssize_t rlen;
  2816. size_t delta = 4096-4;
  2817. // leave space for uwsgi header
  2818. char *ptr = buf+4;
  2819. rlen = read(0, ptr, delta);
  2820. while (rlen > 0) {
  2821. #ifdef UWSGI_DEBUG
  2822. uwsgi_log("%.*s\n", rlen, ptr);
  2823. #endif
  2824. ptr += rlen;
  2825. delta -= rlen;
  2826. if (delta <= 0)
  2827. break;
  2828. rlen = read(0, ptr, delta);
  2829. }
  2830. if (ptr > buf+4) {
  2831. send_udp_message(modifier1, modifier2, socket_name, buf, (ptr - buf)-4);
  2832. uwsgi_log("sent string \"%.*s\" to cluster node %s\n", (ptr - buf)-4, buf+4, socket_name);
  2833. }
  2834. }
  2835. /*
  2836. this function build the help output from the uwsgi.options structure
  2837. */
  2838. void uwsgi_help(char *opt, char *val, void *none) {
  2839. size_t max_size = 0;
  2840. fprintf(stdout, "Usage: %s [options...]\n", uwsgi.binary_path);
  2841. struct uwsgi_option *op = uwsgi.options;
  2842. while(op && op->name) {
  2843. if (strlen(op->name) > max_size) {
  2844. max_size = strlen(op->name);
  2845. }
  2846. op++;
  2847. }
  2848. max_size++;
  2849. op = uwsgi.options;
  2850. while(op && op->name) {
  2851. if (op->shortcut) {
  2852. fprintf(stdout," -%c|--%-*s %s\n", op->shortcut, (int) max_size-3, op->name, op->help);
  2853. }
  2854. else {
  2855. fprintf(stdout," --%-*s %s\n", (int) max_size, op->name, op->help);
  2856. }
  2857. op++;
  2858. }
  2859. exit(0);
  2860. }
  2861. /*
  2862. initialize all apps
  2863. */
  2864. void uwsgi_init_all_apps() {
  2865. int i, j;
  2866. // now run the pre-app scripts
  2867. struct uwsgi_string_list *usl = uwsgi.exec_pre_app;
  2868. while(usl) {
  2869. uwsgi_log("running \"%s\" (pre app)...\n", usl->value);
  2870. int ret = uwsgi_run_command_and_wait(NULL, usl->value);
  2871. if (ret != 0) {
  2872. uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
  2873. exit(1);
  2874. }
  2875. usl = usl->next;
  2876. }
  2877. for (i = 0; i < 256; i++) {
  2878. if (uwsgi.p[i]->init_apps) {
  2879. uwsgi.p[i]->init_apps();
  2880. }
  2881. }
  2882. for (i = 0; i < uwsgi.gp_cnt; i++) {
  2883. if (uwsgi.gp[i]->init_apps) {
  2884. uwsgi.gp[i]->init_apps();
  2885. }
  2886. }
  2887. for (i = 0; i < uwsgi.mounts_cnt; i++) {
  2888. char *what = strchr(uwsgi.mounts[i], '=');
  2889. if (what) {
  2890. what[0] = 0;
  2891. what++;
  2892. uwsgi_log("mounting %s on %s\n", what, uwsgi.mounts[i]);
  2893. for (j = 0; j < 256; j++) {
  2894. if (uwsgi.p[j]->mount_app) {
  2895. if (!uwsgi_startswith(uwsgi.mounts[i], "regexp://", 9)) {
  2896. if (uwsgi.p[j]->mount_app(uwsgi.mounts[i]+9, what, 1) != -1)
  2897. break;
  2898. }
  2899. else {
  2900. if (uwsgi.p[j]->mount_app(uwsgi.mounts[i], what, 0) != -1)
  2901. break;
  2902. }
  2903. }
  2904. }
  2905. what--;
  2906. what[0] = '=';
  2907. }
  2908. else {
  2909. uwsgi_log("invalid mountpoint: %s\n", uwsgi.mounts[i]);
  2910. exit(1);
  2911. }
  2912. }
  2913. // no app initialized and virtualhosting enabled
  2914. if (uwsgi_apps_cnt == 0 && uwsgi.numproc > 0 && !uwsgi.command_mode) {
  2915. if (uwsgi.need_app) {
  2916. if (!uwsgi.lazy)
  2917. uwsgi_log("*** no app loaded. GAME OVER ***\n");
  2918. exit(UWSGI_FAILED_APP_CODE);
  2919. }
  2920. else {
  2921. uwsgi_log("*** no app loaded. going in full dynamic mode ***\n");
  2922. }
  2923. }
  2924. }
  2925. void uwsgi_opt_true(char *opt, char *value, void *key) {
  2926. int *ptr = (int *) key;
  2927. *ptr = 1;
  2928. if (value) {
  2929. if (!strcasecmp("false", value) || !strcasecmp("off", value) || !strcasecmp("no", value) || !strcmp("0", value)) {
  2930. *ptr = 0;
  2931. }
  2932. }
  2933. }
  2934. void uwsgi_opt_cluster_reload(char *opt, char *value, void *foobar) {
  2935. send_udp_message(98, 0, value, NULL, 0);
  2936. exit(0);
  2937. }
  2938. void uwsgi_opt_cluster_log(char *opt, char *value, void *foobar) {
  2939. uwsgi_stdin_sendto(value, 96, 0);
  2940. exit(0);
  2941. }
  2942. void uwsgi_opt_set_int(char *opt, char *value, void *key) {
  2943. int *ptr = (int *) key;
  2944. if (value) {
  2945. *ptr = atoi((char *)value);
  2946. }
  2947. else {
  2948. *ptr = 1;
  2949. }
  2950. if (*ptr < 0) {
  2951. uwsgi_log("invalid value for option \"%s\": must be > 0\n", opt);
  2952. exit(1);
  2953. }
  2954. }
  2955. void uwsgi_opt_set_rawint(char *opt, char *value, void *key) {
  2956. int *ptr = (int *) key;
  2957. if (value) {
  2958. *ptr = atoi((char *)value);
  2959. }
  2960. else {
  2961. *ptr = 1;
  2962. }
  2963. }
  2964. void uwsgi_opt_set_64bit(char *opt, char *value, void *key) {
  2965. uint64_t *ptr = (uint64_t *) key;
  2966. if (value) {
  2967. *ptr = (strtoul(value, NULL, 10)) ;
  2968. }
  2969. else {
  2970. *ptr = 1;
  2971. }
  2972. }
  2973. void uwsgi_opt_set_megabytes(char *opt, char *value, void *key) {
  2974. uint64_t *ptr = (uint64_t *) key;
  2975. *ptr = (strtoul(value, NULL, 10)) * 1024 * 1024;
  2976. }
  2977. void uwsgi_opt_set_dyn(char *opt, char *value, void *key) {
  2978. long *fake_ptr = (long *) key;
  2979. uint8_t dyn_opt_id = (long) fake_ptr;
  2980. uwsgi.shared->options[dyn_opt_id] = atoi(value);
  2981. }
  2982. void uwsgi_opt_dyn_true(char *opt, char *value, void *key) {
  2983. long *fake_ptr = (long *) key;
  2984. uint8_t dyn_opt_id = (long) fake_ptr;
  2985. uwsgi.shared->options[dyn_opt_id] = 1;
  2986. }
  2987. void uwsgi_opt_dyn_false(char *opt, char *value, void *key) {
  2988. long *fake_ptr = (long *) key;
  2989. uint8_t dyn_opt_id = (long) fake_ptr;
  2990. uwsgi.shared->options[dyn_opt_id] = 0;
  2991. }
  2992. void uwsgi_opt_set_str(char *opt, char *value, void *key) {
  2993. char **ptr = (char **) key;
  2994. *ptr = (char *) value;
  2995. }
  2996. void uwsgi_opt_set_logger(char *opt, char *value, void *prefix) {
  2997. if (!value) value = "";
  2998. if (prefix) {
  2999. uwsgi.requested_logger = uwsgi_concat3((char *)prefix, ":", value);
  3000. }
  3001. else {
  3002. uwsgi.requested_logger = uwsgi_str(value);
  3003. }
  3004. }
  3005. void uwsgi_opt_set_str_spaced(char *opt, char *value, void *key) {
  3006. char **ptr = (char **) key;
  3007. *ptr = uwsgi_concat2((char *) value, " ");
  3008. }
  3009. void uwsgi_opt_add_string_list(char *opt, char *value, void *list) {
  3010. struct uwsgi_string_list **ptr = (struct uwsgi_string_list **) list;
  3011. uwsgi_string_new_list(ptr, value);
  3012. }
  3013. void uwsgi_opt_add_shared_socket(char *opt, char *value, void *protocol) {
  3014. uwsgi_new_shared_socket(generate_socket_name(value));
  3015. }
  3016. void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
  3017. struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
  3018. uwsgi_sock->proto_name = protocol;
  3019. }
  3020. void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
  3021. char *p = strchr(value, '=');
  3022. if (!p) {
  3023. uwsgi_log("invalid placeholder/--set value\n");
  3024. exit(1);
  3025. }
  3026. p[0] = 0;
  3027. add_exported_option(uwsgi_str(value), p+1, 1);
  3028. p[0] = '=';
  3029. }
  3030. void uwsgi_opt_set_umask(char *opt, char *value, void *mode) {
  3031. mode_t umask_mode = 0;
  3032. if (strlen(value) < 3) {
  3033. uwsgi_log("invalid umask: %s\n", value);
  3034. }
  3035. umask_mode = 0;
  3036. if (strlen(value) == 3) {
  3037. umask_mode = (umask_mode << 3) + (value[0] - '0');
  3038. umask_mode = (umask_mode << 3) + (value[1] - '0');
  3039. umask_mode = (umask_mode << 3) + (value[2] - '0');
  3040. }
  3041. else {
  3042. umask_mode = (umask_mode << 3) + (value[1] - '0');
  3043. umask_mode = (umask_mode << 3) + (value[2] - '0');
  3044. umask_mode = (umask_mode << 3) + (value[3] - '0');
  3045. }
  3046. umask(umask_mode);
  3047. uwsgi.do_not_change_umask = 1;
  3048. }
  3049. void uwsgi_opt_print(char *opt, char *value, void *str) {
  3050. if (str) {
  3051. fprintf(stdout, "%s\n", (char *) str);
  3052. exit(0);
  3053. }
  3054. fprintf(stdout, "%s\n", value);
  3055. }
  3056. void uwsgi_opt_set_uid(char *opt, char *value, void *none) {
  3057. uwsgi.uid = atoi(value);
  3058. if (!uwsgi.uid)
  3059. uwsgi.uidname = value;
  3060. }
  3061. void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
  3062. uwsgi.gid = atoi(value);
  3063. if (!uwsgi.gid)
  3064. uwsgi.gidname = value;
  3065. }
  3066. #ifdef UWSGI_CAP
  3067. void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
  3068. uwsgi_build_cap(value);
  3069. }
  3070. #endif
  3071. #ifdef __linux__
  3072. void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
  3073. uwsgi_build_unshare(value);
  3074. }
  3075. #endif
  3076. void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
  3077. uwsgi_daemon_new(&uwsgi.daemons, value);
  3078. }
  3079. void uwsgi_opt_set_env(char *opt, char *value, void *none) {
  3080. if (putenv(value)) {
  3081. uwsgi_error("putenv()");
  3082. }
  3083. }
  3084. void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
  3085. if (unsetenv(value)) {
  3086. uwsgi_error("unsetenv()");
  3087. }
  3088. }
  3089. void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
  3090. long *signum_fake_ptr = (long *) sig;
  3091. int signum = (long) signum_fake_ptr;
  3092. signal_pidfile(signum, pidfile);
  3093. exit(0);
  3094. }
  3095. void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
  3096. char *p = strtok(uwsgi_concat2(value, ""), ",");
  3097. while (p != NULL) {
  3098. #ifdef UWSGI_DEBUG
  3099. uwsgi_debug("loading plugin %s\n", p);
  3100. #endif
  3101. if (uwsgi_load_plugin(-1, p, NULL)) {
  3102. build_options();
  3103. }
  3104. p = strtok(NULL, ",");
  3105. }
  3106. }
  3107. void uwsgi_opt_add_app(char *opt, char *value, void *regexp) {
  3108. if (uwsgi.mounts_cnt < MAX_APPS) {
  3109. if (regexp) {
  3110. uwsgi.mounts[uwsgi.mounts_cnt] = uwsgi_concat2("regexp://", value);
  3111. }
  3112. else {
  3113. uwsgi.mounts[uwsgi.mounts_cnt] = value;
  3114. }
  3115. uwsgi.mounts_cnt++;
  3116. }
  3117. else {
  3118. uwsgi_log("you can specify at most %d --%s options\n", opt, MAX_APPS);
  3119. }
  3120. }
  3121. void uwsgi_opt_check_static(char *opt, char *value, void *foobar) {
  3122. uwsgi_dyn_dict_new(&uwsgi.check_static, value, strlen(value), NULL, 0);
  3123. uwsgi_log("[uwsgi-static] added check for %s\n", value);
  3124. uwsgi.build_mime_dict = 1;
  3125. }
  3126. void uwsgi_opt_add_dyn_dict(char *opt, char *value, void *dict) {
  3127. char *equal = strchr(value, '=');
  3128. if (!equal) {
  3129. uwsgi_log("invalid dictionary syntax for %s\n", opt);
  3130. exit(1);
  3131. }
  3132. struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
  3133. uwsgi_dyn_dict_new(udd, value, equal-value, equal+1, strlen(equal+1));
  3134. }
  3135. #ifdef UWSGI_PCRE
  3136. void uwsgi_opt_add_regexp_dyn_dict(char *opt, char *value, void *dict) {
  3137. char *space = strchr(value, ' ');
  3138. if (!space) {
  3139. uwsgi_log("invalid dictionary syntax for %s\n", opt);
  3140. exit(1);
  3141. }
  3142. struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
  3143. struct uwsgi_dyn_dict *new_udd = uwsgi_dyn_dict_new(udd, value, space-value, space+1, strlen(space+1));
  3144. char *regexp = uwsgi_concat2n(value, space-value, "", 0);
  3145. if (uwsgi_regexp_build(regexp, &new_udd->pattern, &new_udd->pattern_extra)) {
  3146. exit(1);
  3147. }
  3148. free(regexp);
  3149. }
  3150. #endif
  3151. void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
  3152. if (!strcasecmp("x-sendfile", value)) {
  3153. uwsgi.file_serve_mode = 2;
  3154. }
  3155. else if (!strcasecmp("xsendfile", value)) {
  3156. uwsgi.file_serve_mode = 2;
  3157. }
  3158. else if (!strcasecmp("x-accel-redirect", value)) {
  3159. uwsgi.file_serve_mode = 1;
  3160. }
  3161. else if (!strcasecmp("xaccelredirect", value)) {
  3162. uwsgi.file_serve_mode = 1;
  3163. }
  3164. else if (!strcasecmp("nginx", value)) {
  3165. uwsgi.file_serve_mode = 1;
  3166. }
  3167. }
  3168. void uwsgi_opt_static_map(char *opt, char *value, void *static_maps) {
  3169. struct uwsgi_dyn_dict **maps = (struct uwsgi_dyn_dict **) static_maps;
  3170. char *mountpoint = uwsgi_str(value);
  3171. char *docroot = strchr(mountpoint, '=');
  3172. if (!docroot) {
  3173. uwsgi_log("invalid document root in static map, syntax mountpoint=docroot\n");
  3174. exit(1);
  3175. }
  3176. docroot[0] = 0;
  3177. docroot++;
  3178. uwsgi_dyn_dict_new(maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
  3179. uwsgi_log("[uwsgi-static] added mapping for %s => %s\n", mountpoint, docroot);
  3180. uwsgi.build_mime_dict = 1;
  3181. }
  3182. int uwsgi_zerg_attach(char *value) {
  3183. int count = 8;
  3184. int zerg_fd = uwsgi_connect(value, 30, 0);
  3185. if (zerg_fd < 0) {
  3186. uwsgi_log("--- unable to connect to zerg server %s ---\n", value);
  3187. return -1;
  3188. }
  3189. int last_count = count;
  3190. int *zerg = uwsgi_attach_fd(zerg_fd, &count, "uwsgi-zerg", 10);
  3191. if (zerg == NULL) {
  3192. if (last_count != count) {
  3193. close(zerg_fd);
  3194. zerg_fd = uwsgi_connect(value, 30, 0);
  3195. if (zerg_fd < 0) {
  3196. uwsgi_log("--- unable to connect to zerg server %s ---\n", value);
  3197. return -1;
  3198. }
  3199. zerg = uwsgi_attach_fd(zerg_fd, &count, "uwsgi-zerg", 10);
  3200. }
  3201. }
  3202. if (zerg == NULL) {
  3203. uwsgi_log("--- invalid data received from zerg-server ---\n");
  3204. return -1;
  3205. }
  3206. if (!uwsgi.zerg) {
  3207. uwsgi.zerg = zerg;
  3208. }
  3209. else {
  3210. int pos = 0;
  3211. for(;;) {
  3212. if (uwsgi.zerg[pos] == -1) {
  3213. uwsgi.zerg = realloc(uwsgi.zerg, (sizeof(int) * (pos)) + (sizeof(int) * count+1));
  3214. if (!uwsgi.zerg) {
  3215. uwsgi_error("realloc()");
  3216. exit(1);
  3217. }
  3218. memcpy(&uwsgi.zerg[pos], zerg, (sizeof(int) * count+1));
  3219. break;
  3220. }
  3221. pos++;
  3222. }
  3223. }
  3224. close(zerg_fd);
  3225. return 0;
  3226. }
  3227. void uwsgi_opt_signal(char *opt, char *value, void *foobar) {
  3228. uwsgi_command_signal(value);
  3229. }
  3230. void uwsgi_opt_log_date(char *opt, char *value, void *foobar) {
  3231. uwsgi.logdate = 1;
  3232. if (value) {
  3233. if (strcasecmp("true", value) && strcasecmp("1", value) && strcasecmp("on", value) && strcasecmp("yes", value)) {
  3234. uwsgi.log_strftime = value;
  3235. }
  3236. }
  3237. }
  3238. void uwsgi_opt_chmod_socket(char *opt, char *value, void *foobar) {
  3239. int i;
  3240. uwsgi.chmod_socket = 1;
  3241. if (value) {
  3242. if (strlen(value) == 1 && *value == '1') {
  3243. return;
  3244. }
  3245. if (strlen(value) != 3) {
  3246. uwsgi_log("invalid chmod value: %s\n", value);
  3247. exit(1);
  3248. }
  3249. for (i = 0; i < 3; i++) {
  3250. if (value[i] < '0' || value[i] > '7') {
  3251. uwsgi_log("invalid chmod value: %s\n", value);
  3252. exit(1);
  3253. }
  3254. }
  3255. uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[0] - '0');
  3256. uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[1] - '0');
  3257. uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (value[2] - '0');
  3258. }
  3259. }
  3260. void uwsgi_opt_logfile_chmod(char *opt, char *value, void *foobar) {
  3261. int i;
  3262. if (strlen(value) != 3) {
  3263. uwsgi_log("invalid chmod value: %s\n", value);
  3264. exit(1);
  3265. }
  3266. for (i = 0; i < 3; i++) {
  3267. if (value[i] < '0' || value[i] > '7') {
  3268. uwsgi_log("invalid chmod value: %s\n", value);
  3269. exit(1);
  3270. }
  3271. }
  3272. uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[0] - '0');
  3273. uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[1] - '0');
  3274. uwsgi.chmod_logfile_value = (uwsgi.chmod_logfile_value << 3) + (value[2] - '0');
  3275. }
  3276. void uwsgi_opt_max_vars(char *opt, char *value, void *foobar) {
  3277. uwsgi.max_vars = atoi(value);
  3278. uwsgi.vec_size = 4 + 1 + (4 * uwsgi.max_vars);
  3279. }
  3280. void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
  3281. uwsgi_log("[WARNING] option \"%s\" is deprecated: %s\n", opt, (char *)message);
  3282. }
  3283. void uwsgi_opt_load(char *opt, char *filename, void *none) {
  3284. #ifdef UWSGI_INI
  3285. if (uwsgi_endswith(filename, ".ini")) { uwsgi_opt_load_ini(opt, filename, none); return;}
  3286. #endif
  3287. #ifdef UWSGI_XML
  3288. if (uwsgi_endswith(filename, ".xml")) { uwsgi_opt_load_xml(opt, filename, none); return;}
  3289. #endif
  3290. #ifdef UWSGI_YAML
  3291. if (uwsgi_endswith(filename, ".yaml")) { uwsgi_opt_load_yml(opt, filename, none); return;}
  3292. if (uwsgi_endswith(filename, ".yml")) { uwsgi_opt_load_yml(opt, filename, none); return;}
  3293. #endif
  3294. #ifdef UWSGI_JSON
  3295. if (uwsgi_endswith(filename, ".json")) { uwsgi_opt_load_json(opt, filename, none); return;}
  3296. if (uwsgi_endswith(filename, ".js")) { uwsgi_opt_load_json(opt, filename, none); return;}
  3297. #endif
  3298. }
  3299. void uwsgi_opt_logic(char *opt, char *arg, void *func) {
  3300. if (uwsgi.logic_opt) {
  3301. uwsgi_log("recursive logic in options is not supported (option = %s)\n", opt);
  3302. exit(1);
  3303. }
  3304. uwsgi.logic_opt = (int (*)(char *, char *)) func;
  3305. uwsgi.logic_opt_cycles = 0;
  3306. if (arg) {
  3307. uwsgi.logic_opt_arg = uwsgi_str(arg);
  3308. }
  3309. else {
  3310. uwsgi.logic_opt_arg = NULL;
  3311. }
  3312. }
  3313. void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
  3314. }
  3315. #ifdef UWSGI_INI
  3316. void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
  3317. config_magic_table_fill(filename, uwsgi.magic_table);
  3318. uwsgi_ini_config(filename, uwsgi.magic_table);
  3319. }
  3320. #endif
  3321. #ifdef UWSGI_XML
  3322. void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
  3323. config_magic_table_fill(filename, uwsgi.magic_table);
  3324. uwsgi_xml_config(filename, uwsgi.wsgi_req, uwsgi.magic_table);
  3325. }
  3326. #endif
  3327. #ifdef UWSGI_YAML
  3328. void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
  3329. config_magic_table_fill(filename, uwsgi.magic_table);
  3330. uwsgi_yaml_config(filename, uwsgi.magic_table);
  3331. }
  3332. #endif
  3333. #ifdef UWSGI_SQLITE3
  3334. void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
  3335. config_magic_table_fill(filename, uwsgi.magic_table);
  3336. uwsgi_sqlite3_config(filename, uwsgi.magic_table);
  3337. }
  3338. #endif
  3339. #ifdef UWSGI_JSON
  3340. void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
  3341. config_magic_table_fill(filename, uwsgi.magic_table);
  3342. uwsgi_json_config(filename, uwsgi.magic_table);
  3343. }
  3344. #endif
  3345. #ifdef UWSGI_LDAP
  3346. void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
  3347. uwsgi_ldap_config(url);
  3348. }
  3349. #endif
  3350. void uwsgi_opt_flock(char *opt, char *filename, void *none) {
  3351. int fd = open(filename, O_RDWR);
  3352. if (fd < 0) {
  3353. uwsgi_error_open(filename);
  3354. exit(1);
  3355. }
  3356. if (uwsgi_fcntl_is_locked(fd)) {
  3357. uwsgi_log("uWSGI ERROR: %s is locked by another instance\n", filename);
  3358. exit(1);
  3359. }
  3360. }
  3361. void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
  3362. int fd = open(filename, O_RDWR);
  3363. if (fd < 0) {
  3364. uwsgi_error_open(filename);
  3365. exit(1);
  3366. }
  3367. if (uwsgi_fcntl_lock(fd)) {
  3368. exit(1);
  3369. }
  3370. }