root/uwsgi.c

Revision 498:9a20412424d9, 84.4 KB (checked in by roberto@…, 5 days ago)

fix pidfile on HTTP mode

Line 
1/*
2       
3    *** uWSGI ***
4
5    Copyright (C) 2009-2010 Unbit S.a.s. <info@unbit.it>
6       
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    as published by the Free Software Foundation; either version 2
10    of the License, or (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21********* Note for Linux users *********
22uWSGI supports UNIX socket on abstract namespace.
23Use them if you have filesystem permission problems.
24
25********* Note for Unbit users *********
26Try to keep the same configuration on your unbit account (threading mode
27in particular)
28
29*/
30
31
32#include "uwsgi.h"
33
34struct uwsgi_server uwsgi;
35
36extern char **environ;
37
38#ifdef UWSGI_SENDFILE
39PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
40#endif
41
42
43static struct option long_options[] = {
44                {"socket", required_argument, 0, 's'},
45                {"processes", required_argument, 0, 'p'},
46                {"harakiri", required_argument, 0, 't'},
47#ifdef UWSGI_XML
48                {"xmlconfig", required_argument, 0, 'x'},
49#endif
50                {"daemonize", required_argument, 0, 'd'},
51                {"listen", required_argument, 0, 'l'},
52                {"optimize", required_argument, 0, 'O'},
53                {"max-vars", required_argument, 0, 'v'},
54                {"buffer-size", required_argument, 0, 'b'},
55                {"memory-report", no_argument, 0, 'm'},
56                {"cgi-mode", no_argument, 0, 'c'},
57                {"abstract-socket", no_argument, 0, 'a'},
58                {"chmod-socket", optional_argument , 0, 'C'},
59#ifdef UWSGI_THREADING
60                {"enable-threads", no_argument, 0, 'T'},
61#endif
62                {"profiler", no_argument, 0, 'P'},
63                {"single-interpreter", no_argument, 0, 'i'},
64                {"master", no_argument, 0, 'M'},
65                {"help", no_argument, 0, 'h'},
66                {"reaper", no_argument, 0, 'r'},
67                {"max-requests", required_argument, 0, 'R'},
68                {"socket-timeout", required_argument, 0, 'z'},
69                {"module", required_argument, 0, 'w'},
70                {"test", required_argument, 0, 'j'},
71                {"home", required_argument, 0, 'H'},
72                {"sharedarea", required_argument, 0, 'A'},
73#ifdef UWSGI_SPOOLER
74                {"spooler", required_argument, 0, 'Q'},
75#endif
76                {"disable-logging", no_argument, 0, 'L'},
77
78                {"callable", required_argument, 0, LONG_ARGS_CALLABLE},
79
80                {"pidfile", required_argument, 0, LONG_ARGS_PIDFILE},
81                {"chroot", required_argument, 0, LONG_ARGS_CHROOT},
82                {"gid", required_argument, 0, LONG_ARGS_GID},
83                {"uid", required_argument, 0, LONG_ARGS_UID},
84                {"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
85                {"python-path", required_argument, 0, LONG_ARGS_PYTHONPATH},
86                {"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
87#ifdef UWSGI_INI
88                {"ini", required_argument, 0, LONG_ARGS_INI},
89                {"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
90#endif
91#ifdef UWSGI_PASTE
92                {"paste", required_argument, 0, LONG_ARGS_PASTE},
93#endif
94#ifdef UWSGI_LDAP
95                {"ldap", required_argument, 0, LONG_ARGS_LDAP},
96                {"ldap-schema", no_argument, 0, LONG_ARGS_LDAP_SCHEMA},
97                {"ldap-schema-ldif", no_argument, 0, LONG_ARGS_LDAP_SCHEMA_LDIF},
98#endif
99                {"no-server", no_argument, &uwsgi.no_server, 1},
100                {"no-defer-accept", no_argument, &uwsgi.no_defer_accept, 1},
101                {"limit-as", required_argument, 0, LONG_ARGS_LIMIT_AS},
102                {"limit-post", required_argument, 0, LONG_ARGS_LIMIT_POST},
103                {"no-orphans", no_argument, &uwsgi.no_orphans, 1},
104                {"prio", required_argument, 0, LONG_ARGS_PRIO},
105                {"post-buffering", required_argument, 0, LONG_ARGS_POST_BUFFERING},
106                {"post-buffering-bufsize", required_argument, 0, LONG_ARGS_POST_BUFFERING_SIZE},
107                {"ignore-script-name", no_argument, &uwsgi.ignore_script_name, 1},
108#ifdef UWSGI_UDP
109                {"udp", required_argument, 0, LONG_ARGS_UDP},
110#endif
111#ifdef UWSGI_MULTICAST
112                {"multicast", required_argument, 0, LONG_ARGS_MULTICAST},
113#endif
114#ifdef UWSGI_SNMP
115                {"snmp", no_argument, 0, LONG_ARGS_SNMP},
116                {"snmp-community", required_argument, 0, LONG_ARGS_SNMP_COMMUNITY},
117#endif
118                {"check-interval", required_argument, 0, LONG_ARGS_CHECK_INTERVAL},
119#ifdef UWSGI_ERLANG
120                {"erlang", required_argument, 0, LONG_ARGS_ERLANG},
121                {"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
122#endif
123
124#ifdef UWSGI_NAGIOS
125                {"nagios", no_argument, &uwsgi.nagios, 1},
126#endif
127                {"binary-path", required_argument, 0, LONG_ARGS_BINARY_PATH},
128#ifdef UWSGI_PROXY
129                {"proxy", required_argument, 0, LONG_ARGS_PROXY},
130                {"proxy-node", required_argument, 0, LONG_ARGS_PROXY_NODE},
131                {"proxy-max-connections", required_argument, 0, LONG_ARGS_PROXY_MAX_CONNECTIONS},
132#endif
133                {"wsgi-file", required_argument, 0, LONG_ARGS_WSGI_FILE},
134                {"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
135#ifdef UWSGI_ASYNC
136                {"async", required_argument, 0, LONG_ARGS_ASYNC},
137#endif
138#ifdef UWSGI_STACKLESS
139                {"stackless", no_argument, &uwsgi.stackless, 1},
140#endif
141#ifdef UWSGI_UGREEN
142                {"ugreen", no_argument, &uwsgi.ugreen, 1},
143                {"ugreen-stacksize", required_argument, 0, LONG_ARGS_UGREEN_PAGES},
144#endif
145                UWSGI_PLUGIN_LONGOPT_PSGI
146                UWSGI_PLUGIN_LONGOPT_LUA
147                UWSGI_PLUGIN_LONGOPT_RACK
148                {"logto", required_argument, 0, LONG_ARGS_LOGTO},
149                {"logdate", no_argument, &uwsgi.logdate, 1},
150                {"chdir", required_argument, 0, LONG_ARGS_CHDIR},
151                {"chdir2", required_argument, 0, LONG_ARGS_CHDIR2},
152                {"grunt", no_argument, &uwsgi.grunt, 1},
153                {"no-site", no_argument, &Py_NoSiteFlag, 1},
154                {"vhost", no_argument, &uwsgi.vhost, 1},
155#ifdef UWSGI_ROUTING
156                {"routing", no_argument, &uwsgi.routing, 1},
157#endif
158
159#ifdef UWSGI_HTTP
160                {"http", required_argument, 0, LONG_ARGS_HTTP},
161                {"http-only", no_argument, &uwsgi.http_only, 1},
162                {"http-var", required_argument, 0, LONG_ARGS_HTTP_VAR},
163#endif
164                {"catch-exceptions", no_argument, &uwsgi.catch_exceptions, 1},
165                {"mode", required_argument, 0, LONG_ARGS_MODE},
166                {"env", required_argument, 0, LONG_ARGS_ENV},
167                {"vacuum", no_argument, &uwsgi.vacuum, 1},
168                {"ping", required_argument, 0, LONG_ARGS_PING},
169                {"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
170                {"version", no_argument, 0, LONG_ARGS_VERSION},
171                {0, 0, 0, 0}
172        };
173
174void ping(struct uwsgi_server *uwsgi) {
175
176        struct uwsgi_header uh;
177        struct pollfd uwsgi_poll;
178       
179        // use a 3 secs timeout by default
180        if (!uwsgi->ping_timeout) uwsgi->ping_timeout = 3 ;
181
182        uwsgi_poll.fd = uwsgi_connect(uwsgi->ping, uwsgi->ping_timeout);
183        if (uwsgi_poll.fd < 0) {
184                exit(1);
185        }
186
187        uh.modifier1 = UWSGI_MODIFIER_PING;
188        uh.pktsize = 0;
189        uh.modifier2 = 0;
190        if (write(uwsgi_poll.fd, &uh, 4) != 4) {
191                uwsgi_error("write()");
192                exit(2);
193        }
194        uwsgi_poll.events = POLLIN;
195        if (!uwsgi_parse_response(&uwsgi_poll, uwsgi->ping_timeout, &uh, NULL)) {
196                exit(1);
197        }
198        else {
199                if (uh.pktsize > 0) {
200                        exit(2);
201                }
202                else {
203                        exit(0);
204                }
205        }
206
207}
208
209
210int find_worker_id(pid_t pid) {
211        int i;
212        for (i = 1; i <= uwsgi.numproc; i++) {
213                /* uwsgi_log("%d of %d\n", pid, uwsgi.workers[i].pid); */
214                if (uwsgi.workers[i].pid == pid)
215                        return i;
216        }
217
218        return -1;
219}
220
221
222PyMethodDef null_methods[] = {
223        {NULL, NULL},
224};
225
226struct uwsgi_app *wi;
227
228void warn_pipe() {
229        uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd !!!\n");
230}
231
232void gracefully_kill() {
233        uwsgi_log("Gracefully killing worker %d...\n", uwsgi.mypid);
234        if (UWSGI_IS_IN_REQUEST) {
235                uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
236        }
237        else {
238                reload_me();
239        }
240}
241
242void reload_me() {
243        exit(UWSGI_RELOAD_CODE);
244}
245
246void end_me() {
247        exit(UWSGI_END_CODE);
248}
249
250void goodbye_cruel_world() {
251        uwsgi_log("...The work of process %d is done. Seeya!\n", getpid());
252        exit(0);
253}
254
255void kill_them_all() {
256        int i;
257        uwsgi.to_hell = 1;
258        uwsgi_log("SIGINT/SIGQUIT received...killing workers...\n");
259        for (i = 1; i <= uwsgi.numproc; i++) {
260                kill(uwsgi.workers[i].pid, SIGINT);
261        }
262}
263
264void grace_them_all() {
265        int i;
266        uwsgi.to_heaven = 1;
267        uwsgi_log("...gracefully killing workers...\n");
268        for (i = 1; i <= uwsgi.numproc; i++) {
269                kill(uwsgi.workers[i].pid, SIGHUP);
270        }
271}
272
273void reap_them_all() {
274        int i;
275        uwsgi.to_heaven = 1;
276        uwsgi_log("...brutally killing workers...\n");
277        for (i = 1; i <= uwsgi.numproc; i++) {
278                kill(uwsgi.workers[i].pid, SIGTERM);
279        }
280}
281
282void harakiri() {
283
284        PyThreadState *_myself;
285
286        PyGILState_Ensure();
287        _myself = PyThreadState_Get();
288        if (wi) {
289                uwsgi_log("\nF*CK !!! i must kill myself (pid: %d app_id: %d) wi: %p wi->wsgi_harakiri: %p thread_state: %p frame: %p...\n", uwsgi.mypid, uwsgi.wsgi_req->app_id, wi, wi->wsgi_harakiri, _myself, _myself->frame);
290
291/*
292                // NEED TO FIND A SAFER WAY !!!
293                if (wi->wsgi_harakiri) {
294                        PyEval_CallObject(wi->wsgi_harakiri, wi->wsgi_args);
295                        if (PyErr_Occurred()) {
296                                PyErr_Print();
297                        }
298                }
299*/
300        }
301        else {
302                uwsgi_log("\nF*CK !!! i must kill myself (pid: %d app_id: %d) thread_state: %p frame: %p...\n", uwsgi.mypid, uwsgi.wsgi_req->app_id, _myself, _myself->frame);
303        }
304
305        uwsgi_log("*** if you want your workers to be automatically respawned consider enabling the uWSGI master process ***\n");
306
307        Py_FatalError("HARAKIRI !\n");
308}
309
310void stats() {
311        // fix this for better logging (this cause races)
312        struct uwsgi_app *ua = NULL;
313        int i;
314
315        uwsgi_log("*** pid %d stats ***\n", getpid());
316        uwsgi_log("\ttotal requests: %llu\n", uwsgi.workers[0].requests);
317        for (i = 0; i < uwsgi.wsgi_cnt; i++) {
318                ua = &uwsgi.wsgi_apps[i];
319                if (ua) {
320                        uwsgi_log("\tapp %d requests: %d\n", i, ua->requests);
321                }
322        }
323        uwsgi_log("\n");
324}
325
326PyObject *wsgi_spitout;
327
328PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
329PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
330
331#ifdef UWSGI_ASYNC
332PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
333PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
334#endif
335
336
337// process manager is now (20090725) available on Unbit
338pid_t masterpid;
339pid_t diedpid;
340int waitpid_status;
341struct timeval last_respawn;
342time_t respawn_delta;
343
344
345int unconfigured_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
346        uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh.modifier1);
347        return -1;
348}
349
350static void unconfigured_after_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
351        return;
352}
353
354static void vacuum(void) {
355
356        struct sockaddr_un sa;
357        socklen_t sa_len = sizeof(struct sockaddr_un);
358
359        if (uwsgi.vacuum) {
360                if (getpid() == masterpid) {
361                        if (chdir(uwsgi.cwd)) {
362                                uwsgi_error("chdir()");
363                        }
364                        memset(&sa, 0, sa_len);
365                        if (!getsockname(uwsgi.serverfd, (struct sockaddr*)&sa, &sa_len)) {
366                                if (sa.sun_family == AF_UNIX) {
367                                        if (unlink(sa.sun_path)) {
368                                                uwsgi_error("unlink()");
369                                        }
370                                        else {
371                                                uwsgi_log("VACUUM: unix socket removed.\n");
372                                        }
373                                }
374                        }
375                        if (uwsgi.pidfile && !uwsgi.uid) {
376                                if (unlink(uwsgi.pidfile)) {
377                                        uwsgi_error("unlink()");
378                                }
379                                else {
380                                        uwsgi_log("VACUUM: pidfile removed.\n");
381                                }
382                        }
383                }
384        }
385}
386
387int main(int argc, char *argv[], char *envp[]) {
388
389        uint64_t master_cycles = 0;
390        struct timeval check_interval = {.tv_sec = 1,.tv_usec = 0 };
391
392        int i;
393
394        int rlen;
395
396        int uwsgi_will_starts = 0;
397
398#ifdef UWSGI_ASYNC
399        int current_async_timeout = 0;
400#endif
401
402
403#ifdef UWSGI_UDP
404        struct pollfd uwsgi_poll;
405        struct sockaddr_in udp_client;
406        socklen_t udp_len;
407        char udp_client_addr[16];
408#endif
409
410        pid_t pid;
411
412        FILE *pidfile;
413
414        int working_workers = 0;
415        int blocking_workers = 0;
416
417        int ready_to_reload = 0;
418        int ready_to_die = 0;
419
420        char *env_reloads;
421        unsigned int reloads = 0;
422        char env_reload_buf[11];
423
424
425#ifdef UNBIT
426        //struct uidsec_struct us;
427#endif
428
429        int socket_type = 0;
430        socklen_t socket_type_len;
431
432        /* anti signal bombing */
433        signal(SIGHUP, SIG_IGN);
434        signal(SIGTERM, SIG_IGN);
435
436        // initialize masterpid with a default value
437        masterpid = getpid();
438
439        memset(&uwsgi, 0, sizeof(struct uwsgi_server));
440        uwsgi.cwd = uwsgi_get_cwd();
441
442        atexit(vacuum);
443
444
445#ifdef UWSGI_DEBUG
446        /* get system information */
447        struct utsname uuts;
448        if (uname(&uuts)) {
449                uwsgi_error("uname()");
450        }
451        else {
452                uwsgi_log("SYSNAME: %s\nNODENAME: %s\nRELEASE: %s\nVERSION: %s\nMACHINE: %s\n",
453                        uuts.sysname,
454                        uuts.nodename,
455                        uuts.release,
456                        uuts.version,
457                        uuts.machine);
458        }
459#endif
460       
461
462        /* generic shared area */
463        uwsgi.shared = (struct uwsgi_shared *) mmap(NULL, sizeof(struct uwsgi_shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
464        if (!uwsgi.shared) {
465                uwsgi_error("mmap()");
466                exit(1);
467        }
468        memset(uwsgi.shared, 0, sizeof(struct uwsgi_shared));
469
470        for (i = 0; i <= 0xFF; i++) {
471                uwsgi.shared->hooks[i] = unconfigured_hook;
472                uwsgi.shared->after_hooks[i] = unconfigured_after_hook;
473        }
474
475        uwsgi.wsgi_cnt = 1;
476        uwsgi.default_app = -1;
477
478        uwsgi.buffer_size = 4096;
479        uwsgi.numproc = 1;
480
481        uwsgi.async = 1;
482        uwsgi.listen_queue = 64;
483
484        uwsgi.max_vars = MAX_VARS;
485        uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
486
487        uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
488        uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
489
490        int option_index = 0;
491
492
493        gettimeofday(&uwsgi.start_tv, NULL);
494
495        setlinebuf(stdout);
496
497        uwsgi.rl.rlim_cur = 0;
498        uwsgi.rl.rlim_max = 0;
499
500
501        env_reloads = getenv("UWSGI_RELOADS");
502        if (env_reloads) {
503                // convert env value to int
504                reloads = atoi(env_reloads);
505                reloads++;
506                // convert reloads to string
507                rlen = snprintf(env_reload_buf, 10, "%u", reloads);
508                if (rlen > 0) {
509                        env_reload_buf[rlen] = 0;
510                        if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
511                                uwsgi_error("setenv()");
512                        }
513                }
514        }
515        else {
516                if (setenv("UWSGI_RELOADS", "0", 1)) {
517                        uwsgi_error("setenv()");
518                }
519        }
520
521        socket_type_len = sizeof(int);
522        if (!getsockopt(3, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) {
523                if (socket_type == SOCK_STREAM && reloads > 0) {
524                        uwsgi_log("...fd 3 is a socket, i suppose this is a graceful reload of uWSGI, i will try to do my best...\n");
525                        uwsgi.is_a_reload = 1;
526#ifdef UNBIT
527                        /* discard the 3'th fd as we will use the fd 0 */
528                        close(3);
529#else
530                        uwsgi.serverfd = 3;
531#endif
532                }
533        }
534
535        uwsgi.binary_path = argv[0];
536
537        while ((i = getopt_long(argc, argv, "s:p:t:x:d:l:O:v:b:mcaCTPiMhrR:z:w:j:H:A:Q:L", long_options, &option_index)) != -1) {
538                manage_opt(i, optarg);
539        }
540
541        if (optind < argc) {
542                char *lazy = argv[optind];
543                char *qc = strchr(lazy, ':');
544                if (qc) {
545                        qc[0] = 0 ;
546                        uwsgi.callable = qc + 1;
547                }
548                if (!strcmp(lazy+strlen(lazy)-3, ".py")) {
549                        uwsgi.file_config = lazy;
550                }
551        }
552
553#ifdef UWSGI_XML
554        if (uwsgi.xml_config != NULL) {
555                uwsgi_xml_config(uwsgi.wsgi_req, long_options);
556        }
557#endif
558#ifdef UWSGI_INI
559        if (uwsgi.ini != NULL) {
560                uwsgi_ini_config(uwsgi.ini, long_options);
561        }
562#endif
563#ifdef UWSGI_LDAP
564        if (uwsgi.ldap != NULL) {
565                uwsgi_ldap_config(&uwsgi, long_options);
566        }
567#endif
568
569//parse environ
570
571        parse_sys_envs(environ, long_options);
572
573        if (uwsgi.ping) {
574                ping(&uwsgi);
575        }
576
577        if (uwsgi.binary_path == argv[0]) {
578                uwsgi.binary_path = malloc(strlen(argv[0]) + 1);
579                if (uwsgi.binary_path == NULL) {
580                        uwsgi_error("malloc()");
581                        exit(1);
582                }
583                memcpy(uwsgi.binary_path, argv[0], strlen(argv[0]) + 1);
584        }
585
586        if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
587                if (uwsgi.test_module == NULL) {
588                        uwsgi_log("*** Starting uWSGI %s (%dbit) on [%.*s] ***\n", UWSGI_VERSION, (int) (sizeof(void *)) * 8, 24, ctime((const time_t *) &uwsgi.start_tv.tv_sec));
589                }
590        }
591        else {
592                uwsgi_log("*** Starting uWSGI %s (CGI mode) (%dbit) on [%.*s] ***\n", UWSGI_VERSION, (int) (sizeof(void *)) * 8, 24, ctime((const time_t *) &uwsgi.start_tv.tv_sec));
593        }
594
595#ifdef UWSGI_DEBUG
596        uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, plese disable DEBUG in uwsgiconfig.py and recompile it ***\n***\n");
597#endif
598
599        uwsgi_log("compiled with version: %s\n", __VERSION__);
600
601#ifdef __BIG_ENDIAN__
602        uwsgi_log("*** big endian arch detected ***\n");
603#endif
604
605#ifdef PYTHREE
606        uwsgi_log("*** Warning Python3.x support is experimental, do not use it in production environment ***\n");
607#endif
608
609        uwsgi_log("Python version: %s\n", Py_GetVersion());
610
611        if (uwsgi.pidfile && !uwsgi.is_a_reload) {
612                uwsgi_log( "writing pidfile to %s\n", uwsgi.pidfile);
613                pidfile = fopen(uwsgi.pidfile, "w");
614                if (!pidfile) {
615                        uwsgi_error("fopen");
616                        exit(1);
617                }
618                if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
619                        uwsgi_log( "could not write pidfile.\n");
620                }
621                fclose(pidfile);
622        }
623
624
625        uwsgi_as_root();
626
627        if (!uwsgi.master_process) {
628                uwsgi_log(" *** WARNING: you are running uWSGI without its master process manager ***\n");
629        }
630
631#ifndef __OpenBSD__
632
633        if (uwsgi.rl.rlim_max > 0) {
634                uwsgi_log("limiting address space of processes...\n");
635                if (setrlimit(RLIMIT_AS, &uwsgi.rl)) {
636                        uwsgi_error("setrlimit()");
637                }
638        }
639
640        if (uwsgi.prio != 0) {
641                if (setpriority(PRIO_PROCESS, 0, uwsgi.prio)) {
642                        uwsgi_error("setpriority()");
643                }
644                else {
645                        uwsgi_log("scheduler priority set to %d\n", uwsgi.prio);
646                }
647        }
648       
649
650        if (!getrlimit(RLIMIT_AS, &uwsgi.rl)) {
651                // check for overflow
652                if (uwsgi.rl.rlim_max != RLIM_INFINITY) {
653                        uwsgi_log("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);
654                }
655        }
656#endif
657
658        uwsgi.page_size = getpagesize();
659        uwsgi_log("your memory page size is %d bytes\n", uwsgi.page_size);
660
661        if (uwsgi.buffer_size > 65536) {
662                uwsgi_log("invalid buffer size.\n");
663                exit(1);
664        }
665
666        sanitize_args(&uwsgi);
667
668#ifdef UWSGI_HTTP
669        if (uwsgi.http && !uwsgi.is_a_reload) {
670                char *tcp_port = strchr(uwsgi.http, ':');
671                if (tcp_port) {
672                        uwsgi.http_server_port = tcp_port+1;
673                        uwsgi.http_fd = bind_to_tcp(uwsgi.http, uwsgi.listen_queue, tcp_port);
674#ifdef UWSGI_DEBUG
675                        uwsgi_debug("HTTP FD: %d\n", uwsgi.http_fd);
676#endif
677                }
678                else {
679                        uwsgi_log("invalid http address.\n");
680                        exit(1);
681                }
682
683                if (uwsgi.http_fd < 0) {
684                        uwsgi_log("unable to create http server socket.\n");
685                        exit(1);
686                }
687
688                if (!uwsgi.socket_name) {
689                        uwsgi.socket_name = malloc(64);
690                        if (!uwsgi.socket_name) {
691                                uwsgi_error("malloc()");
692                                exit(1);
693                        }
694
695                        snprintf(uwsgi.socket_name, 64, "%d_%d.sock", (int) time(NULL), (int) getpid());
696                        uwsgi_log("using %s as uwsgi protocol socket\n", uwsgi.socket_name);
697
698                }
699
700
701                if (uwsgi.http_only) {
702                        http_loop(&uwsgi);
703                        // never here
704                        exit(1);
705                }
706
707                pid_t http_pid = fork();
708
709                if (http_pid > 0) {
710                        masterpid = http_pid;
711                        http_loop(&uwsgi);
712                        // never here
713                        exit(1);
714                }
715                else if (http_pid < 0) {
716                        uwsgi_error("fork()");
717                        exit(1);
718                }
719
720                if (uwsgi.pidfile && !uwsgi.is_a_reload) {
721                        uwsgi_log( "updating pidfile with pid %d\n", (int) getpid());
722                        pidfile = fopen(uwsgi.pidfile, "w");
723                        if (!pidfile) {
724                                uwsgi_error("fopen");
725                                exit(1);
726                        }
727                        if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
728                                uwsgi_log( "could not update pidfile.\n");
729                        }
730                        fclose(pidfile);
731                }
732
733                close(uwsgi.http_fd);
734        }
735#endif
736
737       
738        if (uwsgi.async > 1) {
739                if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
740                        if (uwsgi.rl.rlim_cur < uwsgi.async) {
741                                uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.rl.rlim_cur);
742                                if (uwsgi.rl.rlim_cur < uwsgi.rl.rlim_max && uwsgi.rl.rlim_max > uwsgi.async) {
743                                        unsigned long tmp_nofile = (unsigned long) uwsgi.rl.rlim_cur ;
744                                        uwsgi.rl.rlim_cur = uwsgi.async;
745                                        if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
746                                                uwsgi_log("max open files limit reset to %lu\n", (unsigned long) uwsgi.rl.rlim_cur);
747                                                uwsgi.async = uwsgi.rl.rlim_cur;
748                                        }
749                                        else {
750                                                uwsgi.async = (int) tmp_nofile ;
751                                        }
752                                }
753                                else {
754                                        uwsgi.async = uwsgi.rl.rlim_cur;
755                                }
756
757                                uwsgi_log("- async cores set to %d -\n", uwsgi.async);
758                        }
759                }
760        }
761
762        // allocate more wsgi_req for async mode
763        uwsgi.wsgi_requests = malloc(sizeof(struct wsgi_request) * uwsgi.async);
764        if (uwsgi.wsgi_requests == NULL) {
765                uwsgi_log("unable to allocate memory for requests.\n");
766                exit(1);
767        }
768        memset(uwsgi.wsgi_requests, 0, sizeof(struct wsgi_request) * uwsgi.async);
769
770        uwsgi.async_buf = malloc( sizeof(char *) * uwsgi.async);
771        if (!uwsgi.async_buf) {
772                uwsgi_error("malloc()");
773                exit(1);
774        }
775
776        if (uwsgi.post_buffering > 0) {
777                uwsgi.async_post_buf = malloc( sizeof(char *) * uwsgi.async);
778                if (!uwsgi.async_post_buf) {
779                        uwsgi_error("malloc()");
780                        exit(1);
781                }
782
783                if (!uwsgi.post_buffering_bufsize) {
784                        uwsgi.post_buffering_bufsize = 8192 ;
785                }
786        }
787
788        for(i=0;i<uwsgi.async;i++) {
789                uwsgi.async_buf[i] = malloc(uwsgi.buffer_size);
790                if (!uwsgi.async_buf[i]) {
791                        uwsgi_error("malloc()");
792                        exit(1);
793                }
794                if (uwsgi.post_buffering > 0) {
795                        uwsgi.async_post_buf[i] = malloc(uwsgi.post_buffering_bufsize);
796                        if (!uwsgi.async_post_buf[i]) {
797                                uwsgi_error("malloc()");
798                                exit(1);
799                        }
800                }
801        }
802       
803
804        // by default set wsgi_req to the first slot
805        uwsgi.wsgi_req = uwsgi.wsgi_requests ;
806
807        uwsgi_log("allocated %llu bytes (%llu KB) for %d request's buffer.\n", (uint64_t) (sizeof(struct wsgi_request) * uwsgi.async),
808                                                                 (uint64_t)( (sizeof(struct wsgi_request) * uwsgi.async ) / 1024),
809                                                                 uwsgi.async);
810
811        if (uwsgi.pyhome != NULL) {
812                uwsgi_log("Setting PythonHome to %s...\n", uwsgi.pyhome);
813#ifdef PYTHREE
814                wchar_t *wpyhome;
815                wpyhome = malloc((sizeof(wchar_t) * strlen(uwsgi.pyhome)) + 2);
816                if (!wpyhome) {
817                        uwsgi_error("malloc()");
818                        exit(1);
819                }
820                mbstowcs(wpyhome, uwsgi.pyhome, strlen(uwsgi.pyhome));
821                Py_SetPythonHome(wpyhome);
822                free(wpyhome);
823#else
824                Py_SetPythonHome(uwsgi.pyhome);
825#endif
826        }
827
828
829
830
831#ifdef PYTHREE
832        wchar_t pname[6];
833        mbstowcs(pname, "uWSGI", 6);
834        Py_SetProgramName(pname);
835#else
836        Py_SetProgramName("uWSGI");
837#endif
838
839        Py_Initialize();
840
841        init_pyargv(&uwsgi);
842
843        if (uwsgi.vhost) {
844                uwsgi_log("VirtualHosting mode enabled.\n");
845                uwsgi.wsgi_cnt = 0 ;
846        }
847
848        uwsgi.py_apps = PyDict_New();
849        if (!uwsgi.py_apps) {
850                PyErr_Print();
851                exit(1);
852        }
853
854
855        wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
856        uwsgi.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
857
858#ifdef UWSGI_EMBEDDED
859        if (uwsgi.sharedareasize > 0) {
860#ifndef __OpenBSD__
861                uwsgi.sharedareamutex = mmap(NULL, sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
862                if (!uwsgi.sharedareamutex) {
863                        uwsgi_error("mmap()");
864                        exit(1);
865                }
866#else
867                uwsgi_log("***WARNING*** the sharedarea on OpenBSD is not SMP-safe. Beware of race conditions !!!\n");
868#endif
869                uwsgi.sharedarea = mmap(NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
870                if (uwsgi.sharedarea) {
871                        uwsgi_log("shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea);
872
873#ifdef __APPLE__
874                        memset(uwsgi.sharedareamutex, 0, sizeof(OSSpinLock));
875#else
876#if !defined(__OpenBSD__) && !defined(__NetBSD__)
877                        if (pthread_mutexattr_init((pthread_mutexattr_t *) uwsgi.sharedareamutex)) {
878                                uwsgi_log("unable to allocate mutexattr structure\n");
879                                exit(1);
880                        }
881                        if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) uwsgi.sharedareamutex, PTHREAD_PROCESS_SHARED)) {
882                                uwsgi_log("unable to share mutex\n");
883                                exit(1);
884                        }
885                        if (pthread_mutex_init((pthread_mutex_t *) uwsgi.sharedareamutex + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) uwsgi.sharedareamutex)) {
886                                uwsgi_log("unable to initialize mutex\n");
887                                exit(1);
888                        }
889#endif
890#endif
891
892                }
893                else {
894                        uwsgi_error("mmap()");
895                        exit(1);
896                }
897
898        }
899
900        init_uwsgi_embedded_module();
901#endif
902
903
904
905        Py_OptimizeFlag = uwsgi.py_optimize;
906
907        uwsgi.main_thread = PyThreadState_Get();
908
909
910#ifdef UWSGI_NAGIOS
911        if (uwsgi.nagios) {
912                nagios(&uwsgi);
913                // never here
914        }
915#endif
916
917#ifdef UWSGI_UGREEN
918        if (uwsgi.ugreen) {
919                u_green_init(&uwsgi);
920        }
921#endif
922
923#ifdef UWSGI_THREADING
924        if (uwsgi.has_threads) {
925                PyEval_InitThreads();
926                uwsgi_log("threads support enabled\n");
927        }
928
929#endif
930
931        if (!uwsgi.no_server) {
932                if (uwsgi.socket_name != NULL && !uwsgi.is_a_reload) {
933                                char *tcp_port = strchr(uwsgi.socket_name, ':');
934                                if (tcp_port == NULL) {
935                                        uwsgi.serverfd = bind_to_unix(uwsgi.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
936                                }
937                                else {
938                                        uwsgi.serverfd = bind_to_tcp(uwsgi.socket_name, uwsgi.listen_queue, tcp_port);
939                                }
940
941                                if (uwsgi.serverfd < 0) {
942                                        uwsgi_log("unable to create the server socket.\n");
943                                        exit(1);
944                                }
945                }
946
947                socket_type_len = sizeof(int);
948                if (!getsockopt(uwsgi.serverfd, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) {
949                        uwsgi_will_starts = 1;
950                }
951                else {
952                        uwsgi.numproc = 0 ;
953                }
954
955#ifdef UWSGI_PROXY
956                if (uwsgi.proxy_socket_name) {
957                        uwsgi.shared->proxy_pid = proxy_start(uwsgi.master_process);
958                        uwsgi_will_starts = 1;
959                }
960#endif
961
962#ifdef UWSGI_UDP
963                if (uwsgi.udp_socket) {
964                        uwsgi_will_starts = 1;
965                }
966#endif
967
968
969        }
970
971
972        if (!uwsgi_will_starts && !uwsgi.no_server) {
973                uwsgi_log( "The -s/--socket option is missing and stdin is not a socket.\n");
974                exit(1);
975        }
976
977
978#ifdef UWSGI_DEBUG
979        int so_bufsize ;
980        socklen_t so_bufsize_len = sizeof(int) ;
981        if (getsockopt(uwsgi.serverfd, SOL_SOCKET, SO_RCVBUF,  &so_bufsize, &so_bufsize_len)) {
982                uwsgi_error("getsockopt()");
983        }
984        else {
985                uwsgi_debug("uwsgi socket SO_RCVBUF size: %d\n", so_bufsize);
986        }
987
988        so_bufsize_len = sizeof(int) ;
989        if (getsockopt(uwsgi.serverfd, SOL_SOCKET, SO_SNDBUF,  &so_bufsize, &so_bufsize_len)) {
990                uwsgi_error("getsockopt()");
991        }
992        else {
993                uwsgi_debug("uwsgi socket SO_SNDBUF size: %d\n", so_bufsize);
994        }
995#endif
996
997#ifdef UWSGI_ASYNC
998        if (uwsgi.async > 1) {
999#ifdef __linux__
1000                uwsgi.async_events = malloc( sizeof(struct epoll_event) * uwsgi.async ) ;
1001#elif defined(__sun__)
1002                uwsgi.async_events = malloc( sizeof(struct pollfd) * uwsgi.async ) ;
1003#else
1004                uwsgi.async_events = malloc( sizeof(struct kevent) * uwsgi.async ) ;
1005#endif
1006                if (!uwsgi.async_events) {
1007                        uwsgi_error("malloc()");
1008                        exit(1);
1009                }
1010        }
1011#endif
1012
1013
1014
1015
1016#ifndef UNBIT
1017        uwsgi_log( "your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
1018#endif
1019
1020
1021        if (uwsgi.single_interpreter == 1) {
1022                init_uwsgi_vars();
1023        }
1024
1025        memset(uwsgi.wsgi_apps, 0, sizeof(uwsgi.wsgi_apps));
1026
1027
1028
1029
1030
1031        /* shared area for workers */
1032        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);
1033        if (!uwsgi.workers) {
1034                uwsgi_error("mmap()");
1035                exit(1);
1036        }
1037        memset(uwsgi.workers, 0, sizeof(struct uwsgi_worker) * uwsgi.numproc + 1);
1038
1039        uwsgi.mypid = getpid();
1040        masterpid = uwsgi.mypid;
1041
1042
1043        /* save the masterpid */
1044        uwsgi.workers[0].pid = masterpid;
1045
1046        uwsgi_log( "initializing hooks...");
1047
1048        uwsgi.shared->hooks[0] = uwsgi_request_wsgi;
1049        uwsgi.shared->after_hooks[0] = uwsgi_after_request_wsgi;
1050
1051        uwsgi.shared->hooks[UWSGI_MODIFIER_ADMIN_REQUEST] = uwsgi_request_admin;        //10
1052#ifdef UWSGI_SPOOLER
1053        uwsgi.shared->hooks[UWSGI_MODIFIER_SPOOL_REQUEST] = uwsgi_request_spooler;      //17
1054#endif
1055        uwsgi.shared->hooks[UWSGI_MODIFIER_EVAL] = uwsgi_request_eval;  //22
1056        uwsgi.shared->hooks[UWSGI_MODIFIER_FASTFUNC] = uwsgi_request_fastfunc;  //26
1057
1058        uwsgi.shared->hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_request_wsgi;      // 30
1059        uwsgi.shared->after_hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_after_request_wsgi;  // 30
1060
1061        uwsgi.shared->hooks[UWSGI_MODIFIER_MESSAGE_MARSHAL] = uwsgi_request_marshal;    //33
1062        uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping;  //100
1063
1064        uwsgi_log( "done.\n");
1065
1066#ifdef UWSGI_EMBED_PLUGINS
1067        embed_plugins(&uwsgi);
1068#endif
1069
1070#ifdef UWSGI_ERLANG
1071        if (uwsgi.erlang_node) {
1072                uwsgi.erlang_nodes = 1;
1073                uwsgi.erlangfd = init_erlang(uwsgi.erlang_node, uwsgi.erlang_cookie);
1074        }
1075#endif
1076
1077#ifdef UWSGI_SNMP
1078        if (uwsgi.snmp) {
1079                snmp_init();
1080        }
1081#endif
1082
1083        if (uwsgi.wsgi_config != NULL) {
1084                uwsgi_wsgi_config(NULL);
1085        }
1086        else if (uwsgi.file_config != NULL) {
1087                uwsgi_wsgi_config(uwsgi.file_config);
1088        }
1089        else if (uwsgi.wsgi_file != NULL) {
1090                uwsgi_wsgi_file_config();
1091        }
1092#ifdef UWSGI_PASTE
1093        else if (uwsgi.paste != NULL) {
1094                uwsgi_paste_config();
1095        }
1096#endif
1097
1098// parse xml anyway
1099#ifdef UWSGI_XML
1100        if (uwsgi.xml_round2 && uwsgi.xml_config != NULL) {
1101                uwsgi_xml_config(uwsgi.wsgi_req, NULL);
1102        }
1103#endif
1104
1105
1106        if (uwsgi.test_module != NULL) {
1107                if (PyImport_ImportModule(uwsgi.test_module)) {
1108                        exit(0);
1109                }
1110                exit(1);
1111        }
1112
1113
1114        if (uwsgi.no_server) {
1115                uwsgi_log( "no-server mode requested. Goodbye.\n");
1116                exit(0);
1117        }
1118
1119// is this a proxy only worker ?
1120
1121        if (!uwsgi.master_process && uwsgi.numproc == 0) {
1122                exit(0);
1123        }
1124
1125        if (!uwsgi.single_interpreter) {
1126                uwsgi_log( "*** uWSGI is running in multiple interpreter mode ***\n");
1127        }
1128
1129        /* preforking() */
1130        if (uwsgi.master_process) {
1131                if (uwsgi.is_a_reload) {
1132                        uwsgi_log( "gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
1133                }
1134                else {
1135                        uwsgi_log( "spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
1136                }
1137        }
1138
1139#ifdef UWSGI_SPOOLER
1140        if (uwsgi.spool_dir != NULL && uwsgi.numproc > 0) {
1141                uwsgi.shared->spooler_pid = spooler_start(uwsgi.serverfd, uwsgi.embedded_dict);
1142        }
1143#endif
1144
1145#ifdef UWSGI_STACKLESS
1146        if (uwsgi.stackless) {
1147                stackless_init(&uwsgi);
1148        }
1149#endif
1150
1151#ifdef UWSGI_ROUTING
1152        routing_setup(&uwsgi);
1153#endif
1154
1155        if (!uwsgi.master_process) {
1156                if (uwsgi.numproc == 1) {
1157                        uwsgi_log( "spawned uWSGI worker 1 (and the only) (pid: %d)\n", masterpid);
1158                }
1159                else {
1160                        uwsgi_log( "spawned uWSGI worker 1 (pid: %d)\n", masterpid);
1161                }
1162                uwsgi.workers[1].pid = masterpid;
1163                uwsgi.workers[1].id = 1;
1164                uwsgi.workers[1].last_spawn = time(NULL);
1165                uwsgi.workers[1].manage_next_request = 1;
1166#ifdef UWSGI_THREADING
1167                uwsgi.workers[1].i_have_gil = 1;
1168#endif
1169                uwsgi.mywid = 1;
1170                gettimeofday(&last_respawn, NULL);
1171                respawn_delta = last_respawn.tv_sec;
1172        }
1173
1174
1175        for (i = 2 - uwsgi.master_process; i < uwsgi.numproc + 1; i++) {
1176                /* let the worker know his worker_id (wid) */
1177                pid = fork();
1178                if (pid == 0) {
1179                        uwsgi.mypid = getpid();
1180                        uwsgi.workers[i].pid = uwsgi.mypid;
1181                        uwsgi.workers[i].id = i;
1182                        uwsgi.workers[i].last_spawn = time(NULL);
1183                        uwsgi.workers[i].manage_next_request = 1;
1184#ifdef UWSGI_THREADING
1185                        uwsgi.workers[i].i_have_gil = 1;
1186#endif
1187                        uwsgi.mywid = i;
1188                        if (uwsgi.serverfd != 0 && uwsgi.master_process == 1) {
1189                                /* close STDIN for workers */
1190                                close(0);
1191                        }
1192                        break;
1193                }
1194                else if (pid < 1) {
1195                        uwsgi_error("fork()");
1196                        exit(1);
1197                }
1198                else {
1199                        uwsgi_log( "spawned uWSGI worker %d (pid: %d)\n", i, pid);
1200                        gettimeofday(&last_respawn, NULL);
1201                        respawn_delta = last_respawn.tv_sec;
1202                }
1203        }
1204
1205
1206        if (getpid() == masterpid && uwsgi.master_process == 1) {
1207                /* route signals to workers... */
1208                signal(SIGHUP, (void *) &grace_them_all);
1209                signal(SIGTERM, (void *) &reap_them_all);
1210                signal(SIGINT, (void *) &kill_them_all);
1211                signal(SIGQUIT, (void *) &kill_them_all);
1212                /* used only to avoid human-errors */
1213
1214                signal(SIGUSR1, (void *) &stats);
1215
1216                uwsgi.wsgi_req->buffer = uwsgi.async_buf[0];
1217#ifdef UWSGI_UDP
1218                if (uwsgi.udp_socket) {
1219                        uwsgi_poll.fd = bind_to_udp(uwsgi.udp_socket);
1220                        if (uwsgi_poll.fd < 0) {
1221                                uwsgi_log( "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n");
1222                        }
1223                        else {
1224                                uwsgi_log( "UDP server enabled.\n");
1225                                uwsgi_poll.events = POLLIN;
1226                        }
1227                }
1228#endif
1229
1230#ifdef UWSGI_SNMP
1231                if (uwsgi.snmp) {
1232                        if (uwsgi.snmp_community) {
1233                                if (strlen(uwsgi.snmp_community) > 72) {
1234                                        uwsgi_log( "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
1235                                        memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, 72);
1236                                }
1237                                else {
1238                                        memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
1239                                }
1240                        }
1241                        uwsgi_log( "filling SNMP table...");
1242
1243                        uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
1244                        uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
1245
1246                        uwsgi_log( "done\n");
1247
1248                }
1249#endif
1250
1251#ifdef UWSGI_UDP
1252                PyObject *udp_callable = PyDict_GetItemString(uwsgi.embedded_dict, "udp_callable");
1253                PyObject *udp_callable_args = NULL;
1254                if (udp_callable) {
1255                        udp_callable_args = PyTuple_New(3);
1256                }
1257#endif
1258                for (;;) {
1259                        if (ready_to_die >= uwsgi.numproc && uwsgi.to_hell) {
1260#ifdef UWSGI_SPOOLER
1261                                if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
1262                                        kill(uwsgi.shared->spooler_pid, SIGKILL);
1263                                        uwsgi_log( "killed the spooler with pid %d\n", uwsgi.shared->spooler_pid);
1264                                }
1265
1266#endif
1267
1268#ifdef UWSGI_PROXY
1269                                if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1270                                        kill(uwsgi.shared->proxy_pid, SIGKILL);
1271                                        uwsgi_log( "killed proxy with pid %d\n", uwsgi.shared->proxy_pid);
1272                                }
1273#endif
1274                                uwsgi_log( "goodbye to uWSGI.\n");
1275                                exit(0);
1276                        }
1277                        if (ready_to_reload >= uwsgi.numproc && uwsgi.to_heaven) {
1278#ifdef UWSGI_SPOOLER
1279                                if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
1280                                        kill(uwsgi.shared->spooler_pid, SIGKILL);
1281                                        uwsgi_log( "wait4() the spooler with pid %d...", uwsgi.shared->spooler_pid);
1282                                        diedpid = waitpid(uwsgi.shared->spooler_pid, &waitpid_status, 0);
1283                                        uwsgi_log( "done.");
1284                                }
1285#endif
1286
1287#ifdef UWSGI_PROXY
1288                                if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1289                                        kill(uwsgi.shared->proxy_pid, SIGKILL);
1290                                        uwsgi_log( "wait4() the proxy with pid %d...", uwsgi.shared->proxy_pid);
1291                                        diedpid = waitpid(uwsgi.shared->proxy_pid, &waitpid_status, 0);
1292                                        uwsgi_log( "done.");
1293                                }
1294#endif
1295                                uwsgi_log( "binary reloading uWSGI...\n");
1296                                if (chdir(uwsgi.cwd)) {
1297                                        uwsgi_error("chdir()");
1298                                        exit(1);
1299                                }
1300                                /* check fd table (a module can obviosly open some fd on initialization...) */
1301                                uwsgi_log( "closing all fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf(_SC_OPEN_MAX));
1302                                for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
1303                                        if (i == uwsgi.serverfd) {
1304                                                continue;
1305                                        }
1306                                        close(i);
1307                                }
1308                                if (uwsgi.serverfd != 3) {
1309                                        if (dup2(uwsgi.serverfd, 3) < 0) {
1310                                                uwsgi_error("dup2()");
1311                                                exit(1);
1312                                        }
1313                                }
1314                                uwsgi_log( "running %s\n", uwsgi.binary_path);
1315                                argv[0] = uwsgi.binary_path;
1316                                //strcpy (argv[0], uwsgi.binary_path);
1317                                execve(uwsgi.binary_path, argv, environ);
1318                                uwsgi_error("execve()");
1319                                // never here
1320                                exit(1);
1321                        }
1322
1323                        int master_has_children = 0;
1324
1325                        if (uwsgi.numproc > 0 ) {
1326                                master_has_children = 1;
1327                        }
1328#ifdef UWSGI_SPOOLER
1329                        if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
1330                                master_has_children = 1;
1331                        }
1332#endif
1333#ifdef UWSGI_PROXY
1334                        if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1335                                master_has_children = 1;
1336                        }
1337#endif
1338
1339                        if (!master_has_children) {
1340                                diedpid = 0;
1341                        }
1342                        else {
1343                                diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
1344                                if (diedpid == -1) {
1345                                        uwsgi_error("waitpid()");
1346                                        /* here is better to reload all the uWSGI stack */
1347                                        uwsgi_log( "something horrible happened...\n");
1348                                        reap_them_all();
1349                                        exit(1);
1350                                }
1351                        }
1352
1353                        if (diedpid == 0) {
1354                                /* PLEASE, do not run python threads in the master process, you can potentially destroy the world,
1355                                   we support this for hyperultramegagodprogrammer and systems
1356                                 */
1357#ifdef UWSGI_THREADING
1358                                if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
1359                                        uwsgi._save = PyEval_SaveThread();
1360                                        uwsgi.workers[uwsgi.mywid].i_have_gil = 0;
1361                                }
1362#endif
1363                                /* all processes ok, doing status scan after N seconds */
1364                                check_interval.tv_sec = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
1365                                if (!check_interval.tv_sec)
1366                                        check_interval.tv_sec = 1;
1367
1368#ifdef UWSGI_UDP
1369                                if (uwsgi.udp_socket && uwsgi_poll.fd >= 0) {
1370                                        rlen = poll(&uwsgi_poll, 1, check_interval.tv_sec * 1000);
1371                                        if (rlen < 0) {
1372                                                uwsgi_error("poll()");
1373                                        }
1374                                        else if (rlen > 0) {
1375                                                udp_len = sizeof(udp_client);
1376                                                rlen = recvfrom(uwsgi_poll.fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
1377                                                if (rlen < 0) {
1378                                                        uwsgi_error("recvfrom()");
1379                                                }
1380                                                else if (rlen > 0) {
1381                                                        memset(udp_client_addr, 0, 16);
1382                                                        if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
1383                                                                if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
1384                                                                }
1385#ifdef UWSGI_SNMP
1386                                                                else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
1387                                                                        manage_snmp(uwsgi_poll.fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
1388                                                                }
1389#endif
1390                                                                else {
1391                                                                        if (udp_callable && udp_callable_args) {
1392                                                                                PyTuple_SetItem(udp_callable_args, 0, PyString_FromString(udp_client_addr));
1393                                                                                PyTuple_SetItem(udp_callable_args, 1, PyInt_FromLong(ntohs(udp_client.sin_port)));
1394                                                                                PyTuple_SetItem(udp_callable_args, 2, PyString_FromStringAndSize(uwsgi.wsgi_req->buffer, rlen));
1395                                                                                PyObject *udp_response = python_call(udp_callable, udp_callable_args, 0);
1396                                                                                if (udp_response) {
1397                                                                                        Py_DECREF(udp_response);
1398                                                                                }
1399                                                                                if (PyErr_Occurred())
1400                                                                                        PyErr_Print();
1401                                                                        }
1402                                                                        else {
1403                                                                                // a simple udp logger
1404                                                                                uwsgi_log( "[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), rlen, uwsgi.wsgi_req->buffer);
1405                                                                        }
1406                                                                }
1407                                                        }
1408                                                        else {
1409                                                                uwsgi_error("inet_ntop()");
1410                                                        }
1411                                                }
1412                                        }
1413                                }
1414                                else {
1415#endif
1416                                        select(0, NULL, NULL, NULL, &check_interval);
1417#ifdef UWSGI_UDP
1418                                }
1419#endif
1420
1421                                // checking logsize
1422                                if (uwsgi.logfile) {
1423                                        uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
1424                                }
1425                               
1426                                master_cycles++;
1427                                working_workers = 0;
1428                                blocking_workers = 0;
1429#ifdef UWSGI_THREADING
1430                                if (uwsgi.has_threads && !uwsgi.workers[uwsgi.mywid].i_have_gil) {
1431                                        PyEval_RestoreThread(uwsgi._save);
1432                                        uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
1433                                }
1434#endif
1435                                check_interval.tv_sec = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
1436                                if (!check_interval.tv_sec)
1437                                        check_interval.tv_sec = 1;
1438                                for (i = 1; i <= uwsgi.numproc; i++) {
1439                                        /* first check for harakiri */
1440                                        if (uwsgi.workers[i].harakiri > 0) {
1441                                                if (uwsgi.workers[i].harakiri < time(NULL)) {
1442                                                        /* first try to invoke the harakiri() custom handler */
1443                                                        /* TODO */
1444                                                        /* then brutally kill the worker */
1445                                                        uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d) ***\n", i, uwsgi.workers[i].pid);
1446                                                        kill(uwsgi.workers[i].pid, SIGKILL);
1447                                                        // to avoid races
1448                                                        uwsgi.workers[i].harakiri = 0;
1449                                                }
1450                                        }
1451                                        /* load counters */
1452                                        if (uwsgi.workers[i].status & UWSGI_STATUS_IN_REQUEST)
1453                                                working_workers++;
1454
1455                                        if (uwsgi.workers[i].status & UWSGI_STATUS_BLOCKING)
1456                                                blocking_workers++;
1457
1458                                        uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
1459                                }
1460
1461                                // check for cluster nodes
1462                                for (i = 0; i < MAX_CLUSTER_NODES; i++) {
1463                                        struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
1464
1465                                        if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_FAILED) {
1466                                                // should i retry ?
1467                                                if (master_cycles % ucn->errors == 0) {
1468                                                        if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
1469                                                                ucn->status = UWSGI_NODE_OK;
1470                                                                uwsgi_log( "re-enabled cluster node %d/%s\n", i, ucn->name);
1471                                                        }
1472                                                        else {
1473                                                                ucn->errors++;
1474                                                        }
1475                                                }
1476                                        }
1477                                }
1478
1479                                continue;
1480
1481                        }
1482#ifdef UWSGI_SPOOLER
1483                        /* reload the spooler */
1484                        if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
1485                                if (diedpid == uwsgi.shared->spooler_pid) {
1486                                        uwsgi_log( "OOOPS the spooler is no more...trying respawn...\n");
1487                                        uwsgi.shared->spooler_pid = spooler_start(uwsgi.serverfd, uwsgi.embedded_dict);
1488                                        continue;
1489                                }
1490                        }
1491#endif
1492
1493#ifdef UWSGI_PROXY
1494                        /* reload the proxy (can be the only process running) */
1495                        if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1496                                if (diedpid == uwsgi.shared->proxy_pid) {
1497                                        if (WIFEXITED(waitpid_status)) {
1498                                                if (WEXITSTATUS(waitpid_status) != UWSGI_END_CODE) {
1499                                                        uwsgi_log( "OOOPS the proxy is no more...trying respawn...\n");
1500                                                        uwsgi.shared->spooler_pid = proxy_start(1);
1501                                                        continue;
1502                                                }
1503                                        }
1504                                }
1505                        }
1506#endif
1507                        // TODO rewrite without using exit code (targeted at 0.9.7)
1508
1509#ifdef __sun__
1510                        /* horrible hack... what the FU*K is doing Solaris ??? */
1511                        if (WIFSIGNALED(waitpid_status)) {
1512                                if (uwsgi.to_heaven) {
1513                                        ready_to_reload++;
1514                                        continue;
1515                                }
1516                                else if (uwsgi.to_hell) {
1517                                        ready_to_die++;
1518                                        continue;
1519                                }
1520                        }
1521#endif
1522                        /* check for reloading */
1523                        if (WIFEXITED(waitpid_status)) {
1524                                if (WEXITSTATUS(waitpid_status) == UWSGI_RELOAD_CODE && uwsgi.to_heaven) {
1525                                        ready_to_reload++;
1526                                        continue;
1527                                }
1528                                else if (WEXITSTATUS(waitpid_status) == UWSGI_END_CODE && uwsgi.to_hell) {
1529                                        ready_to_die++;
1530                                        continue;
1531                                }
1532                        }
1533
1534                        uwsgi_log( "DAMN ! process %d died :( trying respawn ...\n", diedpid);
1535                        gettimeofday(&last_respawn, NULL);
1536                        if (last_respawn.tv_sec == respawn_delta) {
1537                                uwsgi_log( "worker respawning too fast !!! i have to sleep a bit...\n");
1538                                /* TODO, user configurable fork throttler */
1539                                sleep(2);
1540                        }
1541                        gettimeofday(&last_respawn, NULL);
1542                        respawn_delta = last_respawn.tv_sec;
1543                        uwsgi.mywid = find_worker_id(diedpid);
1544                        pid = fork();
1545                        if (pid == 0) {
1546                                uwsgi.mypid = getpid();
1547                                uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
1548                                uwsgi.workers[uwsgi.mywid].harakiri = 0;
1549                                uwsgi.workers[uwsgi.mywid].requests = 0;
1550                                uwsgi.workers[uwsgi.mywid].failed_requests = 0;
1551                                uwsgi.workers[uwsgi.mywid].respawn_count++;
1552                                uwsgi.workers[uwsgi.mywid].last_spawn = time(NULL);
1553                                uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
1554                                uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
1555                                break;
1556                        }
1557                        else if (pid < 1) {
1558                                uwsgi_error("fork()");
1559                        }
1560                        else {
1561                                uwsgi_log( "Respawned uWSGI worker (new pid: %d)\n", pid);
1562#ifdef UWSGI_SPOOLER
1563                                if (uwsgi.mywid <= 0 && diedpid != uwsgi.shared->spooler_pid) {
1564#else
1565                                if (uwsgi.mywid <= 0) {
1566#endif
1567
1568#ifdef UWSGI_PROXY
1569                                        if (diedpid != uwsgi.shared->proxy_pid) {
1570#endif
1571                                                uwsgi_log( "warning the died pid was not in the workers list. Probably you hit a BUG of uWSGI\n");
1572#ifdef UWSGI_PROXY
1573                                        }
1574#endif
1575                                }
1576                        }
1577                }
1578        }
1579
1580        // reinitialize the random seed (thanks Jonas Borgström)
1581        PyObject *random_module = PyImport_ImportModule("random");
1582        if (random_module) {
1583                PyObject *random_dict = PyModule_GetDict(random_module);
1584                if (random_dict) {
1585                        PyObject *random_seed = PyDict_GetItemString(random_dict, "seed");
1586                        if (random_seed) {
1587                                PyObject *random_args = PyTuple_New(1);
1588                                // pass no args
1589                                PyTuple_SetItem(random_args, 0, Py_None);
1590                                PyEval_CallObject( random_seed, random_args );
1591                                if (PyErr_Occurred()) {
1592                                        PyErr_Print();
1593                                }
1594                        }
1595                }
1596        }
1597
1598
1599        // postpone the queue initialization as kevent do not pass kfd after fork()
1600#ifdef UWSGI_ASYNC
1601        if (uwsgi.async > 1) {
1602                uwsgi.async_queue = async_queue_init(uwsgi.serverfd);
1603                if (uwsgi.async_queue < 0) {
1604                        exit(1);
1605                }
1606        }
1607#endif
1608
1609
1610
1611        uwsgi.async_hvec = malloc((sizeof(struct iovec) * uwsgi.vec_size)*uwsgi.async);
1612        if (uwsgi.async_hvec == NULL) {
1613                uwsgi_log( "unable to allocate memory for iovec.\n");
1614                exit(1);
1615        }
1616
1617        if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) {
1618                signal(SIGALRM, (void *) &harakiri);
1619        }
1620
1621        /* gracefully reload */
1622        signal(SIGHUP, (void *) &gracefully_kill);
1623        /* close the process (useful for master INT) */
1624        signal(SIGINT, (void *) &end_me);
1625        /* brutally reload */
1626        signal(SIGTERM, (void *) &reload_me);
1627
1628
1629        signal(SIGUSR1, (void *) &stats);
1630
1631
1632        signal(SIGPIPE, (void *) &warn_pipe);
1633
1634// initialization done
1635
1636        if (uwsgi.chdir2) {
1637                if (chdir(uwsgi.chdir2)) {
1638                        uwsgi_error("chdir()");
1639                        exit(1);
1640                }
1641        }
1642
1643#ifdef __linux__
1644        if (uwsgi.master_process && uwsgi.no_orphans) {
1645                if (prctl(PR_SET_PDEATHSIG, SIGINT)) {
1646                        uwsgi_error("prctl()");
1647                }
1648        }
1649#endif
1650
1651
1652#ifdef UWSGI_ERLANG
1653        if (uwsgi.erlang_nodes > 0) {
1654                if (uwsgi.numproc <= uwsgi.erlang_nodes) {
1655                        uwsgi_log( "You do not have enough worker for Erlang. Please respawn with at least %d processes.\n", uwsgi.erlang_nodes + 1);
1656                }
1657                else if (uwsgi.mywid > (uwsgi.numproc - uwsgi.erlang_nodes)) {
1658                        uwsgi_log( "Erlang mode enabled for worker %d.\n", uwsgi.mywid);
1659                        erlang_loop(uwsgi.wsgi_req);
1660                        // NEVER HERE
1661                        exit(1);
1662                }
1663        }
1664        // close the erlang server fd for python workers
1665        close(uwsgi.erlangfd);
1666#endif
1667
1668#ifdef UWSGI_THREADING
1669        // release the GIL
1670        if (uwsgi.has_threads) {
1671                uwsgi._save = PyEval_SaveThread();
1672                uwsgi.workers[uwsgi.mywid].i_have_gil = 0;
1673        }
1674#endif
1675
1676
1677#ifdef UWSGI_ASYNC
1678        uwsgi.async_running = -1 ;
1679#endif
1680
1681#ifdef UWSGI_UGREEN
1682        if (uwsgi.ugreen) {
1683                u_green_loop(&uwsgi);
1684                // never here
1685        }
1686#endif
1687
1688#ifdef UWSGI_STACKLESS
1689        if (uwsgi.stackless) {
1690                stackless_loop(&uwsgi);
1691                // never here
1692        }
1693#endif
1694
1695        while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
1696
1697
1698#ifndef __linux__
1699                if (uwsgi.no_orphans && uwsgi.master_process) {
1700                        // am i a son of init ?
1701                        if (getppid() == 1) {
1702                                uwsgi_log("UAAAAAAH my parent died :( i will follow him...\n");
1703                                exit(1);
1704                        }
1705                }
1706#endif
1707
1708                // clear all status bits
1709                UWSGI_CLEAR_STATUS;
1710
1711#ifdef UWSGI_ASYNC
1712       
1713        if (uwsgi.async > 1) {
1714
1715                current_async_timeout = async_get_timeout(&uwsgi) ;
1716                uwsgi.async_nevents = async_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running, current_async_timeout);
1717                async_expire_timeouts(&uwsgi);
1718
1719                if (uwsgi.async_nevents < 0) {
1720                        continue;
1721                }
1722       
1723                for(i=0; i<uwsgi.async_nevents;i++) {
1724
1725                        if (uwsgi.async_events[i].ASYNC_FD == uwsgi.serverfd) {
1726
1727                                uwsgi.wsgi_req = find_first_available_wsgi_req(&uwsgi);
1728                                if (uwsgi.wsgi_req == NULL) {
1729                                        // async system is full !!!
1730                                        goto cycle;
1731                                }
1732
1733                                wsgi_req_setup(uwsgi.wsgi_req, ( (uint8_t *)uwsgi.wsgi_req - (uint8_t *)uwsgi.wsgi_requests)/sizeof(struct wsgi_request) );
1734
1735                                if (wsgi_req_accept(uwsgi.serverfd, uwsgi.wsgi_req)) {
1736                                        continue;
1737                                }
1738
1739                                if (wsgi_req_recv(uwsgi.wsgi_req)) {
1740                                        continue;
1741                                }
1742
1743                                if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
1744                                        goto reqclear;
1745                                }
1746
1747                        }
1748                        else {
1749                                uwsgi.wsgi_req = find_wsgi_req_by_fd(&uwsgi, uwsgi.async_events[i].ASYNC_FD, uwsgi.async_events[i].ASYNC_EV);
1750                                if (uwsgi.wsgi_req) {
1751                                        uwsgi.wsgi_req->async_status = UWSGI_AGAIN ;
1752                                        uwsgi.wsgi_req->async_waiting_fd = -1 ;
1753                                        uwsgi.wsgi_req->async_waiting_fd_monitored = 0 ;
1754                                }
1755
1756                                async_del(uwsgi.async_queue, uwsgi.async_events[i].ASYNC_FD, uwsgi.async_events[i].ASYNC_EV);
1757                        }
1758                }
1759
1760cycle:
1761                uwsgi.wsgi_req = async_loop(&uwsgi);
1762
1763                if (uwsgi.wsgi_req == NULL)
1764                        continue ;
1765                uwsgi.wsgi_req->async_status = UWSGI_OK ;
1766
1767        }
1768        else {
1769#endif
1770                wsgi_req_setup(uwsgi.wsgi_req, 0);
1771
1772                if (wsgi_req_accept(uwsgi.serverfd, uwsgi.wsgi_req)) {
1773                        continue;
1774                }
1775
1776                if (wsgi_req_recv(uwsgi.wsgi_req)) {
1777                        continue;
1778                }
1779
1780#ifdef UWSGI_ASYNC
1781        }
1782reqclear:
1783#endif
1784
1785
1786                uwsgi_close_request(&uwsgi, uwsgi.wsgi_req);
1787        }
1788
1789        if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
1790                reload_me();
1791        }
1792        else {
1793                goodbye_cruel_world();
1794        }
1795
1796        /* never here */
1797        return 0;
1798}
1799
1800void init_uwsgi_vars() {
1801
1802        int i;
1803        PyObject *pysys, *pysys_dict, *pypath;
1804
1805#ifdef UWSGI_MINTERPRETERS
1806        char venv_version[15] ;
1807        PyObject *site_module;
1808#endif
1809
1810        /* add cwd to pythonpath */
1811        pysys = PyImport_ImportModule("sys");
1812        if (!pysys) {
1813                PyErr_Print();
1814                exit(1);
1815        }
1816        pysys_dict = PyModule_GetDict(pysys);
1817        pypath = PyDict_GetItemString(pysys_dict, "path");
1818        if (!pypath) {
1819                PyErr_Print();
1820                exit(1);
1821        }
1822
1823#ifdef UWSGI_MINTERPRETERS
1824        // simulate a pythonhome directive
1825        if (uwsgi.wsgi_req->pyhome_len > 0) {
1826
1827                PyObject *venv_path = PyString_FromStringAndSize(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len) ;
1828
1829#ifdef UWSGI_DEBUG
1830                uwsgi_debug("setting dynamic virtualenv to %s\n", PyString_AsString(venv_path));
1831#endif
1832
1833                PyDict_SetItemString(pysys_dict, "prefix", venv_path);
1834                PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
1835
1836                venv_version[14] = 0 ;
1837                if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
1838                        return ;
1839                }
1840#ifdef PYTHREE
1841                venv_path = PyString_Concat( venv_path, PyString_FromString(venv_version) );
1842#else
1843                PyString_Concat( &venv_path, PyString_FromString(venv_version) );
1844#endif
1845
1846                if ( PyList_Insert(pypath, 0, venv_path) ) {
1847                        PyErr_Print();
1848                }
1849
1850                site_module = PyImport_ImportModule("site");
1851                if (site_module) {
1852                        PyImport_ReloadModule(site_module);
1853                }
1854
1855        }
1856#endif
1857
1858        if (PyList_Insert(pypath, 0, PyString_FromString(".")) != 0) {
1859                PyErr_Print();
1860        }
1861
1862        for (i = 0; i < uwsgi.python_path_cnt; i++) {
1863                if (PyList_Insert(pypath, 0, PyString_FromString(uwsgi.python_path[i])) != 0) {
1864                        PyErr_Print();
1865                }
1866                else {
1867                        uwsgi_log( "added %s to pythonpath.\n", uwsgi.python_path[i]);
1868                }
1869        }
1870
1871}
1872
1873int init_uwsgi_app(PyObject * force_wsgi_dict, PyObject * my_callable) {
1874        PyObject *wsgi_module, *wsgi_dict = NULL;
1875        PyObject *zero;
1876#ifdef UWSGI_PROFILER
1877        PyObject *pymain, *pycprof, *pycprof_dict;
1878#endif
1879        char tmpstring[256];
1880        int id;
1881#ifdef UWSGI_ASYNC
1882        int i;
1883#endif
1884
1885        struct uwsgi_app *wi;
1886
1887        memset(tmpstring, 0, 256);
1888
1889
1890        if (uwsgi.wsgi_req->wsgi_script_len == 0 && ((uwsgi.wsgi_req->wsgi_module_len == 0 || uwsgi.wsgi_req->wsgi_callable_len == 0) && uwsgi.wsgi_config == NULL && my_callable == NULL)) {
1891                uwsgi_log( "invalid application (%.*s). skip.\n", uwsgi.wsgi_req->script_name_len, uwsgi.wsgi_req->script_name);
1892                return -1;
1893        }
1894
1895        if (uwsgi.wsgi_config && uwsgi.wsgi_req->wsgi_callable_len == 0 && my_callable == NULL) {
1896                uwsgi_log( "invalid application (%.*s). skip.\n", uwsgi.wsgi_req->script_name_len, uwsgi.wsgi_req->script_name);
1897                return -1;
1898        }
1899
1900        if (uwsgi.wsgi_req->wsgi_script_len > 255 || uwsgi.wsgi_req->wsgi_module_len > 255 || uwsgi.wsgi_req->wsgi_callable_len > 255) {
1901                uwsgi_log( "invalid application's string size. skip.\n");
1902                return -1;
1903        }
1904
1905        id = uwsgi.wsgi_cnt;
1906
1907
1908        if (uwsgi.wsgi_req->script_name_len == 0) {
1909                uwsgi.wsgi_req->script_name = "";
1910                if (!uwsgi.vhost) {
1911                        id = 0;
1912                }
1913        }
1914        else if (uwsgi.wsgi_req->script_name_len == 1) {
1915                if (uwsgi.wsgi_req->script_name[0] == '/') {
1916                        if (!uwsgi.vhost) {
1917                                id = 0;
1918                        }
1919                }
1920        }
1921
1922
1923        if (uwsgi.vhost) {
1924                zero = PyString_FromStringAndSize(uwsgi.wsgi_req->host, uwsgi.wsgi_req->host_len);
1925#ifdef PYTHREE
1926                zero = PyString_Concat(zero, PyString_FromString("|"));
1927                zero = PyString_Concat(zero, PyString_FromStringAndSize(uwsgi.wsgi_req->script_name, uwsgi.wsgi_req->script_name_len));
1928#else
1929                PyString_Concat(&zero, PyString_FromString("|"));
1930                PyString_Concat(&zero, PyString_FromStringAndSize(uwsgi.wsgi_req->script_name, uwsgi.wsgi_req->script_name_len));
1931#endif
1932        }
1933        else {
1934                zero = PyString_FromStringAndSize(uwsgi.wsgi_req->script_name, uwsgi.wsgi_req->script_name_len);
1935        }
1936
1937        if (!zero) {
1938                Py_FatalError("cannot get mountpoint python object !\n");
1939        }
1940
1941        if (PyDict_GetItem(uwsgi.py_apps, zero) != NULL) {
1942                Py_DECREF(zero);
1943                uwsgi_log( "mountpoint %.*s already configured. skip.\n", uwsgi.wsgi_req->script_name_len, uwsgi.wsgi_req->script_name);
1944                return -1;
1945        }
1946
1947
1948        wi = &uwsgi.wsgi_apps[id];
1949
1950        memset(wi, 0, sizeof(struct uwsgi_app));
1951
1952        if (uwsgi.single_interpreter == 0) {
1953                wi->interpreter = Py_NewInterpreter();
1954                if (!wi->interpreter) {
1955                        uwsgi_log( "unable to initialize the new interpreter\n");
1956                        exit(1);
1957                }
1958                PyThreadState_Swap(wi->interpreter);
1959                init_pyargv(&uwsgi);
1960
1961#ifdef UWSGI_EMBEDDED
1962                // we need to inizialize an embedded module for every interpreter
1963                init_uwsgi_embedded_module();
1964#endif
1965                init_uwsgi_vars();
1966                uwsgi_log( "interpreter for app %d initialized.\n", id);
1967        }
1968
1969#ifdef UWSGI_PASTE
1970        if (uwsgi.paste) {
1971                wi->wsgi_callable = my_callable;
1972                Py_INCREF(my_callable);
1973        }
1974        else if (uwsgi.wsgi_file) {
1975#else
1976        if (uwsgi.wsgi_file) {
1977#endif
1978                wi->wsgi_callable = my_callable;
1979                Py_INCREF(my_callable);
1980        }
1981        else {
1982
1983                if (uwsgi.wsgi_config == NULL) {
1984                        if (uwsgi.wsgi_req->wsgi_script_len > 0) {
1985                                memcpy(tmpstring, uwsgi.wsgi_req->wsgi_script, uwsgi.wsgi_req->wsgi_script_len);
1986                                wsgi_module = PyImport_ImportModule(tmpstring);
1987                                if (!wsgi_module) {
1988                                        PyErr_Print();
1989                                        if (uwsgi.single_interpreter == 0) {
1990                                                Py_EndInterpreter(wi->interpreter);
1991                                                PyThreadState_Swap(uwsgi.main_thread);
1992                                        }
1993                                        return -1;
1994                                }
1995                                uwsgi.wsgi_req->wsgi_callable = "application";
1996                                uwsgi.wsgi_req->wsgi_callable_len = 11;
1997                        }
1998                        else {
1999                                memcpy(tmpstring, uwsgi.wsgi_req->wsgi_module, uwsgi.wsgi_req->wsgi_module_len);
2000                                wsgi_module = PyImport_ImportModule(tmpstring);
2001                                if (!wsgi_module) {
2002                                        PyErr_Print();
2003                                        if (uwsgi.single_interpreter == 0) {
2004                                                Py_EndInterpreter(wi->interpreter);
2005                                                PyThreadState_Swap(uwsgi.main_thread);
2006                                        }
2007                                        return -1;
2008                                }
2009                        }
2010
2011                        wsgi_dict = PyModule_GetDict(wsgi_module);
2012                        if (!wsgi_dict) {
2013                                PyErr_Print();
2014                                if (uwsgi.single_interpreter == 0) {
2015                                        Py_EndInterpreter(wi->interpreter);
2016                                        PyThreadState_Swap(uwsgi.main_thread);
2017                                }
2018                                return -1;
2019                        }
2020
2021                }
2022                else {
2023                        wsgi_dict = force_wsgi_dict;
2024                }
2025
2026
2027                memset(tmpstring, 0, 256);
2028                memcpy(tmpstring, uwsgi.wsgi_req->wsgi_callable, uwsgi.wsgi_req->wsgi_callable_len);
2029                if (my_callable) {
2030                        wi->wsgi_callable = my_callable;
2031                        Py_INCREF(my_callable);
2032                }
2033                else if (wsgi_dict) {
2034                        wi->wsgi_callable = PyDict_GetItemString(wsgi_dict, tmpstring);
2035                }
2036                else {
2037                        return -1;
2038                }
2039
2040        }
2041
2042        wi->wsgi_dict = wsgi_dict ;
2043
2044        if (!wi->wsgi_callable) {
2045                PyErr_Print();
2046                if (uwsgi.single_interpreter == 0) {
2047                        Py_EndInterpreter(wi->interpreter);
2048                        PyThreadState_Swap(uwsgi.main_thread);
2049                }
2050                return -1;
2051        }
2052
2053#ifdef UWSGI_ASYNC
2054        wi->wsgi_environ = malloc(sizeof(PyObject*)*uwsgi.async);
2055        if (!wi->wsgi_environ) {
2056                uwsgi_error("malloc()");
2057                if (uwsgi.single_interpreter == 0) {
2058                        Py_EndInterpreter(wi->interpreter);
2059                        PyThreadState_Swap(uwsgi.main_thread) ;
2060                }
2061                return -1 ;
2062        }
2063
2064        for(i=0;i<uwsgi.async;i++) {
2065                wi->wsgi_environ[i] = PyDict_New();
2066                // this will leak all the already allocated dictionary !!!
2067                if (!wi->wsgi_environ[i]) {
2068                        if (uwsgi.single_interpreter == 0) {
2069                                Py_EndInterpreter(wi->interpreter);
2070                                PyThreadState_Swap(uwsgi.main_thread) ;
2071                        }
2072                        return -1 ;
2073                }
2074        }
2075#else
2076        wi->wsgi_environ = PyDict_New();
2077        if (!wi->wsgi_environ) {
2078                PyErr_Print();
2079                if (uwsgi.single_interpreter == 0) {
2080                        Py_EndInterpreter(wi->interpreter);
2081                        PyThreadState_Swap(uwsgi.main_thread) ;
2082                }
2083                return -1 ;
2084        }
2085#endif
2086
2087
2088        if (wsgi_dict) {
2089                wi->wsgi_harakiri = PyDict_GetItemString(wsgi_dict, "harakiri");
2090                if (wi->wsgi_harakiri) {
2091                        uwsgi_log( "initialized Harakiri custom handler: %p.\n", wi->wsgi_harakiri);
2092                }
2093        }
2094
2095
2096
2097#ifdef UWSGI_PROFILER
2098        if (uwsgi.enable_profiler) {
2099                pymain = PyImport_AddModule("__main__");
2100                if (!pymain) {
2101                        PyErr_Print();
2102                        exit(1);
2103                }
2104                wi->pymain_dict = PyModule_GetDict(pymain);
2105                if (!wi->pymain_dict) {
2106                        PyErr_Print();
2107                        exit(1);
2108                }
2109                if (PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_application__%d", id), wi->wsgi_callable)) {
2110                        PyErr_Print();
2111                        exit(1);
2112                }
2113
2114                if (PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_spit__%d", id), wsgi_spitout)) {
2115                        PyErr_Print();
2116                        exit(1);
2117                }
2118
2119                pycprof = PyImport_ImportModule("cProfile");
2120                if (!pycprof) {
2121                        PyErr_Print();
2122                        uwsgi_log( "trying old profile module...\n");
2123                        pycprof = PyImport_ImportModule("profile");
2124                        if (!pycprof) {
2125                                PyErr_Print();
2126                                exit(1);
2127                        }
2128                }
2129
2130                pycprof_dict = PyModule_GetDict(pycprof);
2131                if (!pycprof_dict) {
2132                        PyErr_Print();
2133                        exit(1);
2134                }
2135                wi->wsgi_cprofile_run = PyDict_GetItemString(pycprof_dict, "run");
2136                if (!wi->wsgi_cprofile_run) {
2137                        PyErr_Print();
2138                        exit(1);
2139                }
2140
2141#ifdef UWSGI_ASYNC
2142                wi->wsgi_args = malloc(sizeof(PyObject*));
2143                if (!wi->wsgi_args) {
2144                        uwsgi_error("malloc()");
2145                        if (uwsgi.single_interpreter == 0) {
2146                                Py_EndInterpreter(wi->interpreter);
2147                                PyThreadState_Swap(uwsgi.main_thread) ;
2148                        }
2149                        return -1 ;
2150                }
2151                wi->wsgi_args[0] = PyTuple_New(1);
2152                if (PyTuple_SetItem(wi->wsgi_args[0], 0, PyString_FromFormat("uwsgi_out = uwsgi_application__%d(uwsgi_environ__%d,uwsgi_spit__%d)", id, id, id))) {
2153#else
2154                wi->wsgi_args = PyTuple_New(1);
2155                if (PyTuple_SetItem(wi->wsgi_args, 0, PyString_FromFormat("uwsgi_out = uwsgi_application__%d(uwsgi_environ__%d,uwsgi_spit__%d)", id, id, id))) {
2156#endif
2157                        PyErr_Print();
2158                        if (uwsgi.single_interpreter == 0) {
2159                                Py_EndInterpreter(wi->interpreter);
2160                                PyThreadState_Swap(uwsgi.main_thread);
2161                        }
2162                        return -1;
2163                }
2164        }
2165        else {
2166#endif
2167
2168#ifdef UWSGI_ASYNC
2169        wi->wsgi_args = malloc(sizeof(PyObject*)*uwsgi.async);
2170        if (!wi->wsgi_args) {
2171                uwsgi_error("malloc()");
2172                if (uwsgi.single_interpreter == 0) {
2173                        Py_EndInterpreter(wi->interpreter);
2174                        PyThreadState_Swap(uwsgi.main_thread) ;
2175                }
2176                return -1 ;
2177        }
2178
2179        for(i=0;i<uwsgi.async;i++) {
2180                wi->wsgi_args[i] = PyTuple_New(2);
2181                // this will leak all the already allocated dictionary !!!
2182                if (!wi->wsgi_args[i]) {
2183                        if (uwsgi.single_interpreter == 0) {
2184                                Py_EndInterpreter(wi->interpreter);
2185                                PyThreadState_Swap(uwsgi.main_thread) ;
2186                        }
2187                        return -1 ;
2188                }
2189                if (PyTuple_SetItem(wi->wsgi_args[i], 1, wsgi_spitout)) {
2190                        PyErr_Print();
2191                        if (uwsgi.single_interpreter == 0) {
2192                                Py_EndInterpreter(wi->interpreter);
2193                                PyThreadState_Swap(uwsgi.main_thread);
2194                        }
2195                        return -1;
2196                }
2197        }
2198#else
2199
2200                wi->wsgi_args = PyTuple_New(2);
2201                if (PyTuple_SetItem(wi->wsgi_args, 1, wsgi_spitout)) {
2202                        PyErr_Print();
2203                        if (uwsgi.single_interpreter == 0) {
2204                                Py_EndInterpreter(wi->interpreter);
2205                                PyThreadState_Swap(uwsgi.main_thread);
2206                        }
2207                        return -1;
2208                }
2209#endif
2210
2211#ifdef UWSGI_PROFILER
2212        }
2213#endif
2214
2215#ifdef UWSGI_SENDFILE
2216        // prepare sendfile()
2217        wi->wsgi_sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
2218#endif
2219
2220#ifdef UWSGI_ASYNC
2221        wi->wsgi_eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL);
2222        wi->wsgi_eventfd_write = PyCFunction_New(uwsgi_eventfd_write_method, NULL);
2223#endif
2224
2225        if (uwsgi.single_interpreter == 0) {
2226                PyThreadState_Swap(uwsgi.main_thread);
2227        }
2228
2229        PyDict_SetItem(uwsgi.py_apps, zero, PyInt_FromLong(id));
2230        PyErr_Print();
2231
2232        uwsgi_log( "application %d (%s) ready\n", id, PyString_AsString(zero));
2233
2234        Py_DECREF(zero);
2235
2236        if (id == 0) {
2237                uwsgi_log( "setting default application to 0\n");
2238                uwsgi.default_app = 0;
2239                if (uwsgi.vhost) {
2240                        uwsgi.wsgi_cnt++;
2241                }
2242        }
2243        else {
2244                uwsgi.wsgi_cnt++;
2245        }
2246
2247        return id;
2248}
2249
2250#ifdef UWSGI_PASTE
2251void uwsgi_paste_config() {
2252        PyObject *paste_module, *paste_dict, *paste_loadapp;
2253        PyObject *paste_arg, *paste_app;
2254
2255        uwsgi.single_interpreter = 1;
2256
2257        uwsgi_log( "Loading paste environment: %s\n", uwsgi.paste);
2258        paste_module = PyImport_ImportModule("paste.deploy");
2259        if (!paste_module) {
2260                PyErr_Print();
2261                exit(1);
2262        }
2263
2264        paste_dict = PyModule_GetDict(paste_module);
2265        if (!paste_dict) {
2266                PyErr_Print();
2267                exit(1);
2268        }
2269
2270        paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
2271        if (!paste_loadapp) {
2272                PyErr_Print();
2273                exit(1);
2274        }
2275
2276        paste_arg = PyTuple_New(1);
2277        if (!paste_arg) {
2278                PyErr_Print();
2279                exit(1);
2280        }
2281
2282        if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(uwsgi.paste))) {
2283                PyErr_Print();
2284                exit(1);
2285        }
2286
2287        paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
2288        if (!paste_app) {
2289                PyErr_Print();
2290                exit(1);
2291        }
2292
2293        init_uwsgi_app(NULL, paste_app);
2294}
2295
2296#endif
2297
2298/* trying to emulate Graham's mod_wsgi, this will allows easy and fast migrations */
2299void uwsgi_wsgi_file_config() {
2300
2301        FILE *wsgifile;
2302        struct _node *wsgi_file_node = NULL;
2303        PyObject *wsgi_compiled_node, *wsgi_file_module, *wsgi_file_dict;
2304        PyObject *wsgi_file_callable;
2305        int ret;
2306
2307        uwsgi.single_interpreter = 1;
2308
2309        wsgifile = fopen(uwsgi.wsgi_file, "r");
2310        if (!wsgifile) {
2311                uwsgi_error("fopen()");
2312                exit(1);
2313        }
2314
2315        wsgi_file_node = PyParser_SimpleParseFile(wsgifile, uwsgi.wsgi_file, Py_file_input);
2316        if (!wsgi_file_node) {
2317                PyErr_Print();
2318                uwsgi_log( "failed to parse wsgi file %s\n", uwsgi.wsgi_file);
2319                exit(1);
2320        }
2321
2322        fclose(wsgifile);
2323
2324        wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_file_node, uwsgi.wsgi_file);
2325
2326        if (!wsgi_compiled_node) {
2327                PyErr_Print();
2328                uwsgi_log( "failed to compile wsgi file %s\n", uwsgi.wsgi_file);
2329                exit(1);
2330        }
2331
2332        wsgi_file_module = PyImport_ExecCodeModule("uwsgi_wsgi_file", wsgi_compiled_node);
2333        if (!wsgi_file_module) {
2334                PyErr_Print();
2335                exit(1);
2336        }
2337
2338        Py_DECREF(wsgi_compiled_node);
2339
2340        wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
2341        if (!wsgi_file_dict) {
2342                PyErr_Print();
2343                exit(1);
2344        }
2345
2346
2347        wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, "application");
2348        if (!wsgi_file_callable) {
2349                PyErr_Print();
2350                uwsgi_log( "unable to find \"application\" callable in wsgi file %s\n", uwsgi.wsgi_file);
2351                exit(1);
2352        }
2353
2354        if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
2355                uwsgi_log( "\"application\" must be a callable object in wsgi file %s\n", uwsgi.wsgi_file);
2356                exit(1);
2357        }
2358
2359
2360        ret = init_uwsgi_app(NULL, wsgi_file_callable);
2361
2362}
2363
2364
2365void uwsgi_wsgi_config(char *filename) {
2366
2367        PyObject *wsgi_module, *wsgi_dict;
2368#ifdef UWSGI_EMBEDDED
2369        PyObject *uwsgi_module, *uwsgi_dict;
2370#endif
2371        PyObject *applications;
2372        PyObject *app_list;
2373        int ret;
2374        Py_ssize_t i;
2375        PyObject *app_mnt, *app_app = NULL;
2376        FILE *uwsgifile;
2377
2378        char *quick_callable = NULL;
2379
2380        uwsgi.single_interpreter = 1;
2381
2382        if (filename) {
2383
2384                if (uwsgi.callable) {
2385                        quick_callable = uwsgi.callable ;
2386                }
2387
2388                uwsgifile = fopen(filename, "r");
2389                if (!uwsgifile) {
2390                        uwsgi_error("fopen()");
2391                        exit(1);
2392                }
2393
2394                struct _node *uwsgi_file_node = PyParser_SimpleParseFile(uwsgifile, filename, Py_file_input);
2395                if (!uwsgi_file_node) {
2396                        PyErr_Print();
2397                        uwsgi_log( "failed to parse wsgi file %s\n", filename);
2398                        exit(1);
2399                }
2400
2401                fclose(uwsgifile);
2402
2403                PyObject *uwsgi_compiled_node = (PyObject *) PyNode_Compile(uwsgi_file_node, filename);
2404
2405                if (!uwsgi_compiled_node) {
2406                        PyErr_Print();
2407                        uwsgi_log( "failed to compile wsgi file %s\n", filename);
2408                        exit(1);
2409                }
2410
2411                wsgi_module = PyImport_ExecCodeModule("uwsgi_config_file", uwsgi_compiled_node);
2412                if (!wsgi_module) {
2413                        PyErr_Print();
2414                        exit(1);
2415                }
2416
2417                Py_DECREF(uwsgi_compiled_node);
2418                uwsgi.wsgi_config = "uwsgi_config_file";
2419        }
2420        else {
2421
2422                if (uwsgi.callable) {
2423                        quick_callable = uwsgi.callable ;
2424                }
2425                else {
2426                        quick_callable = strchr(uwsgi.wsgi_config, ':');
2427                        if (quick_callable) {
2428                                quick_callable[0] = 0 ;
2429                                quick_callable++;
2430                        }
2431                }
2432
2433                wsgi_module = PyImport_ImportModule(uwsgi.wsgi_config);
2434                if (!wsgi_module) {
2435                        PyErr_Print();
2436                        exit(1);
2437                }
2438        }
2439       
2440        wsgi_dict = PyModule_GetDict(wsgi_module);
2441        if (!wsgi_dict) {
2442                PyErr_Print();
2443                exit(1);
2444        }
2445
2446        if (!quick_callable) {
2447                uwsgi_log( "...getting the applications list from the '%s' module...\n", uwsgi.wsgi_config);
2448
2449#ifdef UWSGI_EMBEDDED
2450                uwsgi_module = PyImport_ImportModule("uwsgi");
2451                if (!uwsgi_module) {
2452                        PyErr_Print();
2453                        exit(1);
2454                }
2455
2456                uwsgi_dict = PyModule_GetDict(uwsgi_module);
2457                if (!uwsgi_dict) {
2458                        PyErr_Print();
2459                        exit(1);
2460                }
2461
2462
2463
2464        applications = PyDict_GetItemString(uwsgi_dict, "applications");
2465        if (!PyDict_Check(applications)) {
2466                uwsgi_log( "uwsgi.applications dictionary is not defined, trying with the \"applications\" one...\n");
2467#endif
2468                applications = PyDict_GetItemString(wsgi_dict, "applications");
2469                if (!applications) {
2470                        uwsgi_log( "applications dictionary is not defined, trying with the \"application\" callable.\n");
2471                        app_app = PyDict_GetItemString(wsgi_dict, "application");
2472                        if (app_app) {
2473                                applications = PyDict_New();
2474                                if (!applications) {
2475                                        uwsgi_log( "could not initialize applications dictionary\n");
2476                                        exit(1);
2477                                }
2478                                if (PyDict_SetItemString(applications, "", app_app)) {
2479                                        PyErr_Print();
2480                                        uwsgi_log( "unable to set default application\n");
2481                                        exit(1);
2482                                }
2483                        }
2484                        else {
2485                                uwsgi_log( "static applications not defined, you have to use the dynamic one...\n");
2486                                return;
2487                        }
2488                }
2489#ifdef UWSGI_EMBEDDED
2490        }
2491#endif
2492
2493        }
2494        else {
2495                // quick callable -> thanks gunicorn for the idea
2496                // we have extended the concept a bit...
2497                if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
2498                        quick_callable[strlen(quick_callable) -2 ] = 0 ;
2499                        PyObject *tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
2500                        if (tmp_callable) {
2501                                app_app = python_call(tmp_callable, PyTuple_New(0), 0);
2502                        }
2503                }
2504                else {
2505                        app_app = PyDict_GetItemString(wsgi_dict, quick_callable);
2506                }
2507                if (app_app) {
2508                        applications = PyDict_New();
2509                        if (!applications) {
2510                                uwsgi_log( "could not initialize applications dictionary\n");
2511                                exit(1);
2512                        }
2513                        if (PyDict_SetItemString(applications, "", app_app)) {
2514                                PyErr_Print();
2515                                uwsgi_log( "unable to set default application\n");
2516                                exit(1);
2517                        }
2518                 }
2519                 else {
2520                        uwsgi_log( "\"%s\" callable not found.\n", quick_callable);
2521                        exit(1);
2522                 }
2523        }
2524
2525        if (!PyDict_Check(applications)) {
2526                uwsgi_log( "The 'applications' object must be a dictionary.\n");
2527                exit(1);
2528        }
2529
2530        app_list = PyDict_Keys(applications);
2531        if (!app_list) {
2532                PyErr_Print();
2533                exit(1);
2534        }
2535        if (PyList_Size(app_list) < 1) {
2536                uwsgi_log( "You must define an app.\n");
2537                exit(1);
2538        }
2539
2540        for (i = 0; i < PyList_Size(app_list); i++) {
2541                app_mnt = PyList_GetItem(app_list, i);
2542
2543                if (!PyString_Check(app_mnt)) {
2544                        uwsgi_log( "the app mountpoint must be a string.\n");
2545                        exit(1);
2546                }
2547
2548                uwsgi.wsgi_req->script_name = PyString_AsString(app_mnt);
2549                uwsgi.wsgi_req->script_name_len = strlen(uwsgi.wsgi_req->script_name);
2550
2551                app_app = PyDict_GetItem(applications, app_mnt);
2552
2553                if (!PyString_Check(app_app) && !PyFunction_Check(app_app) && !PyCallable_Check(app_app)) {
2554                        uwsgi_log( "the app callable must be a string, a function or a callable. (found %s)\n", app_app->ob_type->tp_name);
2555                        exit(1);
2556                }
2557
2558                if (PyString_Check(app_app)) {
2559                        uwsgi.wsgi_req->wsgi_callable = PyString_AsString(app_app);
2560                        uwsgi.wsgi_req->wsgi_callable_len = strlen(uwsgi.wsgi_req->wsgi_callable);
2561                        ret = init_uwsgi_app(wsgi_dict, NULL);
2562                }
2563                else {
2564                        ret = init_uwsgi_app(wsgi_dict, app_app);
2565                }
2566
2567                if (ret < 0) {
2568                        uwsgi_log( "...goodbye cruel world...\n");
2569                        exit(1);
2570                }
2571                Py_DECREF(app_mnt);
2572                Py_DECREF(app_app);
2573        }
2574
2575}
2576
2577
2578#ifdef PYTHREE
2579static PyModuleDef uwsgi_module3 = {
2580        PyModuleDef_HEAD_INIT,
2581        "uwsgi",
2582        NULL,
2583        -1,
2584        null_methods,
2585};
2586PyObject *init_uwsgi3(void) {
2587        return PyModule_Create(&uwsgi_module3);
2588}
2589#endif
2590
2591#ifdef UWSGI_EMBEDDED
2592void init_uwsgi_embedded_module() {
2593        PyObject *new_uwsgi_module, *zero;
2594        int i;
2595
2596
2597        /* initialize for stats */
2598        uwsgi.workers_tuple = PyTuple_New(uwsgi.numproc);
2599        for (i = 0; i < uwsgi.numproc; i++) {
2600                zero = PyDict_New();
2601                Py_INCREF(zero);
2602                PyTuple_SetItem(uwsgi.workers_tuple, i, zero);
2603        }
2604
2605
2606
2607#ifdef PYTHREE
2608        PyImport_AppendInittab("uwsgi", init_uwsgi3);
2609        new_uwsgi_module = PyImport_AddModule("uwsgi");
2610#else
2611        new_uwsgi_module = Py_InitModule("uwsgi", null_methods);
2612#endif
2613        if (new_uwsgi_module == NULL) {
2614                uwsgi_log( "could not initialize the uwsgi python module\n");
2615                exit(1);
2616        }
2617
2618        uwsgi.embedded_dict = PyModule_GetDict(new_uwsgi_module);
2619        if (!uwsgi.embedded_dict) {
2620                uwsgi_log( "could not get uwsgi module __dict__\n");
2621                exit(1);
2622        }
2623
2624        if (PyDict_SetItemString(uwsgi.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
2625                PyErr_Print();
2626                exit(1);
2627        }
2628
2629        if (uwsgi.mode) {
2630                if (PyDict_SetItemString(uwsgi.embedded_dict, "mode", PyString_FromString(uwsgi.mode))) {
2631                        PyErr_Print();
2632                        exit(1);
2633                }
2634        }
2635
2636        if (uwsgi.pidfile) {
2637                if (PyDict_SetItemString(uwsgi.embedded_dict, "pidfile", PyString_FromString(uwsgi.pidfile))) {
2638                        PyErr_Print();
2639                        exit(1);
2640                }
2641        }
2642       
2643
2644        if (PyDict_SetItemString(uwsgi.embedded_dict, "SPOOL_RETRY", PyInt_FromLong(17))) {
2645                PyErr_Print();
2646                exit(1);
2647        }
2648
2649        if (PyDict_SetItemString(uwsgi.embedded_dict, "numproc", PyInt_FromLong(uwsgi.numproc))) {
2650                PyErr_Print();
2651                exit(1);
2652        }
2653
2654#ifdef UNBIT
2655        if (PyDict_SetItemString(uwsgi.embedded_dict, "unbit", Py_True)) {
2656#else
2657        if (PyDict_SetItemString(uwsgi.embedded_dict, "unbit", Py_None)) {
2658#endif
2659                PyErr_Print();
2660                exit(1);
2661        }
2662
2663        if (PyDict_SetItemString(uwsgi.embedded_dict, "buffer_size", PyInt_FromLong(uwsgi.buffer_size))) {
2664                PyErr_Print();
2665                exit(1);
2666        }
2667
2668        if (PyDict_SetItemString(uwsgi.embedded_dict, "started_on", PyInt_FromLong(uwsgi.start_tv.tv_sec))) {
2669                PyErr_Print();
2670                exit(1);
2671        }
2672
2673        if (PyDict_SetItemString(uwsgi.embedded_dict, "start_response", wsgi_spitout)) {
2674                PyErr_Print();
2675                exit(1);
2676        }
2677
2678        if (PyDict_SetItemString(uwsgi.embedded_dict, "fastfuncs", PyList_New(256))) {
2679                PyErr_Print();
2680                exit(1);
2681        }
2682
2683
2684        if (PyDict_SetItemString(uwsgi.embedded_dict, "applist", uwsgi.py_apps)) {
2685                PyErr_Print();
2686                exit(1);
2687        }
2688
2689        if (PyDict_SetItemString(uwsgi.embedded_dict, "applications", Py_None)) {
2690                PyErr_Print();
2691                exit(1);
2692        }
2693
2694        uwsgi.embedded_args = PyTuple_New(2);
2695        if (!uwsgi.embedded_args) {
2696                PyErr_Print();
2697                exit(1);
2698        }
2699
2700        if (PyDict_SetItemString(uwsgi.embedded_dict, "message_manager_marshal", Py_None)) {
2701                PyErr_Print();
2702                exit(1);
2703        }
2704
2705        uwsgi.fastfuncslist = PyDict_GetItemString(uwsgi.embedded_dict, "fastfuncs");
2706        if (!uwsgi.fastfuncslist) {
2707                PyErr_Print();
2708                exit(1);
2709        }
2710
2711        init_uwsgi_module_advanced(new_uwsgi_module);
2712
2713#ifdef UWSGI_SPOOLER
2714        if (uwsgi.spool_dir != NULL) {
2715                init_uwsgi_module_spooler(new_uwsgi_module);
2716        }
2717#endif
2718
2719
2720        if (uwsgi.sharedareasize > 0 && uwsgi.sharedarea) {
2721                init_uwsgi_module_sharedarea(new_uwsgi_module);
2722        }
2723}
2724#endif
2725
2726#ifdef UWSGI_PROXY
2727pid_t proxy_start(has_master) {
2728
2729        pid_t pid;
2730
2731        char *tcp_port = strchr(uwsgi.proxy_socket_name, ':');
2732
2733        if (tcp_port == NULL) {
2734                uwsgi.proxyfd = bind_to_unix(uwsgi.proxy_socket_name, UWSGI_LISTEN_QUEUE, uwsgi.chmod_socket, uwsgi.abstract_socket);
2735        }
2736        else {
2737                uwsgi.proxyfd = bind_to_tcp(uwsgi.proxy_socket_name, UWSGI_LISTEN_QUEUE, tcp_port);
2738                tcp_port[0] = ':';
2739        }
2740
2741        if (uwsgi.proxyfd < 0) {
2742                uwsgi_log( "unable to create the server socket.\n");
2743                exit(1);
2744        }
2745
2746        if (!has_master && uwsgi.numproc == 0) {
2747                uwsgi_proxy(uwsgi.proxyfd);
2748                // never here
2749                exit(1);
2750        }
2751        else {
2752                pid = fork();
2753                if (pid < 0) {
2754                        uwsgi_error("fork()");
2755                        exit(1);
2756                }
2757                else if (pid > 0) {
2758                        close(uwsgi.proxyfd);
2759                        return pid;
2760                        // continue with uWSGI spawn...
2761                }
2762                else {
2763                        uwsgi_proxy(uwsgi.proxyfd);
2764                        // never here
2765                        exit(1);
2766                }
2767        }
2768}
2769#endif
2770
2771#ifdef UWSGI_SPOOLER
2772pid_t spooler_start(int serverfd, PyObject * uwsgi_module_dict) {
2773        pid_t pid;
2774
2775        pid = fork();
2776        if (pid < 0) {
2777                uwsgi_error("fork()");
2778                exit(1);
2779        }
2780        else if (pid == 0) {
2781                close(serverfd);
2782                spooler(&uwsgi, uwsgi_module_dict);
2783        }
2784        else if (pid > 0) {
2785                uwsgi_log( "spawned the uWSGI spooler on dir %s with pid %d\n", uwsgi.spool_dir, pid);
2786        }
2787
2788        return pid;
2789}
2790#endif
2791
2792void manage_opt(int i, char *optarg) {
2793
2794        switch (i) {
2795
2796        case LONG_ARGS_CHDIR:
2797                if (chdir(optarg)) {
2798                        uwsgi_error("chdir()");
2799                        exit(1);
2800                }
2801                break;
2802        case LONG_ARGS_CHDIR2:
2803                uwsgi.chdir2 = optarg;
2804                break;
2805        case LONG_ARGS_PING:
2806                uwsgi.ping = optarg;
2807                break;
2808        case LONG_ARGS_PING_TIMEOUT:
2809                uwsgi.ping_timeout = atoi(optarg);
2810                break;
2811        case LONG_ARGS_CALLABLE:
2812                uwsgi.callable = optarg;
2813                break;
2814#ifdef UWSGI_HTTP
2815        case LONG_ARGS_HTTP:
2816                uwsgi.http = optarg;
2817                break;
2818#endif
2819#ifdef UWSGI_LDAP
2820        case LONG_ARGS_LDAP:
2821                uwsgi.ldap = optarg;
2822                break;
2823        case LONG_ARGS_LDAP_SCHEMA:
2824                uwsgi_ldap_schema_dump(long_options);
2825                break;
2826        case LONG_ARGS_LDAP_SCHEMA_LDIF:
2827                uwsgi_ldap_schema_dump_ldif(long_options);
2828                break;
2829#endif
2830        case LONG_ARGS_MODE:
2831                uwsgi.mode = optarg;
2832                break;
2833        case LONG_ARGS_ENV:
2834                if (putenv(optarg)) {
2835                        uwsgi_error("putenv()");
2836                }
2837                break;
2838#ifdef UWSGI_ASYNC
2839        case LONG_ARGS_ASYNC:
2840                uwsgi.async = atoi(optarg);
2841                break;
2842#endif
2843        case LONG_ARGS_LOGTO:
2844                logto(optarg);
2845                break;
2846#ifdef UWSGI_UGREEN
2847        case LONG_ARGS_UGREEN_PAGES:
2848                uwsgi.ugreen_stackpages = atoi(optarg);
2849                break;
2850#endif
2851        case LONG_ARGS_VERSION:
2852                fprintf(stdout, "uWSGI %s\n", UWSGI_VERSION);
2853                exit(0);
2854#ifdef UWSGI_SNMP
2855        case LONG_ARGS_SNMP:
2856                uwsgi.snmp = 1;
2857                break;
2858        case LONG_ARGS_SNMP_COMMUNITY:
2859                uwsgi.snmp = 1;
2860                uwsgi.snmp_community = optarg;
2861                break;
2862#endif
2863        case LONG_ARGS_PIDFILE:
2864                uwsgi.pidfile = optarg;
2865                break;
2866#ifdef UWSGI_UDP
2867        case LONG_ARGS_UDP:
2868                uwsgi.udp_socket = optarg;
2869                uwsgi.master_process = 1;
2870                break;
2871#endif
2872#ifdef UWSGI_MULTICAST
2873        case LONG_ARGS_MULTICAST:
2874                uwsgi.multicast_group = optarg;
2875                uwsgi.master_process = 1;
2876                break;
2877#endif
2878        case LONG_ARGS_CHROOT:
2879                uwsgi.chroot = optarg;
2880                break;
2881        case LONG_ARGS_GID:
2882                uwsgi.gid = atoi(optarg);
2883                if (!uwsgi.gid) {
2884                        struct group *ugroup = getgrnam(optarg);
2885                        if (ugroup) {
2886                                uwsgi.gid = ugroup->gr_gid ;
2887                        }
2888                        else {
2889                                uwsgi_log("group %s not found.\n", optarg);
2890                                exit(1);
2891                        }
2892                }
2893                break;
2894        case LONG_ARGS_UID:
2895                uwsgi.uid = atoi(optarg);
2896                if (!uwsgi.uid) {
2897                        struct passwd *upasswd = getpwnam(optarg);
2898                        if (upasswd) {
2899                                uwsgi.uid = upasswd->pw_uid ;
2900                        }
2901                        else {
2902                                uwsgi_log("user %s not found.\n", optarg);
2903                                exit(1);
2904                        }
2905                }
2906                break;
2907        case LONG_ARGS_BINARY_PATH:
2908                uwsgi.binary_path = optarg;
2909                break;
2910        case LONG_ARGS_WSGI_FILE:
2911                uwsgi.wsgi_file = optarg;
2912                break;
2913        case LONG_ARGS_FILE_CONFIG:
2914                uwsgi.file_config = optarg;
2915                break;
2916#ifdef UWSGI_PROXY
2917        case LONG_ARGS_PROXY_NODE:
2918                uwsgi_cluster_add_node(optarg, 1);
2919                break;
2920        case LONG_ARGS_PROXY:
2921                uwsgi.proxy_socket_name = optarg;
2922                break;
2923#endif
2924#ifdef UWSGI_ERLANG
2925        case LONG_ARGS_ERLANG:
2926                uwsgi.erlang_node = optarg;
2927                break;
2928        case LONG_ARGS_ERLANG_COOKIE:
2929                uwsgi.erlang_cookie = optarg;
2930                break;
2931#endif
2932#ifdef UWSGI_HTTP
2933        case LONG_ARGS_HTTP_VAR:
2934                if (uwsgi.http_vars_cnt < 63) {
2935                        uwsgi.http_vars[uwsgi.http_vars_cnt] = optarg;
2936                        uwsgi.http_vars_cnt++;
2937                }
2938                else {
2939                        uwsgi_log( "you can specify at most 64 --http-var options\n");
2940                }
2941                break;
2942#endif
2943        case LONG_ARGS_PYTHONPATH:
2944                if (uwsgi.python_path_cnt < 63) {
2945                        uwsgi.python_path[uwsgi.python_path_cnt] = optarg;
2946                        uwsgi.python_path_cnt++;
2947                }
2948                else {
2949                        uwsgi_log( "you can specify at most 64 --pythonpath options\n");
2950                }
2951                break;
2952        case LONG_ARGS_LIMIT_AS:
2953                uwsgi.rl.rlim_cur = (atoi(optarg)) * 1024 * 1024;
2954                uwsgi.rl.rlim_max = uwsgi.rl.rlim_cur;
2955                break;
2956        case LONG_ARGS_LIMIT_POST:
2957                uwsgi.limit_post = (int) strtol(optarg, NULL, 10);
2958                break;
2959        case LONG_ARGS_PRIO:
2960                uwsgi.prio = (int) strtol(optarg, NULL, 10);
2961                break;
2962        case LONG_ARGS_POST_BUFFERING:
2963                uwsgi.post_buffering = atoi(optarg);
2964                break;
2965        case LONG_ARGS_POST_BUFFERING_SIZE:
2966                uwsgi.post_buffering_bufsize = atoi(optarg);
2967                break;
2968#ifdef UWSGI_INI
2969        case LONG_ARGS_INI:
2970                uwsgi.ini = optarg;
2971                break;
2972        case LONG_ARGS_INI_PASTE:
2973                uwsgi.ini = optarg;
2974                if (uwsgi.ini[0] != '/') {
2975                        uwsgi.paste = malloc( 7 + strlen(uwsgi.cwd) + 1 + strlen(uwsgi.ini) + 1);
2976                        if (uwsgi.paste == NULL) {
2977                                uwsgi_error("malloc()");
2978                                exit(1);
2979                        }
2980                        memset(uwsgi.paste, 0, 7 + strlen(uwsgi.cwd) + strlen(uwsgi.ini) + 1);
2981                        memcpy(uwsgi.paste, "config:", 7);
2982                        memcpy(uwsgi.paste + 7, uwsgi.cwd, strlen(uwsgi.cwd));
2983                        uwsgi.paste[7 + strlen(uwsgi.cwd)] = '/';
2984                        memcpy(uwsgi.paste + 7 + strlen(uwsgi.cwd) + 1, uwsgi.ini, strlen(uwsgi.ini));
2985                }
2986                else {
2987                        uwsgi.paste = malloc( 7 + strlen(uwsgi.ini) + 1);
2988                        if (uwsgi.paste == NULL) {
2989                                uwsgi_error("malloc()");
2990                                exit(1);
2991                        }
2992                        memset(uwsgi.paste, 0, 7 + strlen(uwsgi.ini) + 1);
2993                        memcpy(uwsgi.paste, "config:", 7);
2994                        memcpy(uwsgi.paste + 7, uwsgi.ini, strlen(uwsgi.ini));
2995                }
2996                break;
2997#endif
2998#ifdef UWSGI_PASTE
2999        case LONG_ARGS_PASTE:
3000                uwsgi.paste = optarg;
3001                break;
3002#endif
3003        case LONG_ARGS_CHECK_INTERVAL:
3004                uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = atoi(optarg);
3005                break;
3006        case LONG_ARGS_PYARGV:
3007                uwsgi.pyargv = optarg;
3008                break;
3009        case 'j':
3010                uwsgi.test_module = optarg;
3011                break;
3012        case 'H':
3013                uwsgi.pyhome = optarg;
3014                break;
3015        case 'A':
3016                uwsgi.sharedareasize = atoi(optarg);
3017                break;
3018        case 'L':
3019                uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 0;
3020                break;
3021#ifdef UWSGI_SPOOLER
3022        case 'Q':
3023                uwsgi.spool_dir = malloc(PATH_MAX);
3024                if (!uwsgi.spool_dir) {
3025                        uwsgi_error("malloc()");
3026                        exit(1);
3027                }
3028                if (access(optarg, R_OK | W_OK | X_OK)) {
3029                        uwsgi_error("[spooler directory] access()");
3030                        exit(1);
3031                }
3032                if (!realpath(optarg, uwsgi.spool_dir)) {
3033                        uwsgi_error("realpath()");
3034                        exit(1);
3035                }
3036                uwsgi.master_process = 1;
3037                break;
3038#endif
3039
3040        case 'd':
3041                if (!uwsgi.is_a_reload) {
3042                        daemonize(optarg);
3043                }
3044                break;
3045        case 's':
3046                uwsgi.socket_name = optarg;
3047                break;
3048#ifdef UWSGI_XML
3049        case 'x':
3050                uwsgi.xml_config = optarg;
3051                break;
3052#endif
3053        case 'l':
3054                uwsgi.listen_queue = atoi(optarg);
3055                break;
3056        case 'v':
3057                uwsgi.max_vars = atoi(optarg);
3058                uwsgi.vec_size = 4 + 1 + (4 * uwsgi.max_vars);
3059                break;
3060        case 'p':
3061                uwsgi.numproc = atoi(optarg);
3062                break;
3063        case 'r':
3064                uwsgi.shared->options[UWSGI_OPTION_REAPER] = 1;
3065                break;
3066        case 'w':
3067                uwsgi.wsgi_config = optarg;
3068                break;
3069        case 'm':
3070                uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] = 1;
3071                break;
3072        case 'O':
3073                uwsgi.py_optimize = atoi(optarg);
3074                break;
3075        case 't':
3076                uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] = atoi(optarg);
3077                break;
3078        case 'b':
3079                uwsgi.buffer_size = atoi(optarg);
3080                break;
3081        case 'c':
3082                uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
3083                break;
3084        case 'a':
3085                uwsgi.abstract_socket = 1;
3086                break;
3087        case 'C':
3088                uwsgi.chmod_socket = 1;
3089                if (optarg) {
3090                        if (strlen(optarg) != 3) {
3091                                uwsgi_log("invalid chmod value: %s\n", optarg);
3092                                exit(1);
3093                        }
3094                        for(i=0;i<3;i++) {
3095                                if (optarg[i] < '0' || optarg[i] > '7') {
3096                                        uwsgi_log("invalid chmod value: %s\n", optarg);
3097                                        exit(1);
3098                                }
3099                        }
3100
3101                        uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (optarg[0] - '0');
3102                        uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (optarg[1] - '0');
3103                        uwsgi.chmod_socket_value = (uwsgi.chmod_socket_value << 3) + (optarg[2] - '0');
3104                }
3105                break;
3106        case 'M':
3107                uwsgi.master_process = 1;
3108                break;
3109        case 'R':
3110                uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] = atoi(optarg);
3111                break;
3112        case 'z':
3113                if (atoi(optarg) > 0) {
3114                        uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = atoi(optarg);
3115                }
3116                break;
3117        case 'T':
3118                uwsgi.has_threads = 1;
3119                uwsgi.shared->options[UWSGI_OPTION_THREADS] = 1;
3120                break;
3121        case 'P':
3122                uwsgi.enable_profiler = 1;
3123                break;
3124        case 'i':
3125                uwsgi.single_interpreter = 1;
3126                break;
3127        LONG_ARGS_PLUGIN_EMBED_PSGI
3128        LONG_ARGS_PLUGIN_EMBED_LUA
3129        LONG_ARGS_PLUGIN_EMBED_RACK
3130        case 'h':
3131                fprintf(stdout, "Usage: %s [options...]\n\
3132\t-s|--socket <name>\t\tpath (or name) of UNIX/TCP socket to bind to\n\
3133\t-l|--listen <num>\t\tset socket listen queue to <n> (default 64, maximum is system dependent)\n\
3134\t-z|--socket-timeout <sec>\tset socket timeout to <sec> seconds (default 4 seconds)\n\
3135\t-b|--buffer-size <n>\t\tset buffer size to <n> bytes\n\
3136\t-L|--disable-logging\t\tdisable request logging (only errors or server messages will be logged)\n\
3137\t-x|--xmlconfig <path>\t\tpath of xml config file\n\
3138\t-w|--module <module>\t\tname of python config module\n\
3139\t-t|--harakiri <sec>\t\tset harakiri timeout to <sec> seconds\n\
3140\t-p|--processes <n>\t\tspawn <n> uwsgi worker processes\n\
3141\t-O|--optimize <n>\t\tset python optimization level to <n>\n\
3142\t-v|--max-vars <n>\t\tset maximum number of vars/headers to <n>\n\
3143\t-A|--sharedarea <n>\t\tcreate a shared memory area of <n> pages\n\
3144\t-c|--cgi-mode\t\t\tset cgi mode\n\
3145\t-C|--chmod-socket[=NNN]\t\tchmod socket to 666 or NNN\n\
3146\t-P|--profiler\t\t\tenable profiler\n\
3147\t-m|--memory-report\t\tenable memory usage report\n\
3148\t-i|--single-interpreter\t\tsingle interpreter mode\n\
3149\t-a|--abstract-socket\t\tset socket in the abstract namespace (Linux only)\n\
3150\t-T|--enable-threads\t\tenable threads support\n\
3151\t-M|--master\t\t\tenable master process manager\n\
3152\t-H|--home <path>\t\tset python home/virtualenv\n\
3153\t-h|--help\t\t\tthis help\n\
3154\t-r|--reaper\t\t\tprocess reaper (call waitpid(-1,...) after each request)\n\
3155\t-R|--max-requests\t\tmaximum number of requests for each worker\n\
3156\t-j|--test\t\t\ttest if uWSGI can import a module\n\
3157\t-Q|--spooler <dir>\t\trun the spooler on directory <dir>\n\
3158\t--callable <callable>\t\tset the callable (default 'application')\n\
3159\t--pidfile <file>\t\twrite the masterpid to <file>\n\
3160\t--chroot <dir>\t\t\tchroot to directory <dir> (only root)\n\
3161\t--gid <id/groupname>\t\tsetgid to <id/groupname> (only root)\n\
3162\t--uid <id/username>\t\tsetuid to <id/username> (only root)\n\
3163\t--chdir <dir>\t\t\tchdir to <dir> before app loading\n\
3164\t--chdir2 <dir>\t\t\tchdir to <dir> after module loading\n\
3165\t--no-server\t\t\tinitialize the uWSGI server then exit. Useful for testing and using uwsgi embedded module\n\
3166\t--no-defer-accept\t\tdisable the no-standard way to defer the accept() call (TCP_DEFER_ACCEPT, SO_ACCEPTFILTER...)\n\
3167\t--paste <config:/egg:>\t\tload applications using paste.deploy.loadapp()\n\
3168\t--check-interval <sec>\t\tset the check interval (in seconds) of the master process\n\
3169\t--pythonpath <dir>\t\tadd <dir> to PYTHONPATH\n\
3170\t--pyargv <args>\t\t\tassign args to python sys.argv\n\
3171\t--limit-as <MB>\t\t\tlimit the address space of processes to MB megabytes\n\
3172\t--limit-post <bytes>\t\tlimit HTTP content_length size to <bytes>\n\
3173\t--post-buffering <bytes>\tbuffer HTTP POST request higher than <bytes> to disk\n\
3174\t--post-buffering-bufsize <b>\tset the buffer size to <b> bytes for post-buffering\n\
3175\t--prio <N>\t\t\tset process priority/nice to N\n\
3176\t--no-orphans\t\t\tautomatically kill workers on master's dead\n\
3177\t--udp <ip:port>\t\t\tbind master process to udp socket on ip:port\n\
3178\t--multicast <group>\t\tset multicast group\n\
3179\t--snmp\t\t\t\tenable SNMP support in the UDP server\n\
3180\t--snmp-community <value>\tset SNMP community code to <value>\n\
3181\t--erlang <name@ip>\t\tenable the Erlang server with node name <node@ip>\n\
3182\t--erlang-cookie <cookie>\ttset the erlang cookie to <cookie>\n\
3183\t--nagios\t\t\tdo a nagios check\n\
3184\t--binary-path <bin-path>\ttset the path for the next reload of uWSGI (needed for chroot environments)\n\
3185\t--proxy <socket>\t\trun the uwsgi proxy on socket <socket>\n\
3186\t--proxy-node <socket>\t\tadd the node <socket> to the proxy\n\
3187\t--proxy-max-connections <n>\tset the max number of concurrent connections mnaged by the proxy\n\
3188\t--wsgi-file <file>\t\tload the <file> wsgi file\n\
3189\t--file <file>\t\t\tuse python file instead of python module for configuration\n\
3190\t--async <n>\t\t\tenable async mode with n core\n\
3191\t--logto <logfile|addr>\t\tlog to file/udp\n\
3192\t--logdate\t\t\tadd timestamp to loglines\n\
3193\t--ignore-script-name\t\tdisable uWSGI management of SCRIPT_NAME\n\
3194\t--ini <inifile>\t\t\tpath of ini config file\n\
3195\t--ini-paste <inifile>\t\tpath of ini config file that contains paste configuration\n\
3196\t--ldap <url>\t\t\turl of LDAP uWSGIConfig resource\n\
3197\t--ldap-schema\t\t\tdump uWSGIConfig LDAP schema\n\
3198\t--ldap-schema-ldif\t\tdump uWSGIConfig LDAP schema in LDIF format\n\
3199\t--grunt\t\t\t\tenable grunt workers\n\
3200\t--ugreen\t\t\tenable uGreen support\n\
3201\t--ugreen-stacksize <n>\t\tset uGreen stacksize to <n>\n\
3202\t--stackless\t\t\tenable usage of tasklet (only on Stackless Python)\n\
3203\t--no-site\t\t\tdo not import site.py on startup\n\
3204\t--vhost\t\t\t\tenable virtual hosting\n\
3205\t--routing\t\t\tenable uWSGI advanced routing\n\
3206\t--http <addr>\t\t\tstart embedded HTTP server on <addr>\n\
3207\t--http-only\t\t\tstart only the embedded HTTP server\n\
3208\t--http-var KEY[=VALUE]\t\tadd var KEY to uwsgi requests made by the embedded HTTP server\n\
3209\t--catch-exceptions\t\tprint exceptions in the browser\n\
3210\t--mode\t\t\t\tset configuration mode\n\
3211\t--env KEY=VALUE\t\t\tset environment variable\n\
3212\t--vacuum\t\t\tclear the environment on exit (remove UNIX sockets and pidfiles)\n\
3213\t--ping <addr>\t\t\tping a uWSGI server (returns 1 on failure 0 on success)\n\
3214\t--ping-timeout <n>\t\tset ping timeout to <n>\n\
3215\t--version\t\t\tprint server version\n\
3216\t-d|--daemonize <logfile|addr>\tdaemonize and log into <logfile> or udp <addr>\n", uwsgi.binary_path);
3217                exit(1);
3218        case 0:
3219                break;
3220        default:
3221                if (i != '?') {
3222                        uwsgi_log( "invalid argument -%c  exiting \n", i);
3223                }
3224                exit(1);
3225        }
3226}
3227
3228
3229void uwsgi_cluster_add_node(char *nodename, int workers) {
3230
3231        int i;
3232        struct uwsgi_cluster_node *ucn;
3233        char *tcp_port;
3234
3235        if (strlen(nodename) > 100) {
3236                uwsgi_log( "invalid cluster node name %s\n", nodename);
3237                return;
3238        }
3239
3240        tcp_port = strchr(nodename, ':');
3241        if (tcp_port == NULL) {
3242                fprintf(stdout, "invalid cluster node name %s\n", nodename);
3243                return;
3244        }
3245
3246        for (i = 0; i < MAX_CLUSTER_NODES; i++) {
3247                ucn = &uwsgi.shared->nodes[i];
3248
3249                if (ucn->name[0] == 0) {
3250                        memcpy(ucn->name, nodename, strlen(nodename) + 1);
3251                        ucn->workers = workers;
3252                        ucn->ucn_addr.sin_family = AF_INET;
3253                        ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
3254                        tcp_port[0] = 0;
3255                        if (nodename[0] == 0) {
3256                                ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
3257                        }
3258                        else {
3259                                uwsgi_log( "%s\n", nodename);
3260                                ucn->ucn_addr.sin_addr.s_addr = inet_addr(nodename);
3261                        }
3262
3263                        ucn->last_seen = time(NULL);
3264
3265                        return;
3266                }
3267        }
3268
3269        uwsgi_log( "unable to add node %s\n", nodename);
3270}
Note: See TracBrowser for help on using the browser.