1 #include "uwsgi.h"
2
3 extern struct uwsgi_server uwsgi;
4
5 struct http_status_codes {
6 const char key[3];
7 const char *message;
8 int message_size;
9 };
10
11 /* statistically ordered */
12 struct http_status_codes hsc[] = {
13 {"200", "OK"},
14 {"302", "Found"},
15 {"404", "Not Found"},
16 {"500", "Internal Server Error"},
17 {"301", "Moved Permanently"},
18 {"304", "Not Modified"},
19 {"303", "See Other"},
20 {"403", "Forbidden"},
21 {"307", "Temporary Redirect"},
22 {"401", "Unauthorized"},
23 {"400", "Bad Request"},
24 {"405", "Method Not Allowed"},
25 {"408", "Request Timeout"},
26
27 {"100", "Continue"},
28 {"101", "Switching Protocols"},
29 {"201", "Created"},
30 {"202", "Accepted"},
31 {"203", "Non-Authoritative Information"},
32 {"204", "No Content"},
33 {"205", "Reset Content"},
34 {"206", "Partial Content"},
35 {"300", "Multiple Choices"},
36 {"305", "Use Proxy"},
37 {"402", "Payment Required"},
38 {"406", "Not Acceptable"},
39 {"407", "Proxy Authentication Required"},
40 {"409", "Conflict"},
41 {"410", "Gone"},
42 {"411", "Length Required"},
43 {"412", "Precondition Failed"},
44 {"413", "Request Entity Too Large"},
45 {"414", "Request-URI Too Long"},
46 {"415", "Unsupported Media Type"},
47 {"416", "Requested Range Not Satisfiable"},
48 {"417", "Expectation Failed"},
49 {"418", "I'm a teapot"},
50 {"422", "Unprocessable Entity"},
51 {"425", "Too Early"},
52 {"426", "Upgrade Required"},
53 {"428", "Precondition Required"},
54 {"429", "Too Many Requests"},
55 {"431", "Request Header Fields Too Large"},
56 {"451", "Unavailable For Legal Reasons"},
57 {"501", "Not Implemented"},
58 {"502", "Bad Gateway"},
59 {"503", "Service Unavailable"},
60 {"504", "Gateway Timeout"},
61 {"505", "HTTP Version Not Supported"},
62 {"509", "Bandwidth Limit Exceeded"},
63 {"511", "Network Authentication Required"},
64 {"", NULL},
65 };
66
67
68
69
uwsgi_init_default()70 void uwsgi_init_default() {
71
72 uwsgi.cpus = 1;
73 uwsgi.new_argc = -1;
74
75 uwsgi.backtrace_depth = 64;
76 uwsgi.max_apps = 64;
77
78 uwsgi.master_queue = -1;
79
80 uwsgi.signal_socket = -1;
81 uwsgi.my_signal_socket = -1;
82 uwsgi.stats_fd = -1;
83
84 uwsgi.stats_pusher_default_freq = 3;
85
86 uwsgi.original_log_fd = 2;
87
88 uwsgi.emperor_fd_config = -1;
89 uwsgi.emperor_fd_proxy = -1;
90 // default emperor scan frequency
91 uwsgi.emperor_freq = 3;
92 uwsgi.emperor_throttle = 1000;
93 uwsgi.emperor_heartbeat = 30;
94 uwsgi.emperor_curse_tolerance = 30;
95 // max 3 minutes throttling
96 uwsgi.emperor_max_throttle = 1000 * 180;
97 uwsgi.emperor_pid = -1;
98
99 uwsgi.subscribe_freq = 10;
100 uwsgi.subscription_tolerance = 17;
101
102 uwsgi.cores = 1;
103 uwsgi.threads = 1;
104
105 // default max number of rpc slot
106 uwsgi.rpc_max = 64;
107
108 uwsgi.offload_threads_events = 64;
109
110 uwsgi.default_app = -1;
111
112 uwsgi.buffer_size = 4096;
113 uwsgi.body_read_warning = 8;
114 uwsgi.numproc = 1;
115
116 uwsgi.forkbomb_delay = 2;
117
118 uwsgi.async = 1;
119 uwsgi.listen_queue = 100;
120
121 uwsgi.cheaper_overload = 3;
122
123 uwsgi.log_master_bufsize = 8192;
124
125 uwsgi.worker_reload_mercy = 60;
126 uwsgi.mule_reload_mercy = 60;
127
128 uwsgi.max_vars = MAX_VARS;
129 uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
130
131 uwsgi.socket_timeout = 4;
132 uwsgi.logging_options.enabled = 1;
133
134 // a workers hould be running for at least 10 seconds
135 uwsgi.min_worker_lifetime = 10;
136
137 uwsgi.spooler_frequency = 30;
138
139 uwsgi.shared->spooler_signal_pipe[0] = -1;
140 uwsgi.shared->spooler_signal_pipe[1] = -1;
141
142 uwsgi.shared->mule_signal_pipe[0] = -1;
143 uwsgi.shared->mule_signal_pipe[1] = -1;
144
145 uwsgi.shared->mule_queue_pipe[0] = -1;
146 uwsgi.shared->mule_queue_pipe[1] = -1;
147
148 uwsgi.shared->worker_log_pipe[0] = -1;
149 uwsgi.shared->worker_log_pipe[1] = -1;
150
151 uwsgi.shared->worker_req_log_pipe[0] = -1;
152 uwsgi.shared->worker_req_log_pipe[1] = -1;
153
154 uwsgi.req_log_fd = 2;
155
156 #ifdef UWSGI_SSL
157 // 1 day of tolerance
158 uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
159 uwsgi.ssl_sessions_timeout = 300;
160 uwsgi.ssl_verify_depth = 1;
161 #endif
162
163 uwsgi.alarm_freq = 3;
164 uwsgi.alarm_msg_size = 8192;
165
166 uwsgi.exception_handler_msg_size = 65536;
167
168 uwsgi.multicast_ttl = 1;
169 uwsgi.multicast_loop = 1;
170
171 // filling http status codes
172 struct http_status_codes *http_sc;
173 for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
174 http_sc->message_size = strlen(http_sc->message);
175 }
176
177 uwsgi.empty = "";
178
179 #ifdef __linux__
180 uwsgi.cgroup_dir_mode = "0700";
181 #endif
182
183 uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
184 uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
185 uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
186 uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
187
188 uwsgi_websockets_init();
189
190 // 1 MB default limit
191 uwsgi.chunked_input_limit = 1024*1024;
192
193 // clear reforked status
194 uwsgi.master_is_reforked = 0;
195
196 uwsgi.master_fifo_fd = -1;
197 uwsgi_master_fifo_prepare();
198
199 uwsgi.notify_socket_fd = -1;
200 }
201
uwsgi_setup_reload()202 void uwsgi_setup_reload() {
203
204 char env_reload_buf[11];
205
206 char *env_reloads = getenv("UWSGI_RELOADS");
207 if (env_reloads) {
208 //convert env value to int
209 uwsgi.reloads = atoi(env_reloads);
210 uwsgi.reloads++;
211 //convert reloads to string
212 int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
213 if (rlen > 0 && rlen < 10) {
214 env_reload_buf[rlen] = 0;
215 if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
216 uwsgi_error("setenv()");
217 }
218 }
219 uwsgi.is_a_reload = 1;
220 }
221 else {
222 if (setenv("UWSGI_RELOADS", "0", 1)) {
223 uwsgi_error("setenv()");
224 }
225 }
226
227 }
228
uwsgi_autoload_plugins_by_name(char * argv_zero)229 void uwsgi_autoload_plugins_by_name(char *argv_zero) {
230
231 char *plugins_requested = NULL;
232
233 char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
234 if (!original_proc_name) {
235 // here we use argv[0];
236 original_proc_name = argv_zero;
237 setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
238 }
239 char *p = strrchr(original_proc_name, '/');
240 if (p == NULL)
241 p = original_proc_name;
242 p = strstr(p, "uwsgi_");
243 if (p != NULL) {
244 char *ctx = NULL;
245 uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
246 uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
247 uwsgi_load_plugin(-1, plugins_requested, NULL);
248 }
249 }
250
251 plugins_requested = getenv("UWSGI_PLUGINS");
252 if (plugins_requested) {
253 plugins_requested = uwsgi_concat2(plugins_requested, "");
254 char *p, *ctx = NULL;
255 uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
256 uwsgi_load_plugin(-1, p, NULL);
257 }
258 }
259
260 }
261
uwsgi_commandline_config()262 void uwsgi_commandline_config() {
263 int i;
264
265 uwsgi.option_index = -1;
266
267 int argc = uwsgi.argc;
268 char **argv = uwsgi.argv;
269
270 if (uwsgi.new_argc > -1 && uwsgi.new_argv) {
271 argc = uwsgi.new_argc;
272 argv = uwsgi.new_argv;
273 }
274
275 char *optname;
276 while ((i = getopt_long(argc, argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
277
278 if (i == '?') {
279 uwsgi_log("getopt_long() error\n");
280 exit(1);
281 }
282
283 if (uwsgi.option_index > -1) {
284 optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
285 }
286 else {
287 optname = uwsgi_get_optname_by_index(i);
288 }
289 if (!optname) {
290 uwsgi_log("unable to parse command line options\n");
291 exit(1);
292 }
293 uwsgi.option_index = -1;
294 add_exported_option(optname, optarg, 0);
295 }
296
297
298 #ifdef UWSGI_DEBUG
299 uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
300 #endif
301
302 if (optind < argc) {
303 for (i = optind; i < argc; i++) {
304 char *lazy = argv[i];
305 if (lazy[0] != '[') {
306 uwsgi_opt_load(NULL, lazy, NULL);
307 // manage magic mountpoint
308 int magic = 0;
309 int j;
310 for (j = 0; j < uwsgi.gp_cnt; j++) {
311 if (uwsgi.gp[j]->magic) {
312 if (uwsgi.gp[j]->magic(NULL, lazy)) {
313 magic = 1;
314 break;
315 }
316 }
317 }
318 if (!magic) {
319 for (j = 0; j < 256; j++) {
320 if (uwsgi.p[j]->magic) {
321 if (uwsgi.p[j]->magic(NULL, lazy)) {
322 magic = 1;
323 break;
324 }
325 }
326 }
327 }
328 }
329 }
330 }
331
332 }
333
uwsgi_setup_workers()334 void uwsgi_setup_workers() {
335 int i, j;
336 // allocate shared memory for workers + master
337 uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1));
338
339 for (i = 0; i <= uwsgi.numproc; i++) {
340 // allocate memory for apps
341 uwsgi.workers[i].apps = (struct uwsgi_app *) uwsgi_calloc_shared(sizeof(struct uwsgi_app) * uwsgi.max_apps);
342
343 // allocate memory for cores
344 uwsgi.workers[i].cores = (struct uwsgi_core *) uwsgi_calloc_shared(sizeof(struct uwsgi_core) * uwsgi.cores);
345
346 // this is a trick for avoiding too much memory areas
347 void *ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps * uwsgi.cores);
348 // add 4 bytes for uwsgi header
349 void *buffers = uwsgi_malloc_shared((uwsgi.buffer_size+4) * uwsgi.cores);
350 void *hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
351 void *post_buf = NULL;
352 if (uwsgi.post_buffering > 0)
353 post_buf = uwsgi_malloc_shared(uwsgi.post_buffering_bufsize * uwsgi.cores);
354
355
356 for (j = 0; j < uwsgi.cores; j++) {
357 // allocate shared memory for thread states (required for some language, like python)
358 uwsgi.workers[i].cores[j].ts = ts + ((sizeof(void *) * uwsgi.max_apps) * j);
359 // raw per-request buffer (+4 bytes for uwsgi header)
360 uwsgi.workers[i].cores[j].buffer = buffers + ((uwsgi.buffer_size+4) * j);
361 // iovec for uwsgi vars
362 uwsgi.workers[i].cores[j].hvec = hvec + ((sizeof(struct iovec) * uwsgi.vec_size) * j);
363 if (post_buf)
364 uwsgi.workers[i].cores[j].post_buf = post_buf + (uwsgi.post_buffering_bufsize * j);
365 }
366
367 // master does not need to following steps...
368 if (i == 0)
369 continue;
370 uwsgi.workers[i].signal_pipe[0] = -1;
371 uwsgi.workers[i].signal_pipe[1] = -1;
372 snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
373 }
374
375 uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
376 if (uwsgi.post_buffering > 0) {
377 total_memory += (uwsgi.post_buffering_bufsize * uwsgi.cores);
378 }
379
380 total_memory *= (uwsgi.numproc + uwsgi.master_process);
381 if (uwsgi.numproc > 0)
382 uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", (unsigned long long) total_memory, (unsigned long long) (total_memory / 1024), uwsgi.cores * uwsgi.numproc);
383
384 // allocate signal table
385 uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
386
387 #ifdef UWSGI_ROUTING
388 uwsgi_fixup_routes(uwsgi.routes);
389 uwsgi_fixup_routes(uwsgi.error_routes);
390 uwsgi_fixup_routes(uwsgi.response_routes);
391 uwsgi_fixup_routes(uwsgi.final_routes);
392 #endif
393
394 }
395
uwsgi_daemonize2()396 pid_t uwsgi_daemonize2() {
397 if (uwsgi.has_emperor) {
398 logto(uwsgi.daemonize2);
399 }
400 else {
401 if (!uwsgi.is_a_reload) {
402 uwsgi_log("*** daemonizing uWSGI ***\n");
403 daemonize(uwsgi.daemonize2);
404 }
405 else if (uwsgi.log_reopen) {
406 logto(uwsgi.daemonize2);
407 }
408 }
409 uwsgi.mypid = getpid();
410
411 uwsgi.workers[0].pid = uwsgi.mypid;
412
413 if (uwsgi.pidfile && !uwsgi.is_a_reload) {
414 uwsgi_write_pidfile(uwsgi.pidfile);
415 }
416
417 if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
418 uwsgi_write_pidfile(uwsgi.pidfile2);
419 }
420
421 if (uwsgi.log_master) uwsgi_setup_log_master();
422
423 return uwsgi.mypid;
424 }
425
426 // fix/check related options
sanitize_args()427 void sanitize_args() {
428
429 if (uwsgi.async > 1) {
430 uwsgi.cores = uwsgi.async;
431 }
432
433 if (uwsgi.threads > 1) {
434 uwsgi.has_threads = 1;
435 uwsgi.cores = uwsgi.threads;
436 }
437
438 if (uwsgi.harakiri_options.workers > 0) {
439 if (!uwsgi.post_buffering) {
440 uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
441 }
442 }
443
444 if (uwsgi.write_errors_exception_only) {
445 uwsgi.ignore_sigpipe = 1;
446 uwsgi.ignore_write_errors = 1;
447 }
448
449 if (uwsgi.cheaper_count == 0) uwsgi.cheaper = 0;
450
451 if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
452 uwsgi_log("invalid cheaper value: must be lower than processes\n");
453 exit(1);
454 }
455
456 if (uwsgi.cheaper && uwsgi.cheaper_count) {
457 if (uwsgi.cheaper_initial) {
458 if (uwsgi.cheaper_initial < uwsgi.cheaper_count) {
459 uwsgi_log("warning: invalid cheaper-initial value (%d), must be equal or higher than cheaper (%d), using %d as initial number of workers\n",
460 uwsgi.cheaper_initial, uwsgi.cheaper_count, uwsgi.cheaper_count);
461 uwsgi.cheaper_initial = uwsgi.cheaper_count;
462 }
463 else if (uwsgi.cheaper_initial > uwsgi.numproc) {
464 uwsgi_log("warning: invalid cheaper-initial value (%d), must be lower or equal than worker count (%d), using %d as initial number of workers\n",
465 uwsgi.cheaper_initial, uwsgi.numproc, uwsgi.numproc);
466 uwsgi.cheaper_initial = uwsgi.numproc;
467 }
468 }
469 else {
470 uwsgi.cheaper_initial = uwsgi.cheaper_count;
471 }
472 }
473
474 if (uwsgi.max_worker_lifetime > 0 && uwsgi.min_worker_lifetime >= uwsgi.max_worker_lifetime) {
475 uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
476 uwsgi.min_worker_lifetime, uwsgi.max_worker_lifetime);
477 exit(1);
478 }
479
480 if (uwsgi.cheaper_rss_limit_soft && uwsgi.logging_options.memory_report != 1 && uwsgi.force_get_memusage != 1) {
481 uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
482 exit(1);
483 }
484 if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
485 uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
486 exit(1);
487 }
488 if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
489 uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
490 exit(1);
491 }
492
493 if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
494 if (!uwsgi.mem_collector_freq) uwsgi.mem_collector_freq = 3;
495 }
496
497 /* here we try to choose if thunder lock is a good thing */
498 #ifdef UNBIT
499 if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
500 uwsgi.use_thunder_lock = 1;
501 }
502 #endif
503 }
504
uwsgi_http_status_msg(char * status,uint16_t * len)505 const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
506 struct http_status_codes *http_sc;
507 for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
508 if (!strncmp(http_sc->key, status, 3)) {
509 *len = http_sc->message_size;
510 return http_sc->message;
511 }
512 }
513 return NULL;
514 }
515