root/uwsgi.c

Revision 284:50549c1d07db, 71.6 KB (checked in by roberto@…, 34 minutes ago)

updated --help

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
34#if PY_MINOR_VERSION < 5
35#define Py_ssize_t int
36#endif
37
38struct uwsgi_server uwsgi;
39
40static char *nl = "\r\n";
41static char *h_sep = ": ";
42static const char *http_protocol = "HTTP/1.1";
43static const char *app_slash = "/";
44
45extern char **environ;
46
47int find_worker_id (pid_t pid) {
48        int i;
49        for (i = 1; i <= uwsgi.numproc; i++) {
50                /* fprintf(stderr,"%d of %d\n", pid, uwsgi.workers[i].pid); */
51                if (uwsgi.workers[i].pid == pid)
52                        return i;
53        }
54
55        return -1;
56}
57
58struct wsgi_request wsgi_req;
59
60PyMethodDef null_methods[] = {
61        {NULL, NULL},
62};
63
64#ifdef UNBIT
65int save_to_disk = -1;
66int tmp_dir_fd = -1;
67char *tmp_filename;
68int uri_to_hex (void);
69int check_for_memory_errors = 0;
70#endif
71
72PyObject *wsgi_writeout;
73
74
75struct uwsgi_app *wi;
76
77void warn_pipe () {
78        fprintf (stderr, "writing to a closed pipe/socket/fd !!!\n");
79}
80
81void gracefully_kill () {
82        fprintf (stderr, "Gracefully killing worker %d...\n", uwsgi.mypid);
83        if (UWSGI_IS_IN_REQUEST) {
84                uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
85        }
86        else {
87                reload_me ();
88        }
89}
90
91void reload_me () {
92        exit (UWSGI_RELOAD_CODE);
93}
94
95void end_me () {
96        exit (UWSGI_END_CODE);
97}
98
99void goodbye_cruel_world () {
100        fprintf (stderr, "...The work of process %d is done. Seeya!\n", getpid ());
101        exit (0);
102}
103
104void kill_them_all () {
105        int i;
106        uwsgi.to_hell = 1;
107        fprintf (stderr, "SIGINT/SIGQUIT received...killing workers...\n");
108        for (i = 1; i <= uwsgi.numproc; i++) {
109                kill (uwsgi.workers[i].pid, SIGINT);
110        }
111}
112
113void grace_them_all () {
114        int i;
115        uwsgi.to_heaven = 1;
116        fprintf (stderr, "...gracefully killing workers...\n");
117        for (i = 1; i <= uwsgi.numproc; i++) {
118                kill (uwsgi.workers[i].pid, SIGHUP);
119        }
120}
121
122void reap_them_all () {
123        int i;
124        fprintf (stderr, "...brutally killing workers...\n");
125        for (i = 1; i <= uwsgi.numproc; i++) {
126                kill (uwsgi.workers[i].pid, SIGTERM);
127        }
128}
129
130void harakiri () {
131
132        PyThreadState *_myself;
133
134/* CHECK ROCK_SOLID
135        struct uwsgi_app *wi = NULL;
136        if (wsgi_req.app_id >= 0) {
137                wi = &uwsgi.wsgi_apps[wsgi_req.app_id];
138        }
139 end rock_solid */
140
141        PyGILState_Ensure ();
142        _myself = PyThreadState_Get ();
143        if (wi) {
144/*
145#ifdef ROCK_SOLID
146                fprintf (stderr, "\nF*CK !!! i must kill myself (pid: %d) wi: %p wi->wsgi_harakiri: %p thread_state: %p frame: %p...\n", uwsgi.mypid, wi, wi->wsgi_harakiri, _myself, _myself->frame);
147#else
148*/
149                fprintf (stderr, "\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, wsgi_req.app_id, wi, wi->wsgi_harakiri, _myself, _myself->frame);
150
151                if (wi->wsgi_harakiri) {
152                        PyEval_CallObject (wi->wsgi_harakiri, wi->wsgi_args);
153                        if (PyErr_Occurred ()) {
154                                PyErr_Print ();
155                        }
156                }
157        }
158        Py_FatalError ("HARAKIRI !\n");
159}
160
161#ifndef UNBIT
162void stats () {
163        struct uwsgi_app *ua = NULL;
164        int i;
165
166        fprintf (stderr, "*** pid %d stats ***\n", getpid ());
167        fprintf (stderr, "\ttotal requests: %llu\n", uwsgi.workers[0].requests);
168        for (i = 0; i < uwsgi.wsgi_cnt; i++) {
169                ua = &uwsgi.wsgi_apps[i];
170                if (ua) {
171                        fprintf (stderr, "\tapp %d requests: %d\n", i, ua->requests);
172                }
173        }
174        fprintf (stderr, "\n");
175}
176#endif
177
178void internal_server_error (int fd, char *message) {
179#ifndef UNBIT
180        if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
181#endif
182                wsgi_req.headers_size = write (fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63);
183#ifndef UNBIT
184        }
185        else {
186                wsgi_req.headers_size = write (fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62);
187        }
188        wsgi_req.header_cnt = 2;
189#endif
190        wsgi_req.response_size = write (fd, "<h1>uWSGI Error</h1>", 20);
191        wsgi_req.response_size += write (fd, message, strlen (message));
192}
193
194PyObject *py_uwsgi_write (PyObject * self, PyObject * args) {
195        PyObject *data;
196        char *content;
197        int len;
198        data = PyTuple_GetItem (args, 0);
199        if (PyString_Check (data)) {
200                content = PyString_AsString (data);
201                len = PyString_Size (data);
202
203#ifdef UWSGI_THREADING
204                if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
205                        Py_BEGIN_ALLOW_THREADS wsgi_req.response_size = write (uwsgi.poll.fd, content, len);
206                Py_END_ALLOW_THREADS}
207                else {
208#endif
209                        wsgi_req.response_size = write (uwsgi.poll.fd, content, len);
210#ifdef UNBIT
211                        if (save_to_disk >= 0) {
212                                if (write (save_to_disk, content, len) != len) {
213                                        perror ("write()");
214                                        close (save_to_disk);
215                                        save_to_disk = -1;
216                                }
217                        }
218#endif
219#ifdef UWSGI_THREADING
220                }
221#endif
222        }
223#ifdef UNBIT
224        if (save_to_disk >= 0) {
225                close (save_to_disk);
226                save_to_disk = -1;
227                fprintf (stderr, "[uWSGI cacher] output of request %llu (%.*s) on pid %d written to cache file %s\n", uwsgi.workers[0].requests, wsgi_req.uri_len, wsgi_req.uri, uwsgi.mypid, tmp_filename);
228        }
229#endif
230        Py_INCREF (Py_None);
231        return Py_None;
232}
233
234
235PyObject *wsgi_spitout;
236
237PyObject *py_uwsgi_spit (PyObject * self, PyObject * args) {
238        PyObject *headers, *head;
239        PyObject *h_key, *h_value;
240        int i, j;
241
242#ifndef UNBIT
243        int base = 0;
244#else
245        int base = 4;
246#endif
247
248        // use writev()
249
250
251        head = PyTuple_GetItem (args, 0);
252        if (!head) {
253                goto clear;
254        }
255
256        if (!PyString_Check (head)) {
257                fprintf (stderr, "http status must be a string !\n");
258                goto clear;
259        }
260
261
262#ifndef UNBIT
263        if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
264                base = 4;
265#endif
266
267
268                if (wsgi_req.protocol_len == 0) {
269                        uwsgi.hvec[0].iov_base = (char *) http_protocol;
270                        wsgi_req.protocol_len = 8;
271                }
272                else {
273                        uwsgi.hvec[0].iov_base = wsgi_req.protocol;
274                }
275
276                uwsgi.hvec[0].iov_len = wsgi_req.protocol_len;
277                uwsgi.hvec[1].iov_base = " ";
278                uwsgi.hvec[1].iov_len = 1;
279#ifdef PYTHREE
280                uwsgi.hvec[2].iov_base = PyBytes_AsString (PyUnicode_AsASCIIString (head));
281                uwsgi.hvec[2].iov_len = strlen (uwsgi.hvec[2].iov_base);
282#else
283                uwsgi.hvec[2].iov_base = PyString_AsString (head);
284                uwsgi.hvec[2].iov_len = PyString_Size (head);
285#endif
286                wsgi_req.status = atoi (uwsgi.hvec[2].iov_base);
287                uwsgi.hvec[3].iov_base = nl;
288                uwsgi.hvec[3].iov_len = NL_SIZE;
289#ifndef UNBIT
290        }
291        else {
292                // drop http status on cgi mode
293                base = 3;
294                uwsgi.hvec[0].iov_base = "Status: ";
295                uwsgi.hvec[0].iov_len = 8;
296#ifdef PYTHREE
297                uwsgi.hvec[1].iov_base = PyBytes_AsString (PyUnicode_AsASCIIString (head));
298                uwsgi.hvec[1].iov_len = strlen (uwsgi.hvec[1].iov_base);
299#else
300                uwsgi.hvec[1].iov_base = PyString_AsString (head);
301                uwsgi.hvec[1].iov_len = PyString_Size (head);
302#endif
303                wsgi_req.status = atoi (uwsgi.hvec[1].iov_base);
304                uwsgi.hvec[2].iov_base = nl;
305                uwsgi.hvec[2].iov_len = NL_SIZE;
306        }
307#endif
308
309
310#ifdef UNBIT
311        if (wsgi_req.unbit_flags & (unsigned long long) 1) {
312                if (tmp_dir_fd >= 0 && tmp_filename[0] != 0 && wsgi_req.status == 200 && wsgi_req.method_len == 3 && wsgi_req.method[0] == 'G' && wsgi_req.method[1] == 'E' && wsgi_req.method[2] == 'T') {
313                        save_to_disk = openat (tmp_dir_fd, tmp_filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
314                }
315        }
316#endif
317
318
319        headers = PyTuple_GetItem (args, 1);
320        if (!headers) {
321                goto clear;
322        }
323        if (!PyList_Check (headers)) {
324                fprintf (stderr, "http headers must be in a python list\n");
325                goto clear;
326        }
327        wsgi_req.header_cnt = PyList_Size (headers);
328
329
330
331        if (wsgi_req.header_cnt > uwsgi.max_vars) {
332                wsgi_req.header_cnt = uwsgi.max_vars;
333        }
334        for (i = 0; i < wsgi_req.header_cnt; i++) {
335                j = (i * 4) + base;
336                head = PyList_GetItem (headers, i);
337                if (!head) {
338                        goto clear;
339                }
340                if (!PyTuple_Check (head)) {
341                        fprintf (stderr, "http header must be defined in a tuple !\n");
342                        goto clear;
343                }
344                h_key = PyTuple_GetItem (head, 0);
345                if (!h_key) {
346                        goto clear;
347                }
348                h_value = PyTuple_GetItem (head, 1);
349                if (!h_value) {
350                        goto clear;
351                }
352#ifdef PYTHREE
353                uwsgi.hvec[j].iov_base = PyBytes_AsString (PyUnicode_AsASCIIString (h_key));
354                uwsgi.hvec[j].iov_len = strlen (uwsgi.hvec[j].iov_base);
355#else
356                uwsgi.hvec[j].iov_base = PyString_AsString (h_key);
357                uwsgi.hvec[j].iov_len = PyString_Size (h_key);
358#endif
359                uwsgi.hvec[j + 1].iov_base = h_sep;
360                uwsgi.hvec[j + 1].iov_len = H_SEP_SIZE;
361#ifdef PYTHREE
362                uwsgi.hvec[j + 2].iov_base = PyBytes_AsString (PyUnicode_AsASCIIString (h_value));
363                uwsgi.hvec[j + 2].iov_len = strlen (uwsgi.hvec[j + 2].iov_base);
364#else
365                uwsgi.hvec[j + 2].iov_base = PyString_AsString (h_value);
366                uwsgi.hvec[j + 2].iov_len = PyString_Size (h_value);
367#endif
368                uwsgi.hvec[j + 3].iov_base = nl;
369                uwsgi.hvec[j + 3].iov_len = NL_SIZE;
370                //fprintf(stderr, "%.*s: %.*s\n", uwsgi.hvec[j].iov_len, (char *)uwsgi.hvec[j].iov_base, uwsgi.hvec[j+2].iov_len, (char *) uwsgi.hvec[j+2].iov_base);
371        }
372
373
374#ifdef UNBIT
375        if (save_to_disk >= 0) {
376                for (j = 0; j < i; j += 4) {
377                        if (!strncasecmp (uwsgi.hvec[j].iov_base, "Set-Cookie", uwsgi.hvec[j].iov_len)) {
378                                close (save_to_disk);
379                                save_to_disk = -1;
380                                break;
381                        }
382                }
383        }
384#endif
385
386        // \r\n
387        j = (i * 4) + base;
388        uwsgi.hvec[j].iov_base = nl;
389        uwsgi.hvec[j].iov_len = NL_SIZE;
390
391        wsgi_req.headers_size = writev (uwsgi.poll.fd, uwsgi.hvec, j + 1);
392        if (wsgi_req.headers_size < 0) {
393                perror ("writev()");
394        }
395        Py_INCREF (wsgi_writeout);
396
397
398        return wsgi_writeout;
399
400      clear:
401
402        Py_INCREF (Py_None);
403        return Py_None;
404}
405
406#ifdef UWSGI_SENDFILE
407PyObject *py_uwsgi_sendfile (PyObject * self, PyObject * args) {
408
409        //PyObject *zero ;
410
411        uwsgi.py_sendfile = PyTuple_GetItem (args, 0);
412
413#ifdef PYTHREE
414        if ((wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile)) >= 0) {
415                Py_INCREF (uwsgi.py_sendfile);
416        }
417#else
418        if (PyFile_Check (uwsgi.py_sendfile)) {
419                //zero = PyFile_Name(uwsgi.py_sendfile) ;
420                //fprintf(stderr,"->serving %s as static file...", PyString_AsString(zero));
421                wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile);
422                Py_INCREF (uwsgi.py_sendfile);
423        }
424#endif
425
426
427        return PyTuple_New (0);
428}
429#endif
430
431PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""}
432};
433PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""}
434};
435
436#ifdef UWSGI_SENDFILE
437PyMethodDef uwsgi_sendfile_method[] = { {"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}
438};
439#endif
440
441
442// process manager is now (20090725) available on Unbit
443pid_t masterpid;
444pid_t diedpid;
445int waitpid_status;
446struct timeval last_respawn;
447time_t respawn_delta;
448#ifdef UNBIT
449int single_app_mode = 0;
450#endif
451
452char *spool_dir = NULL;
453
454static int unconfigured_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
455        fprintf(stderr, "-- unavailable modifier requested: %d --\n", wsgi_req->modifier);
456        return -1;
457}
458
459static void unconfigured_after_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
460        return;
461}
462
463int main (int argc, char *argv[], char *envp[]) {
464
465        uint64_t master_cycles = 0 ;
466        struct timeval check_interval = {.tv_sec = 1,.tv_usec = 0 };
467
468#ifdef UWSGI_EMBEDDED
469        PyObject *uwsgi_module;
470
471#endif
472        char *pyargv[MAX_PYARGV];
473        int pyargc = 1;
474
475        struct sockaddr_un c_addr;
476        int c_len = sizeof (struct sockaddr_un);
477        int i;
478        int ret;
479
480        int rlen;
481
482#ifdef UWSGI_NAGIOS
483        int nagios = 0 ;
484#endif
485
486#ifdef UWSGI_SCTP
487        int i_am_sctp = 0;
488        struct sctp_sndrcvinfo sctp_ss;
489#endif
490
491        char *udp_socket = NULL;
492        struct pollfd uwsgi_poll;
493        struct sockaddr_in udp_client;
494        socklen_t udp_len;
495        char udp_client_addr[16];
496
497        pid_t pid;
498        int no_server = 0;
499
500#ifndef UNBIT
501        FILE *pidfile;
502#endif
503
504        int working_workers = 0;
505        int blocking_workers = 0;
506
507        char *cwd = NULL;
508        int ready_to_reload = 0;
509        int ready_to_die = 0;
510
511        char *env_reloads ;
512        unsigned int reloads = 0;
513        char env_reload_buf[11];
514
515
516#ifdef UNBIT
517        struct uidsec_struct us;
518#endif
519
520        int socket_type = 0;
521        socklen_t socket_type_len;
522
523        /* anti signal bombing */
524        signal (SIGHUP, SIG_IGN);
525        signal (SIGTERM, SIG_IGN);
526
527        memset (&uwsgi, 0, sizeof (struct uwsgi_server));
528
529        /* generic shared area */
530        uwsgi.shared = (struct uwsgi_shared *) mmap (NULL, sizeof (struct uwsgi_shared), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
531        if (!uwsgi.shared) {
532                perror ("mmap()");
533                exit (1);
534        }
535        memset (uwsgi.shared, 0, sizeof (struct uwsgi_shared));
536
537        for(i=0;i<0xFF;i++) {
538                uwsgi.shared->hooks[i] = unconfigured_hook;
539                uwsgi.shared->after_hooks[i] = unconfigured_after_hook;
540        }
541
542        uwsgi.wsgi_cnt = 1;
543        uwsgi.default_app = -1;
544
545        uwsgi.buffer_size = 4096;
546        uwsgi.numproc = 1;
547#ifndef UNBIT
548        uwsgi.listen_queue = 64;
549#endif
550
551        uwsgi.max_vars = MAX_VARS;
552        uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
553
554        uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
555        uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
556
557#ifndef UNBIT
558        int option_index = 0;
559        struct option long_options[] = {
560                {"socket", required_argument, 0, 's'},
561                {"processes", required_argument, 0, 'p'},
562                {"harakiri", required_argument, 0, 't'},
563                {"xmlconfig", required_argument, 0, 'x'},
564                {"daemonize", required_argument, 0, 'd'},
565                {"listen", required_argument, 0, 'l'},
566                {"optimize", required_argument, 0, 'O'},
567                {"max-vars", required_argument, 0, 'v'},
568                {"buffer-size", required_argument, 0, 'b'},
569                {"memory-report", no_argument, 0, 'm'},
570                {"cgi-mode", no_argument, 0, 'c'},
571                {"abstract-socket", no_argument, 0, 'a'},
572                {"chmod-socket", no_argument, 0, 'C'},
573                {"enable-threads", no_argument, 0, 'T'},
574                {"profiler", no_argument, 0, 'P'},
575                {"single-interpreter", no_argument, 0, 'i'},
576                {"master", no_argument, 0, 'M'},
577                {"help", no_argument, 0, 'h'},
578                {"reaper", no_argument, 0, 'r'},
579                {"max-requests", required_argument, 0, 'R'},
580                {"socket-timeout", required_argument, 0, 'z'},
581                {"module", required_argument, 0, 'w'},
582                {"test", required_argument, 0, 'j'},
583                {"home", required_argument, 0, 'H'},
584                {"sharedarea", required_argument, 0, 'A'},
585                {"spooler", required_argument, 0, 'Q'},
586                {"disable-logging", no_argument, 0, 'L'},
587
588                {"pidfile", required_argument, 0, LONG_ARGS_PIDFILE},
589                {"chroot", required_argument, 0, LONG_ARGS_CHROOT},
590                {"gid", required_argument, 0, LONG_ARGS_GID},
591                {"uid", required_argument, 0, LONG_ARGS_UID},
592                {"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
593                {"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
594                {"paste", required_argument, 0, LONG_ARGS_PASTE},
595                {"sync-log", no_argument, &uwsgi.synclog, 1},
596                {"no-server", no_argument, &no_server, 1},
597                {"no-defer-accept", no_argument, &uwsgi.no_defer_accept, 1},
598                {"limit-as", required_argument, 0, LONG_ARGS_LIMIT_AS},
599                {"udp", required_argument, 0, LONG_ARGS_UDP},
600                {"check-interval", required_argument, 0, LONG_ARGS_CHECK_INTERVAL},
601                {"erlang", required_argument, 0, LONG_ARGS_ERLANG},
602                {"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
603                {"nagios", no_argument, &nagios, 1},
604                {"binary-path", required_argument, 0, LONG_ARGS_BINARY_PATH},
605                {"proxy", required_argument, 0, LONG_ARGS_PROXY},
606                {"proxy-node", required_argument, 0, LONG_ARGS_PROXY_NODE},
607                {"proxy-max-connections", required_argument, 0, LONG_ARGS_PROXY_MAX_CONNECTIONS},
608                {"wsgi-file", required_argument, 0, LONG_ARGS_WSGI_FILE},
609                {"version", no_argument, 0, LONG_ARGS_VERSION},
610                {0, 0, 0, 0}
611        };
612#endif
613
614
615        gettimeofday (&uwsgi.start_tv, NULL);
616
617        setlinebuf (stdout);
618
619        uwsgi.rl.rlim_cur = 0;
620        uwsgi.rl.rlim_max = 0;
621
622
623        env_reloads = getenv("UWSGI_RELOADS");
624        if (env_reloads) {
625                // convert env value to int
626                reloads = atoi(env_reloads);
627                reloads++;
628                // convert reloads to string
629                rlen = snprintf(env_reload_buf, 10, "%u", reloads) ;
630                if (rlen > 0) {
631                        env_reload_buf[rlen] = 0 ;
632                        if (setenv("UWSGI_RELOADS",env_reload_buf, 1)) {
633                                perror("setenv()");
634                        }
635                }
636        }
637        else {
638                if (setenv("UWSGI_RELOADS","0", 1)) {
639                        perror("setenv()");
640                }
641        }
642
643        socket_type_len = sizeof (int);
644        if (!getsockopt (3, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) {
645                if (socket_type == SOCK_STREAM && reloads > 0) {
646                        fprintf (stderr, "...fd 3 is a socket, i suppose this is a graceful reload of uWSGI, i will try to do my best...\n");
647                        uwsgi.is_a_reload = 1;
648#ifdef UNBIT
649                        /* discard the 3'th fd as we will use the fd 0 */
650                        close (3);
651#else
652                        uwsgi.serverfd = 3;
653#endif
654                }
655        }
656
657        uwsgi.binary_path = argv[0] ;
658
659#ifndef UNBIT
660        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) {
661#else
662        while ((i = getopt (argc, argv, "p:t:mTPiv:b:rMR:Sz:w:C:j:H:A:EQ:L")) != -1) {
663#endif
664                manage_opt(i, optarg);
665
666        }
667
668#ifdef UWSGI_XML
669        if (uwsgi.xml_config != NULL) {
670                uwsgi_xml_config (&wsgi_req, long_options);
671        }
672#endif
673
674        if (uwsgi.binary_path == argv[0]) {
675                cwd = uwsgi_get_cwd ();
676                uwsgi.binary_path = malloc (strlen (argv[0]) + 1);
677                if (uwsgi.binary_path == NULL) {
678                        perror ("malloc()");
679                        exit (1);
680                }
681                strcpy (uwsgi.binary_path, argv[0]);
682        }
683
684#ifndef UNBIT
685        if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
686#endif
687                if (uwsgi.test_module == NULL) {
688                        fprintf (stderr, "*** Starting uWSGI %s (%dbit) on [%.*s] ***\n", UWSGI_VERSION, (int) (sizeof (void *)) * 8, 24, ctime ((const time_t *) &uwsgi.start_tv.tv_sec));
689                }
690#ifndef UNBIT
691        }
692        else {
693                fprintf (stderr, "*** 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));
694        }
695#endif
696
697#ifdef __BIG_ENDIAN__
698        fprintf (stderr, "*** big endian arch detected ***\n");
699#endif
700
701#ifdef PYTHREE
702        fprintf (stderr, "*** Warning Python3.x support is experimental, do not use it in production environment ***\n");
703#endif
704
705        fprintf (stderr, "Python version: %s\n", Py_GetVersion ());
706
707#ifndef UNBIT
708        if (!getuid ()) {
709                fprintf (stderr, "uWSGI running as root, you can use --uid/--gid/--chroot options\n");
710                if (uwsgi.chroot) {
711                        fprintf (stderr, "chroot() to %s\n", uwsgi.chroot);
712                        if (chroot (uwsgi.chroot)) {
713                                perror ("chroot()");
714                                exit (1);
715                        }
716#ifdef __linux__
717                        if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
718                                fprintf (stderr, "*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
719                        }
720#endif
721                }
722                if (uwsgi.gid) {
723                        fprintf (stderr, "setgid() to %d\n", uwsgi.gid);
724                        if (setgid (uwsgi.gid)) {
725                                perror ("setgid()");
726                                exit (1);
727                        }
728                }
729                if (uwsgi.uid) {
730                        fprintf (stderr, "setuid() to %d\n", uwsgi.uid);
731                        if (setuid (uwsgi.uid)) {
732                                perror ("setuid()");
733                                exit (1);
734                        }
735                }
736
737                if (!getuid()) {
738                        fprintf(stderr," *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
739                }
740        }
741        else {
742                if (uwsgi.chroot) {
743                        fprintf (stderr, "cannot chroot() as non-root user\n");
744                        exit (1);
745                }
746                if (uwsgi.gid) {
747                        fprintf (stderr, "cannot setgid() as non-root user\n");
748                        exit (1);
749                }
750                if (uwsgi.uid) {
751                        fprintf (stderr, "cannot setuid() as non-root user\n");
752                        exit (1);
753                }
754        }
755
756       
757
758#endif
759
760#ifndef UNBIT
761        if (uwsgi.rl.rlim_max > 0) {
762                fprintf (stderr, "limiting address space of processes...\n");
763                if (setrlimit (RLIMIT_AS, &uwsgi.rl)) {
764                        perror ("setrlimit()");
765                }
766        }
767#endif
768
769        if (!getrlimit (RLIMIT_AS, &uwsgi.rl)) {
770#ifndef UNBIT
771                // check for overflow
772                if ((sizeof (void *) == 4 && (uint32_t) uwsgi.rl.rlim_max < UINT32_MAX) || (sizeof (void *) == 8 && (uint64_t) uwsgi.rl.rlim_max < UINT64_MAX)) {
773#endif
774                        fprintf (stderr, "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);
775#ifndef UNBIT
776                }
777#endif
778        }
779
780        uwsgi.page_size = getpagesize ();
781        fprintf (stderr, "your memory page size is %d bytes\n", uwsgi.page_size);
782
783
784        if (uwsgi.synclog) {
785                fprintf (stderr, "allocating a memory page for synced logging.\n");
786                uwsgi.sync_page = malloc (uwsgi.page_size);
787                if (!uwsgi.sync_page) {
788                        perror ("malloc()");
789                        exit (1);
790                }
791        }
792
793        if (uwsgi.pyhome != NULL) {
794                fprintf (stderr, "Setting PythonHome to %s...\n", uwsgi.pyhome);
795#ifdef PYTHREE
796                wchar_t *wpyhome;
797                wpyhome = malloc ((sizeof (wchar_t) * strlen (uwsgi.pyhome)) + 2);
798                if (!wpyhome) {
799                        perror ("malloc()");
800                        exit (1);
801                }
802                mbstowcs (wpyhome, uwsgi.pyhome, strlen (uwsgi.pyhome));
803                Py_SetPythonHome (wpyhome);
804                free (wpyhome);
805#else
806                Py_SetPythonHome (uwsgi.pyhome);
807#endif
808        }
809
810
811
812
813#ifdef PYTHREE
814        wchar_t pname[6];
815        mbstowcs (pname, "uWSGI", 6);
816        Py_SetProgramName (pname);
817#else
818        Py_SetProgramName ("uWSGI");
819#endif
820
821
822        Py_Initialize ();
823
824        pyargv[0] = "uwsgi";
825
826        if (uwsgi.pyargv != NULL) {
827                char *ap;
828                while ((ap = strsep (&uwsgi.pyargv, " \t")) != NULL) {
829                        if (*ap != '\0') {
830                                pyargv[pyargc] = ap;
831                                pyargc++;
832                        }
833                        if (pyargc + 1 > MAX_PYARGV)
834                                break;
835                }
836        }
837
838        PySys_SetArgv (pyargc, pyargv);
839
840
841        uwsgi.py_apps = PyDict_New ();
842        if (!uwsgi.py_apps) {
843                PyErr_Print ();
844                exit (1);
845        }
846
847
848        wsgi_spitout = PyCFunction_New (uwsgi_spit_method, NULL);
849        wsgi_writeout = PyCFunction_New (uwsgi_write_method, NULL);
850
851#ifdef UWSGI_EMBEDDED
852        uwsgi_module = Py_InitModule ("uwsgi", null_methods);
853        if (uwsgi_module == NULL) {
854                fprintf (stderr, "could not initialize the uwsgi python module\n");
855                exit (1);
856        }
857        if (uwsgi.sharedareasize > 0) {
858#ifndef __OpenBSD__
859                uwsgi.sharedareamutex = mmap (NULL, sizeof (pthread_mutexattr_t) + sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
860                if (!uwsgi.sharedareamutex) {
861                        perror ("mmap()");
862                        exit (1);
863                }
864#else
865                fprintf (stderr, "***WARNING*** the sharedarea on OpenBSD is not SMP-safe. Beware of race conditions !!!\n");
866#endif
867                uwsgi.sharedarea = mmap (NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
868                if (uwsgi.sharedarea) {
869                        fprintf (stderr, "shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea);
870
871#ifdef __APPLE__
872                        memset (uwsgi.sharedareamutex, 0, sizeof (OSSpinLock));
873#else
874#ifndef __OpenBSD__
875                        if (pthread_mutexattr_init ((pthread_mutexattr_t *) uwsgi.sharedareamutex)) {
876                                fprintf (stderr, "unable to allocate mutexattr structure\n");
877                                exit (1);
878                        }
879                        if (pthread_mutexattr_setpshared ((pthread_mutexattr_t *) uwsgi.sharedareamutex, PTHREAD_PROCESS_SHARED)) {
880                                fprintf (stderr, "unable to share mutex\n");
881                                exit (1);
882                        }
883                        if (pthread_mutex_init ((pthread_mutex_t *) uwsgi.sharedareamutex + sizeof (pthread_mutexattr_t), (pthread_mutexattr_t *) uwsgi.sharedareamutex)) {
884                                fprintf (stderr, "unable to initialize mutex\n");
885                                exit (1);
886                        }
887#endif
888#endif
889
890                }
891                else {
892                        perror ("mmap()");
893                        exit (1);
894                }
895
896        }
897
898        init_uwsgi_embedded_module ();
899#endif
900
901
902
903#ifdef UWSGI_ONEAPP
904
905
906        wi = malloc (sizeof (struct uwsgi_app));
907        if (wi == NULL) {
908                perror ("malloc()");
909                exit (1);
910        }
911        memset (wi, 0, sizeof (struct uwsgi_app));
912
913        // load wsgi module/script
914        for (i = optind; i < argc; i++) {
915                init_uwsgi_vars ();
916                wi->wsgi_module = PyImport_ImportModule (argv[i]);
917                if (!wi->wsgi_module) {
918                        PyErr_Print ();
919                        exit (1);
920                }
921                wi->wsgi_dict = PyModule_GetDict (wi->wsgi_module);
922                if (!wi->wsgi_dict) {
923                        PyErr_Print ();
924                        exit (1);
925                }
926                wi->wsgi_callable = PyDict_GetItemString (wi->wsgi_dict, "application");
927                if (!wi->wsgi_callable) {
928                        PyErr_Print ();
929                        exit (1);
930                }
931                wi->wsgi_environ = PyDict_New ();
932                if (!wi->wsgi_environ) {
933                        PyErr_Print ();
934                        exit (1);
935                }
936
937                wi->wsgi_harakiri = PyDict_GetItemString (wi->wsgi_dict, "harakiri");
938
939                wi->wsgi_args = PyTuple_New (2);
940                if (!wi->wsgi_args) {
941                        PyErr_Print ();
942                        exit (1);
943                }
944                if (PyTuple_SetItem (wi->wsgi_args, 0, wi->wsgi_environ)) {
945                        PyErr_Print ();
946                        exit (1);
947                }
948                if (PyTuple_SetItem (wi->wsgi_args, 1, wsgi_spitout)) {
949                        PyErr_Print ();
950                        exit (1);
951                }
952                break;
953        }
954
955        if (!wi->wsgi_module) {
956                fprintf (stderr, "unable to find the wsgi script. Have you specified it ?\n");
957                exit (1);
958        }
959#endif
960
961        Py_OptimizeFlag = uwsgi.py_optimize;
962
963        uwsgi.main_thread = PyThreadState_Get ();
964
965
966#ifdef UWSGI_THREADING
967        if (uwsgi.has_threads) {
968                PyEval_InitThreads ();
969                fprintf (stderr, "threads support enabled\n");
970        }
971
972#endif
973
974        if (uwsgi.buffer_size > 65536) {
975                fprintf (stderr, "invalid buffer size.\n");
976                exit (1);
977        }
978        uwsgi.buffer = malloc (uwsgi.buffer_size);
979        if (uwsgi.buffer == NULL) {
980                fprintf (stderr, "unable to allocate memory for buffer.\n");
981                exit (1);
982        }
983
984        fprintf (stderr, "request/response buffer (%d bytes) allocated.\n", uwsgi.buffer_size);
985
986#ifdef UWSGI_NAGIOS
987        if (nagios) {
988                // connect and send
989                if (uwsgi.socket_name == NULL) {
990                        fprintf(stdout,"UWSGI UNKNOWN: you have specified an invalid socket\n");
991                        exit(3);
992                }
993                char *tcp_port = strchr (uwsgi.socket_name, ':');
994                if (tcp_port == NULL) {
995                        fprintf(stdout,"UWSGI UNKNOWN: you have specified an invalid socket\n");
996                        exit(3);
997                }
998
999                tcp_port[0] = 0 ;
1000
1001                uwsgi_poll.fd = connect_to_tcp(uwsgi.socket_name, atoi(tcp_port+1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
1002                if (uwsgi_poll.fd < 0) {
1003                        fprintf(stdout,"UWSGI CRITICAL: could not connect() to workers\n");
1004                        exit(2);
1005                }
1006                wsgi_req.modifier = UWSGI_MODIFIER_PING ;
1007                wsgi_req.size = 0 ;
1008                wsgi_req.modifier_arg = 0 ;
1009                if (write(uwsgi_poll.fd, &wsgi_req, 4) != 4) {
1010                        perror("write()");
1011                        fprintf(stdout,"UWSGI CRITICAL: could not send ping packet to workers\n");
1012                        exit(2);
1013                }
1014                uwsgi_poll.events = POLLIN ;
1015                if (!uwsgi_parse_response (&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) &wsgi_req, uwsgi.buffer)) {
1016                        fprintf(stdout,"UWSGI CRITICAL: timed out waiting for response\n");
1017                        exit(2);       
1018                }
1019                else {
1020                        if (wsgi_req.size > 0) {
1021                                fprintf(stdout,"UWSGI WARNING: %.*s\n", wsgi_req.size, uwsgi.buffer);
1022                                exit(1);
1023                        }
1024                        else {
1025                                fprintf(stdout,"UWSGI OK: armed and ready\n");
1026                                exit(0);
1027                        }
1028                }
1029
1030                // never here
1031                fprintf(stdout,"UWSGI UNKNOWN: probably you hit a bug of uWSGI !!!\n");
1032                exit(3);
1033               
1034        }
1035#endif
1036
1037        if (!no_server) {
1038#ifndef UNBIT
1039                if (uwsgi.socket_name != NULL && !uwsgi.is_a_reload) {
1040#ifdef UWSGI_SCTP
1041                        if (!strncmp (uwsgi.socket_name, "sctp:", 5)) {
1042                                char *sctp_port = strchr (uwsgi.socket_name + 5, ':');
1043                                if (sctp_port == NULL) {
1044                                        fprintf (stderr, "invalid SCTP port ! syntax: sctp:ip1,ip2,ipN:port\n");
1045                                        exit (1);
1046                                }
1047                                uwsgi.serverfd = bind_to_sctp (uwsgi.socket_name + 5, uwsgi.listen_queue, sctp_port);
1048                                i_am_sctp = 1;
1049                        }
1050                        else {
1051#endif
1052                                char *tcp_port = strchr (uwsgi.socket_name, ':');
1053                                if (tcp_port == NULL) {
1054                                        uwsgi.serverfd = bind_to_unix (uwsgi.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
1055                                }
1056                                else {
1057                                        uwsgi.serverfd = bind_to_tcp (uwsgi.socket_name, uwsgi.listen_queue, tcp_port);
1058                                }
1059
1060                                if (uwsgi.serverfd < 0) {
1061                                        fprintf (stderr, "unable to create the server socket.\n");
1062                                        exit (1);
1063                                }
1064#ifdef UWSGI_SCTP
1065                        }
1066#endif
1067                }
1068#endif
1069
1070                socket_type_len = sizeof (int);
1071                if (getsockopt (uwsgi.serverfd, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) {
1072                        //perror ("getsockopt()");
1073                        uwsgi.numproc = 0 ;
1074                }
1075
1076#ifdef UWSGI_PROXY
1077                if (uwsgi.proxy_socket_name) {
1078                        uwsgi.shared->proxy_pid = proxy_start(uwsgi.master_process);
1079                }
1080#endif
1081
1082
1083        }
1084
1085#ifdef UWSGI_PROXY
1086        if (uwsgi.numproc == 0 && (!uwsgi.proxy_socket_name || uwsgi.shared->proxy_pid <= 0)) {
1087#else
1088        if (uwsgi.numproc == 0) {
1089#endif
1090                fprintf(stderr, "The -s/--socket option is missing and stdin is not a socket.\n");
1091                exit (1);
1092        }
1093
1094
1095
1096#ifndef UNBIT
1097        fprintf (stderr, "your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
1098#endif
1099
1100
1101        if (uwsgi.single_interpreter == 1) {
1102                init_uwsgi_vars ();
1103        }
1104
1105        memset (uwsgi.wsgi_apps, 0, sizeof (uwsgi.wsgi_apps));
1106
1107
1108
1109        uwsgi.poll.events = POLLIN;
1110
1111        memset (&wsgi_req, 0, sizeof (struct wsgi_request));
1112
1113        /* shared area for workers */
1114        uwsgi.workers = (struct uwsgi_worker *) mmap (NULL, sizeof (struct uwsgi_worker) * uwsgi.numproc + 1, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1115        if (!uwsgi.workers) {
1116                perror ("mmap()");
1117                exit (1);
1118        }
1119        memset (uwsgi.workers, 0, sizeof (struct uwsgi_worker) * uwsgi.numproc + 1);
1120
1121        uwsgi.mypid = getpid ();
1122        masterpid = uwsgi.mypid;
1123
1124#ifndef UNBIT
1125        if (uwsgi.pidfile) {
1126                fprintf (stderr, "writing pidfile to %s\n", uwsgi.pidfile);
1127                pidfile = fopen (uwsgi.pidfile, "w");
1128                if (!pidfile) {
1129                        perror ("fopen");
1130                        exit (1);
1131                }
1132                if (fprintf (pidfile, "%d\n", masterpid) < 0) {
1133                        fprintf (stderr, "could not write pidfile.\n");
1134                }
1135                fclose (pidfile);
1136        }
1137#endif
1138
1139
1140        /* save the masterpid */
1141        uwsgi.workers[0].pid = masterpid;
1142
1143        fprintf(stderr,"initializing hooks...");
1144
1145        uwsgi.shared->hooks[0] = uwsgi_request_wsgi ;
1146        uwsgi.shared->after_hooks[0] = uwsgi_after_request_wsgi ;
1147
1148        uwsgi.shared->hooks[UWSGI_MODIFIER_ADMIN_REQUEST] = uwsgi_request_admin ; //10
1149#ifdef UWSGI_SPOOLER
1150        uwsgi.shared->hooks[UWSGI_MODIFIER_SPOOL_REQUEST] = uwsgi_request_spooler ; //17
1151#endif
1152        uwsgi.shared->hooks[UWSGI_MODIFIER_FASTFUNC] = uwsgi_request_fastfunc ; //26
1153
1154        uwsgi.shared->hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_request_wsgi ; // 30
1155        uwsgi.shared->after_hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_after_request_wsgi; // 30
1156
1157        uwsgi.shared->hooks[UWSGI_MODIFIER_MESSAGE_MARSHAL] = uwsgi_request_marshal ; //33
1158        uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping ; //100
1159
1160        fprintf(stderr,"done.\n");
1161
1162#ifdef UWSGI_ERLANG
1163        if (uwsgi.erlang_node) {
1164                uwsgi.erlang_nodes = 1;
1165                uwsgi.erlangfd = init_erlang(uwsgi.erlang_node, uwsgi.erlang_cookie);
1166        }
1167#endif
1168
1169
1170
1171        if (uwsgi.wsgi_config != NULL) {
1172                uwsgi_wsgi_config ();
1173        }
1174        else if (uwsgi.wsgi_file != NULL) {
1175                uwsgi_wsgi_file_config();
1176        }
1177#ifdef UWSGI_XML
1178        else if (uwsgi.xml_config != NULL) {
1179                uwsgi_xml_config (&wsgi_req, NULL);
1180        }
1181#endif
1182
1183#ifdef UWSGI_PASTE
1184        else if (uwsgi.paste != NULL) {
1185                uwsgi_paste_config ();
1186        }
1187#endif
1188
1189        if (uwsgi.test_module != NULL) {
1190                if (PyImport_ImportModule (uwsgi.test_module)) {
1191                        exit (0);
1192                }
1193                exit (1);
1194        }
1195
1196
1197
1198#ifndef UNBIT
1199        if (no_server) {
1200                fprintf (stderr, "no-server mode requested. Goodbye.\n");
1201                exit (0);
1202        }
1203#endif
1204
1205// is this a proxy only worker ?
1206
1207        if (!uwsgi.master_process && uwsgi.numproc == 0) {
1208                exit(0);
1209        }
1210
1211        if (!uwsgi.single_interpreter) {
1212                fprintf(stderr,"*** uWSGI is running in multiple interpreter mode !!! ***\n");
1213        }
1214
1215        /* preforking() */
1216        if (uwsgi.master_process) {
1217                if (uwsgi.is_a_reload) {
1218                        fprintf (stderr, "gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
1219                }
1220                else {
1221                        fprintf (stderr, "spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
1222                }
1223        }
1224
1225#ifdef UNBIT
1226        if (single_app_mode == 1) {
1227                wsgi_req.wsgi_script = getenv ("UWSGI_SCRIPT");
1228                if (wsgi_req.wsgi_script) {
1229                        wsgi_req.wsgi_script_len = strlen (wsgi_req.wsgi_script);
1230                }
1231                else {
1232                        fprintf (stderr, "UWSGI_SCRIPT env var not set !\n");
1233                        exit (1);
1234                }
1235
1236                init_uwsgi_app (NULL, NULL);
1237        }
1238#endif
1239
1240#ifdef UWSGI_SPOOLER
1241        if (spool_dir != NULL && uwsgi.numproc > 0) {
1242                uwsgi.shared->spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module);
1243        }
1244#endif
1245
1246
1247        if (!uwsgi.master_process) {
1248                if (uwsgi.numproc == 1) {
1249                        fprintf (stderr, "spawned uWSGI worker 1 (and the only) (pid: %d)\n", masterpid);
1250                }
1251                else {
1252                        fprintf (stderr, "spawned uWSGI worker 1 (pid: %d)\n", masterpid);
1253                }
1254                uwsgi.workers[1].pid = masterpid;
1255                uwsgi.workers[1].id = 1;
1256                uwsgi.workers[1].last_spawn = time (NULL);
1257                uwsgi.workers[1].manage_next_request = 1;
1258#ifdef UWSGI_THREADING
1259                uwsgi.workers[1].i_have_gil = 1;
1260#endif
1261                uwsgi.mywid = 1;
1262                gettimeofday (&last_respawn, NULL);
1263                respawn_delta = last_respawn.tv_sec;
1264        }
1265
1266
1267                for (i = 2-uwsgi.master_process ; i < uwsgi.numproc + 1; i++) {
1268                        /* let the worker know his worker_id (wid) */
1269                        pid = fork ();
1270                        if (pid == 0) {
1271                                uwsgi.mypid = getpid ();
1272                                uwsgi.workers[i].pid = uwsgi.mypid;
1273                                uwsgi.workers[i].id = i;
1274                                uwsgi.workers[i].last_spawn = time (NULL);
1275                                uwsgi.workers[i].manage_next_request = 1;
1276#ifdef UWSGI_THREADING
1277                                uwsgi.workers[i].i_have_gil = 1;
1278#endif
1279                                uwsgi.mywid = i;
1280                                if (uwsgi.serverfd != 0 && uwsgi.master_process == 1) {
1281                                        /* close STDIN for workers */
1282                                        close (0);
1283                                }
1284                                break;
1285                        }
1286                        else if (pid < 1) {
1287                                perror ("fork()");
1288                                exit (1);
1289                        }
1290                        else {
1291                                fprintf (stderr, "spawned uWSGI worker %d (pid: %d)\n", i, pid);
1292                                gettimeofday (&last_respawn, NULL);
1293                                respawn_delta = last_respawn.tv_sec;
1294                        }
1295                }
1296
1297
1298        if (getpid () == masterpid && uwsgi.master_process == 1) {
1299                /* route signals to workers... */
1300                signal (SIGHUP, (void *) &grace_them_all);
1301                signal (SIGTERM, (void *) &reap_them_all);
1302                signal (SIGINT, (void *) &kill_them_all);
1303                signal (SIGQUIT, (void *) &kill_them_all);
1304                /* used only to avoid human-errors */
1305#ifndef UNBIT
1306                signal (SIGUSR1, (void *) &stats);
1307#endif
1308
1309                if (udp_socket) {
1310                        uwsgi_poll.fd = bind_to_udp (udp_socket);
1311                        if (uwsgi_poll.fd < 0) {
1312                                fprintf (stderr, "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n");
1313                        }
1314                        else {
1315                                fprintf (stderr, "UDP server enabled.\n");
1316                                uwsgi_poll.events = POLLIN;
1317                        }
1318                }
1319                for (;;) {
1320                        if (ready_to_die >= uwsgi.numproc && uwsgi.to_hell) {
1321#ifdef UWSGI_SPOOLER
1322                                if (spool_dir && uwsgi.shared->spooler_pid > 0) {
1323                                        kill (uwsgi.shared->spooler_pid, SIGKILL);
1324                                        fprintf(stderr,"killed the spooler with pid %d\n", uwsgi.shared->spooler_pid);
1325                                }
1326
1327#endif
1328
1329#ifdef UWSGI_PROXY
1330                                if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1331                                        kill (uwsgi.shared->proxy_pid, SIGKILL);
1332                                        fprintf(stderr,"killed proxy with pid %d\n", uwsgi.shared->proxy_pid);
1333                                }
1334#endif
1335                                fprintf (stderr, "goodbye to uWSGI.\n");
1336                                exit (0);
1337                        }
1338                        if (ready_to_reload >= uwsgi.numproc && uwsgi.to_heaven) {
1339#ifdef UWSGI_SPOOLER
1340                                if (spool_dir && uwsgi.shared->spooler_pid > 0) {
1341                                        kill (uwsgi.shared->spooler_pid, SIGKILL);
1342                                        fprintf(stderr,"wait4() the spooler with pid %d...", uwsgi.shared->spooler_pid);
1343                                        diedpid = waitpid(uwsgi.shared->spooler_pid, &waitpid_status, 0);
1344                                        fprintf(stderr,"done.");
1345                                }
1346#endif
1347
1348#ifdef UWSGI_PROXY
1349                                if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1350                                        kill (uwsgi.shared->proxy_pid, SIGKILL);
1351                                        fprintf(stderr,"wait4() the proxy with pid %d...", uwsgi.shared->proxy_pid);
1352                                        diedpid = waitpid(uwsgi.shared->proxy_pid, &waitpid_status, 0);
1353                                        fprintf(stderr,"done.");
1354                                }
1355#endif
1356                                fprintf (stderr, "binary reloading uWSGI...\n");
1357                                if (cwd) {
1358                                        if (chdir (cwd)) {
1359                                                perror ("chdir()");
1360                                                exit (1);
1361                                        }
1362                                }
1363                                /* check fd table (a module can obviosly open some fd on initialization...) */
1364                                fprintf (stderr, "closing all fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf (_SC_OPEN_MAX));
1365                                for (i = 3; i < sysconf (_SC_OPEN_MAX); i++) {
1366                                        if (i == uwsgi.serverfd) {
1367                                                continue;
1368                                        }
1369                                        close (i);
1370                                }
1371                                if (uwsgi.serverfd != 3) {
1372                                        if (dup2 (uwsgi.serverfd, 3) < 0) {
1373                                                perror ("dup2()");
1374                                                exit (1);
1375                                        }
1376                                }
1377                                fprintf (stderr, "running %s\n", uwsgi.binary_path);
1378                                argv[0] = uwsgi.binary_path ;
1379                                //strcpy (argv[0], uwsgi.binary_path);
1380                                execve (uwsgi.binary_path, argv, environ);
1381                                perror ("execve()");
1382                                // never here
1383                                exit (1);
1384                        }
1385                        diedpid = waitpid (WAIT_ANY, &waitpid_status, WNOHANG);
1386                        if (diedpid == -1) {
1387                                perror ("waitpid()");
1388                                /* here is better to reload all the uWSGI stack */
1389                                fprintf (stderr, "something horrible happened...\n");
1390                                reap_them_all ();
1391                                exit (1);
1392                        }
1393                        else if (diedpid == 0) {
1394                                /* PLEASE, do not run python threads in the master process, you can potentially destroy the world,
1395                                   we support this for hyperultramegagodprogrammer and systems
1396                                 */
1397#ifdef UWSGI_THREADING
1398                                if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
1399                                        uwsgi._save = PyEval_SaveThread ();
1400                                        uwsgi.workers[uwsgi.mywid].i_have_gil = 0;
1401                                }
1402#endif
1403                                /* all processes ok, doing status scan after N seconds */
1404                                check_interval.tv_sec = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
1405                                if (!check_interval.tv_sec)
1406                                        check_interval.tv_sec = 1;
1407                               
1408                                if (udp_socket && uwsgi_poll.fd >= 0) {
1409                                        rlen = poll (&uwsgi_poll, 1, check_interval.tv_sec * 1000);
1410                                        if (rlen < 0) {
1411                                                perror ("poll()");
1412                                        }
1413                                        else if (rlen > 0) {
1414                                                udp_len = sizeof (udp_client);
1415                                                rlen = recvfrom (uwsgi_poll.fd, uwsgi.buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
1416                                                if (rlen < 0) {
1417                                                        perror ("recvfrom()");
1418                                                }
1419                                                else if (rlen > 0) {
1420                                                        memset (udp_client_addr, 0, 16);
1421                                                        if (inet_ntop (AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
1422                                                                fprintf (stderr, "received udp packet of %d bytes from %s:%d\n", rlen, udp_client_addr, ntohs (udp_client.sin_port));
1423#ifdef UWSGI_SNMP
1424                                                                if (uwsgi.buffer[0] == 0x30) {
1425                                                                        manage_snmp (uwsgi_poll.fd, (uint8_t *) uwsgi.buffer, rlen, &udp_client);
1426                                                                }
1427#endif
1428                                                        }
1429                                                        else {
1430                                                                perror ("inet_ntop()");
1431                                                        }
1432                                                }
1433                                        }
1434                                }
1435                                else {
1436                                        select (0, NULL, NULL, NULL, &check_interval);
1437                                }
1438                                master_cycles++;
1439                                working_workers = 0;
1440                                blocking_workers = 0;
1441#ifdef UWSGI_THREADING
1442                                if (uwsgi.has_threads && !uwsgi.workers[uwsgi.mywid].i_have_gil) {
1443                                        PyEval_RestoreThread (uwsgi._save);
1444                                        uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
1445                                }
1446#endif
1447                                check_interval.tv_sec = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
1448                                if (!check_interval.tv_sec)
1449                                        check_interval.tv_sec = 1;
1450                                for (i = 1; i <= uwsgi.numproc; i++) {
1451                                        /* first check for harakiri */
1452                                        if (uwsgi.workers[i].harakiri > 0) {
1453                                                if (uwsgi.workers[i].harakiri < time (NULL)) {
1454                                                        /* first try to invoke the harakiri() custom handler */
1455                                                        /* TODO */
1456                                                        /* then brutally kill the worker */
1457                                                        kill (uwsgi.workers[i].pid, SIGKILL);
1458                                                }
1459                                        }
1460                                        /* load counters */
1461                                        if (uwsgi.workers[i].status & UWSGI_STATUS_IN_REQUEST)
1462                                                working_workers++;
1463
1464                                        if (uwsgi.workers[i].status & UWSGI_STATUS_BLOCKING)
1465                                                blocking_workers++;
1466
1467                                        uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
1468                                }
1469
1470                                // check for cluster nodes
1471                                for(i=0;i<MAX_CLUSTER_NODES;i++) {
1472                                        struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
1473                                       
1474                                        if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_FAILED) {
1475                                                // should i retry ?
1476                                                if (master_cycles % ucn->errors == 0) {
1477                                                        if (!uwsgi_ping_node(i, &wsgi_req)) {
1478                                                                ucn->status = UWSGI_NODE_OK ;
1479                                                                fprintf(stderr,"re-enabled cluster node %d/%s\n", i, ucn->name);
1480                                                        }
1481                                                        else {
1482                                                                ucn->errors++;
1483                                                        }
1484                                                }
1485                                        }
1486                                }
1487
1488                                continue;
1489
1490                        }
1491#ifdef UWSGI_SPOOLER
1492                        /* reload the spooler */
1493                        if (spool_dir && uwsgi.shared->spooler_pid > 0) {
1494                                if (diedpid == uwsgi.shared->spooler_pid) {
1495                                        fprintf(stderr,"OOOPS the spooler is no more...trying respawn...\n");
1496                                        uwsgi.shared->spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module);
1497                                        continue;
1498                                }
1499                        }
1500#endif
1501
1502#ifdef UWSGI_PROXY
1503                        /* reload the proxy (can be the only process running) */
1504                        if (uwsgi.proxy_socket_name && uwsgi.shared->proxy_pid > 0) {
1505                                if (diedpid == uwsgi.shared->proxy_pid) {
1506                                        if (WIFEXITED (waitpid_status)) {
1507                                                if (WEXITSTATUS (waitpid_status) != UWSGI_END_CODE) {   
1508                                                        fprintf(stderr,"OOOPS the proxy is no more...trying respawn...\n");
1509                                                        uwsgi.shared->spooler_pid = proxy_start(1);
1510                                                        continue;
1511                                                }
1512                                        }
1513                                }
1514                        }
1515#endif
1516                        /* check for reloading */
1517                        if (WIFEXITED (waitpid_status)) {
1518                                if (WEXITSTATUS (waitpid_status) == UWSGI_RELOAD_CODE && uwsgi.to_heaven) {
1519                                        ready_to_reload++;
1520                                        continue;
1521                                }
1522                                else if (WEXITSTATUS (waitpid_status) == UWSGI_END_CODE && uwsgi.to_hell) {
1523                                        ready_to_die++;
1524                                        continue;
1525                                }
1526                        }
1527
1528                        fprintf (stderr, "DAMN ! process %d died :( trying respawn ...\n", diedpid);
1529                        gettimeofday (&last_respawn, NULL);
1530                        if (last_respawn.tv_sec == respawn_delta) {
1531                                fprintf (stderr, "worker respawning too fast !!! i have to sleep a bit...\n");
1532                                /* TODO, user configurable fork throttler */
1533                                sleep (2);
1534                        }
1535                        gettimeofday (&last_respawn, NULL);
1536                        respawn_delta = last_respawn.tv_sec;
1537                        uwsgi.mywid = find_worker_id (diedpid);
1538                        pid = fork ();
1539                        if (pid == 0) {
1540                                uwsgi.mypid = getpid ();
1541                                uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
1542                                uwsgi.workers[uwsgi.mywid].harakiri = 0;
1543                                uwsgi.workers[uwsgi.mywid].requests = 0;
1544                                uwsgi.workers[uwsgi.mywid].failed_requests = 0;
1545                                uwsgi.workers[uwsgi.mywid].respawn_count++;
1546                                uwsgi.workers[uwsgi.mywid].last_spawn = time (NULL);
1547                                uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
1548                                uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
1549                                break;
1550                        }
1551                        else if (pid < 1) {
1552                                perror ("fork()");
1553                        }
1554                        else {
1555                                fprintf (stderr, "Respawned uWSGI worker (new pid: %d)\n", pid);
1556#ifdef UWSGI_SPOOLER
1557                                if (uwsgi.mywid <= 0 && diedpid != uwsgi.shared->spooler_pid) {
1558#else
1559                                if (uwsgi.mywid <= 0) {
1560#endif
1561
1562#ifdef UWSGI_PROXY
1563                                        if (diedpid != uwsgi.shared->proxy_pid) {
1564#endif
1565                                                fprintf (stderr, "warning the died pid was not in the workers list. Probably you hit a BUG of uWSGI\n");
1566#ifdef UWSGI_PROXY
1567                                        }
1568#endif
1569                                }
1570                        }
1571                }
1572        }
1573
1574
1575
1576
1577        uwsgi.hvec = malloc (sizeof (struct iovec) * uwsgi.vec_size);
1578        if (uwsgi.hvec == NULL) {
1579                fprintf (stderr, "unable to allocate memory for iovec.\n");
1580                exit (1);
1581        }
1582
1583        if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) {
1584                signal (SIGALRM, (void *) &harakiri);
1585        }
1586
1587        /* gracefully reload */
1588        signal (SIGHUP, (void *) &gracefully_kill);
1589        /* close the process (useful for master INT) */
1590        signal (SIGINT, (void *) &end_me);
1591        /* brutally reload */
1592        signal (SIGTERM, (void *) &reload_me);
1593
1594
1595#ifndef UNBIT
1596        signal (SIGUSR1, (void *) &stats);
1597#endif
1598
1599
1600        signal (SIGPIPE, (void *) &warn_pipe);
1601
1602
1603#ifdef UWSGI_ERLANG
1604        if (uwsgi.erlang_nodes > 0) {
1605                if (uwsgi.numproc <= uwsgi.erlang_nodes) {
1606                        fprintf(stderr,"You do not have enough worker for Erlang. Please respawn with at least %d processes.\n", uwsgi.erlang_nodes+1);
1607                }
1608                else if ( uwsgi.mywid > (uwsgi.numproc - uwsgi.erlang_nodes) ) {
1609                        fprintf(stderr,"Erlang mode enabled for worker %d.\n", uwsgi.mywid);
1610                        erlang_loop();
1611                        // NEVER HERE
1612                        exit(1);
1613                }
1614        }
1615        // close the erlang server fd for python workers
1616        close(uwsgi.erlangfd);
1617#endif
1618
1619#ifdef UWSGI_THREADING
1620        // release the GIL
1621        if (uwsgi.has_threads) {
1622                uwsgi._save = PyEval_SaveThread ();
1623                uwsgi.workers[uwsgi.mywid].i_have_gil = 0;
1624        }
1625#endif
1626
1627
1628        while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
1629
1630
1631                wsgi_req.app_id = uwsgi.default_app;
1632#ifdef UWSGI_SENDFILE
1633                wsgi_req.sendfile_fd = -1;
1634#endif
1635                // clear all status bits
1636                UWSGI_CLEAR_STATUS ;
1637
1638                uwsgi.poll.fd = accept (uwsgi.serverfd, (struct sockaddr *) &c_addr, (socklen_t *) & c_len);
1639
1640                if (uwsgi.poll.fd < 0) {
1641                        perror ("accept()");
1642                        continue;
1643                }
1644
1645                UWSGI_SET_IN_REQUEST;
1646
1647                if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
1648                        gettimeofday (&wsgi_req.start_of_request, NULL);
1649
1650               
1651
1652#ifdef UWSGI_SCTP
1653                if (i_am_sctp == 1) {
1654                        // get stream id, and map it to uwsgi modifiers
1655                        struct sctp_status sstatus;
1656                        memset (&sstatus, 0, sizeof (sstatus));
1657                        socklen_t slen = sizeof (sstatus);
1658                        sstatus.sstat_assoc_id = 1;
1659                        if (getsockopt (uwsgi.poll.fd, IPPROTO_SCTP, SCTP_STATUS, &sstatus, &slen)) {
1660                                perror ("getsockopt()");
1661                        }
1662
1663                        memset (&sctp_ss, 0, sizeof (sctp_ss));
1664
1665                        fprintf (stderr, "%d %d\n", sstatus.sstat_instrms, sstatus.sstat_outstrms);
1666
1667                        i = 0;
1668                        wsgi_req.size = sctp_recvmsg (uwsgi.poll.fd, uwsgi.buffer, uwsgi.buffer_size, 0, 0, &sctp_ss, 0);
1669                        if (wsgi_req.size < 0) {
1670                                perror ("sctp_recvmsg()");
1671                        }
1672                        fprintf (stderr, "received uwsgi message of %d bytes on stream id %d flags %d\n", wsgi_req.size, ntohs (sctp_ss.sinfo_stream), i);
1673
1674                }
1675                else {
1676#endif
1677                        if (!uwsgi_parse_response (&uwsgi.poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) &wsgi_req, uwsgi.buffer)) {
1678                                continue;
1679                        }
1680#ifdef UWSGI_SCTP
1681                }
1682#endif
1683
1684                // enter harakiri mode
1685                if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
1686                        set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
1687                }
1688
1689                ret = (*uwsgi.shared->hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req);
1690                // calculate execution time
1691                gettimeofday(&wsgi_req.end_of_request, NULL) ;
1692                uwsgi.workers[uwsgi.mywid].running_time += (double) (( (double)(wsgi_req.end_of_request.tv_sec*1000000+wsgi_req.end_of_request.tv_usec)-(double)(wsgi_req.start_of_request.tv_sec*1000000+wsgi_req.start_of_request.tv_usec))/ (double)1000.0) ;
1693
1694
1695                // get memory usage
1696                if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1)
1697                        get_memusage();
1698
1699                // close the connection with the webserver
1700                close(uwsgi.poll.fd);
1701                uwsgi.workers[0].requests++;
1702                uwsgi.workers[uwsgi.mywid].requests++;
1703
1704                if (!ret)
1705                        (*uwsgi.shared->after_hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req);
1706
1707
1708                // leave harakiri mode
1709                if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
1710                        set_harakiri(0);
1711                }
1712
1713
1714                // defunct process reaper
1715                if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1) {
1716                        waitpid (-1, &waitpid_status, WNOHANG);
1717                }
1718                // reset request
1719                memset (&wsgi_req, 0, sizeof (struct wsgi_request));
1720#ifdef UNBIT
1721                if (tmp_filename && tmp_dir_fd >= 0) {
1722                        tmp_filename[0] = 0;
1723                }
1724#endif
1725
1726                if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
1727                        goodbye_cruel_world ();
1728                }
1729
1730#ifdef UNBIT
1731                if (check_for_memory_errors) {
1732                        if (syscall (357, &us, 0) > 0) {
1733                                if (us.memory_errors > 0) {
1734                                        fprintf (stderr, "Unbit Kernel found a memory allocation error for process %d.\n", uwsgi.mypid);
1735                                        goodbye_cruel_world ();
1736                                }
1737                        }
1738                }
1739#endif
1740
1741        }
1742
1743        if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
1744                reload_me ();
1745        }
1746        else {
1747                goodbye_cruel_world ();
1748        }
1749
1750        /* never here */
1751        return 0;
1752}
1753
1754void init_uwsgi_vars () {
1755
1756#ifndef UNBIT
1757        int i;
1758#endif
1759        PyObject *pysys, *pysys_dict, *pypath;
1760
1761        /* add cwd to pythonpath */
1762        pysys = PyImport_ImportModule ("sys");
1763        if (!pysys) {
1764                PyErr_Print ();
1765                exit (1);
1766        }
1767        pysys_dict = PyModule_GetDict (pysys);
1768        pypath = PyDict_GetItemString (pysys_dict, "path");
1769        if (!pypath) {
1770                PyErr_Print ();
1771                exit (1);
1772        }
1773        if (PyList_Insert (pypath, 0, PyString_FromString (".")) != 0) {
1774                PyErr_Print ();
1775        }
1776
1777#ifndef UNBIT
1778        for (i = 0; i < uwsgi.python_path_cnt; i++) {
1779                if (PyList_Insert (pypath, 0, PyString_FromString (uwsgi.python_path[i])) != 0) {
1780                        PyErr_Print ();
1781                }
1782                else {
1783                        fprintf (stderr, "added %s to pythonpath.\n", uwsgi.python_path[i]);
1784                }
1785        }
1786#endif
1787
1788}
1789
1790int init_uwsgi_app (PyObject * force_wsgi_dict, PyObject * my_callable) {
1791        PyObject *wsgi_module, *wsgi_dict = NULL;
1792        PyObject *pymain, *zero;
1793        PyObject *pycprof, *pycprof_dict;
1794        char tmpstring[256];
1795        int id;
1796
1797        struct uwsgi_app *wi;
1798
1799        memset (tmpstring, 0, 256);
1800
1801
1802        if (wsgi_req.wsgi_script_len == 0 && ((wsgi_req.wsgi_module_len == 0 || wsgi_req.wsgi_callable_len == 0) && uwsgi.wsgi_config == NULL && my_callable == NULL)) {
1803                fprintf (stderr, "invalid application (%.*s). skip.\n", wsgi_req.script_name_len, wsgi_req.script_name);
1804                return -1;
1805        }
1806
1807        if (uwsgi.wsgi_config && wsgi_req.wsgi_callable_len == 0 && my_callable == NULL) {
1808                fprintf (stderr, "invalid application (%.*s). skip.\n", wsgi_req.script_name_len, wsgi_req.script_name);
1809                return -1;
1810        }
1811
1812        if (wsgi_req.wsgi_script_len > 255 || wsgi_req.wsgi_module_len > 255 || wsgi_req.wsgi_callable_len > 255) {
1813                fprintf (stderr, "invalid application's string size. skip.\n");
1814                return -1;
1815        }
1816
1817        id = uwsgi.wsgi_cnt;
1818
1819
1820        if (wsgi_req.script_name_len == 0) {
1821                wsgi_req.script_name_len = 1;
1822                wsgi_req.script_name = (char *) app_slash;
1823                id = 0;
1824        }
1825        else if (wsgi_req.script_name_len == 1) {
1826                if (wsgi_req.script_name[0] == '/') {
1827                        id = 0;
1828                }
1829        }
1830
1831
1832        zero = PyString_FromStringAndSize (wsgi_req.script_name, wsgi_req.script_name_len);
1833        if (!zero) {
1834                Py_FatalError ("cannot get mountpoint python object !\n");
1835        }
1836
1837        if (PyDict_GetItem (uwsgi.py_apps, zero) != NULL) {
1838                Py_DECREF (zero);
1839                fprintf (stderr, "mountpoint %.*s already configured. skip.\n", wsgi_req.script_name_len, wsgi_req.script_name);
1840                return -1;
1841        }
1842
1843        Py_DECREF (zero);
1844
1845        wi = &uwsgi.wsgi_apps[id];
1846
1847        memset (wi, 0, sizeof (struct uwsgi_app));
1848
1849        if (uwsgi.single_interpreter == 0) {
1850                wi->interpreter = Py_NewInterpreter ();
1851                if (!wi->interpreter) {
1852                        fprintf (stderr, "unable to initialize the new interpreter\n");
1853                        exit (1);
1854                }
1855                PyThreadState_Swap (wi->interpreter);
1856#ifndef PYTHREE
1857                init_uwsgi_embedded_module ();
1858#endif
1859                init_uwsgi_vars ();
1860                fprintf (stderr, "interpreter for app %d initialized.\n", id);
1861        }
1862
1863        if (uwsgi.paste) {
1864                wi->wsgi_callable = my_callable;
1865                Py_INCREF (my_callable);
1866        }
1867        else if (uwsgi.wsgi_file) {
1868                wi->wsgi_callable = my_callable;
1869                Py_INCREF (my_callable);
1870        }
1871        else {
1872
1873                if (uwsgi.wsgi_config == NULL) {
1874                        if (wsgi_req.wsgi_script_len > 0) {
1875                                memcpy (tmpstring, wsgi_req.wsgi_script, wsgi_req.wsgi_script_len);
1876                                wsgi_module = PyImport_ImportModule (tmpstring);
1877                                if (!wsgi_module) {
1878                                        PyErr_Print ();
1879                                        if (uwsgi.single_interpreter == 0) {
1880                                                Py_EndInterpreter (wi->interpreter);
1881                                                PyThreadState_Swap (uwsgi.main_thread);
1882                                        }
1883                                        return -1;
1884                                }
1885                                wsgi_req.wsgi_callable = "application";
1886                                wsgi_req.wsgi_callable_len = 11;
1887                        }
1888                        else {
1889                                memcpy (tmpstring, wsgi_req.wsgi_module, wsgi_req.wsgi_module_len);
1890                                wsgi_module = PyImport_ImportModule (tmpstring);
1891                                if (!wsgi_module) {
1892                                        PyErr_Print ();
1893                                        if (uwsgi.single_interpreter == 0) {
1894                                                Py_EndInterpreter (wi->interpreter);
1895                                                PyThreadState_Swap (uwsgi.main_thread);
1896                                        }
1897                                        return -1;
1898                                }
1899                        }
1900
1901                        wsgi_dict = PyModule_GetDict (wsgi_module);
1902                        if (!wsgi_dict) {
1903                                PyErr_Print ();
1904                                if (uwsgi.single_interpreter == 0) {
1905                                        Py_EndInterpreter (wi->interpreter);
1906                                        PyThreadState_Swap (uwsgi.main_thread);
1907                                }
1908                                return -1;
1909                        }
1910
1911                }
1912                else {
1913                        wsgi_dict = force_wsgi_dict;
1914                }
1915
1916
1917                memset (tmpstring, 0, 256);
1918                memcpy (tmpstring, wsgi_req.wsgi_callable, wsgi_req.wsgi_callable_len);
1919                if (my_callable) {
1920                        wi->wsgi_callable = my_callable;
1921                        Py_INCREF (my_callable);
1922                }
1923                else if (wsgi_dict) {
1924                        wi->wsgi_callable = PyDict_GetItemString (wsgi_dict, tmpstring);
1925                }
1926                else {
1927                        return -1;
1928                }
1929
1930        }
1931
1932
1933        if (!wi->wsgi_callable) {
1934                PyErr_Print ();
1935                if (uwsgi.single_interpreter == 0) {
1936                        Py_EndInterpreter (wi->interpreter);
1937                        PyThreadState_Swap (uwsgi.main_thread);
1938                }
1939                return -1;
1940        }
1941
1942
1943        wi->wsgi_environ = PyDict_New ();
1944        if (!wi->wsgi_environ) {
1945                PyErr_Print ();
1946                if (uwsgi.single_interpreter == 0) {
1947                        Py_EndInterpreter (wi->interpreter);
1948                        PyThreadState_Swap (uwsgi.main_thread);
1949                }
1950                return -1;
1951        }
1952
1953        if (wsgi_dict) {
1954                wi->wsgi_harakiri = PyDict_GetItemString (wsgi_dict, "harakiri");
1955                if (wi->wsgi_harakiri) {
1956                        fprintf (stderr, "initialized Harakiri custom handler: %p.\n", wi->wsgi_harakiri);
1957                }
1958        }
1959
1960
1961
1962#ifdef UWSGI_PROFILER
1963        if (uwsgi.enable_profiler) {
1964                pymain = PyImport_AddModule ("__main__");
1965                if (!pymain) {
1966                        PyErr_Print ();
1967                        exit (1);
1968                }
1969                wi->pymain_dict = PyModule_GetDict (pymain);
1970                if (!wi->pymain_dict) {
1971                        PyErr_Print ();
1972                        exit (1);
1973                }
1974                if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_application__%d", id), wi->wsgi_callable)) {
1975                        PyErr_Print ();
1976                        exit (1);
1977                }
1978                if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_environ__%d", id), wi->wsgi_environ)) {
1979                        PyErr_Print ();
1980                        exit (1);
1981                }
1982                if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_spit__%d", id), wsgi_spitout)) {
1983                        PyErr_Print ();
1984                        exit (1);
1985                }
1986
1987                pycprof = PyImport_ImportModule ("cProfile");
1988                if (!pycprof) {
1989                        PyErr_Print ();
1990                        fprintf (stderr, "trying old profile module... ");
1991                        pycprof = PyImport_ImportModule ("profile");
1992                        if (!pycprof) {
1993                                fprintf (stderr, "doh!!!\n");
1994                                PyErr_Print ();
1995                                exit (1);
1996                        }
1997                        else {
1998                                fprintf (stderr, "ok and set stdout to linebuf mode.\n");
1999                        }
2000                }
2001                pycprof_dict = PyModule_GetDict (pycprof);
2002                if (!pycprof_dict) {
2003                        PyErr_Print ();
2004                        exit (1);
2005                }
2006                wi->wsgi_cprofile_run = PyDict_GetItemString (pycprof_dict, "run");
2007                if (!wi->wsgi_cprofile_run) {
2008                        PyErr_Print ();
2009                        exit (1);
2010                }
2011
2012                wi->wsgi_args = PyTuple_New (1);
2013                if (PyTuple_SetItem (wi->wsgi_args, 0, PyString_FromFormat ("uwsgi_out = uwsgi_application__%d(uwsgi_environ__%d,uwsgi_spit__%d)", id, id, id))) {
2014                        PyErr_Print ();
2015                        if (uwsgi.single_interpreter == 0) {
2016                                Py_EndInterpreter (wi->interpreter);
2017                                PyThreadState_Swap (uwsgi.main_thread);
2018                        }
2019                        return -1;
2020                }
2021        }
2022        else {
2023#endif
2024                wi->wsgi_args = PyTuple_New (2);
2025                if (PyTuple_SetItem (wi->wsgi_args, 0, wi->wsgi_environ)) {
2026                        PyErr_Print ();
2027                        if (uwsgi.single_interpreter == 0) {
2028                                Py_EndInterpreter (wi->interpreter);
2029                                PyThreadState_Swap (uwsgi.main_thread);
2030                        }
2031                        return -1;
2032                }
2033                if (PyTuple_SetItem (wi->wsgi_args, 1, wsgi_spitout)) {
2034                        PyErr_Print ();
2035                        if (uwsgi.single_interpreter == 0) {
2036                                Py_EndInterpreter (wi->interpreter);
2037                                PyThreadState_Swap (uwsgi.main_thread);
2038                        }
2039                        return -1;
2040                }
2041#ifdef UWSGI_PROFILER
2042        }
2043#endif
2044
2045#ifdef UWSGI_SENDFILE
2046        // prepare sendfile()
2047        wi->wsgi_sendfile = PyCFunction_New (uwsgi_sendfile_method, NULL);
2048#endif
2049
2050        if (uwsgi.single_interpreter == 0) {
2051                PyThreadState_Swap (uwsgi.main_thread);
2052        }
2053
2054        memset (tmpstring, 0, 256);
2055        memcpy (tmpstring, wsgi_req.script_name, wsgi_req.script_name_len);
2056        PyDict_SetItemString (uwsgi.py_apps, tmpstring, PyInt_FromLong (id));
2057        PyErr_Print ();
2058
2059        fprintf (stderr, "application %d (%s) ready\n", id, tmpstring);
2060
2061        if (id == 0) {
2062                fprintf (stderr, "setting default application to 0\n");
2063                uwsgi.default_app = 0;
2064        }
2065        else {
2066                uwsgi.wsgi_cnt++;
2067        }
2068
2069        return id;
2070}
2071
2072#ifdef UWSGI_PASTE
2073void uwsgi_paste_config () {
2074        PyObject *paste_module, *paste_dict, *paste_loadapp;
2075        PyObject *paste_arg, *paste_app;
2076
2077        fprintf (stderr, "Loading paste environment: %s\n", uwsgi.paste);
2078        paste_module = PyImport_ImportModule ("paste.deploy");
2079        if (!paste_module) {
2080                PyErr_Print ();
2081                exit (1);
2082        }
2083
2084        paste_dict = PyModule_GetDict (paste_module);
2085        if (!paste_dict) {
2086                PyErr_Print ();
2087                exit (1);
2088        }
2089
2090        paste_loadapp = PyDict_GetItemString (paste_dict, "loadapp");
2091        if (!paste_loadapp) {
2092                PyErr_Print ();
2093                exit (1);
2094        }
2095
2096        paste_arg = PyTuple_New (1);
2097        if (!paste_arg) {
2098                PyErr_Print ();
2099                exit (1);
2100        }
2101
2102        if (PyTuple_SetItem (paste_arg, 0, PyString_FromString (uwsgi.paste))) {
2103                PyErr_Print ();
2104                exit (1);
2105        }
2106
2107        paste_app = PyEval_CallObject (paste_loadapp, paste_arg);
2108        if (!paste_app) {
2109                PyErr_Print ();
2110                exit (1);
2111        }
2112
2113        init_uwsgi_app (NULL, paste_app);
2114}
2115
2116#endif
2117
2118/* trying to emulate Graham's mod_wsgi, this will allows easy and fast migrations */
2119void uwsgi_wsgi_file_config() {
2120
2121        FILE *wsgifile ;
2122        struct _node *wsgi_file_node = NULL;
2123        PyObject *wsgi_compiled_node, *wsgi_file_module, *wsgi_file_dict;
2124        PyObject *wsgi_file_callable ;
2125        int ret;
2126
2127
2128        wsgifile = fopen(uwsgi.wsgi_file, "r");
2129        if (!wsgifile) {
2130                perror("fopen()");
2131                exit(1);
2132        }
2133
2134        wsgi_file_node = PyParser_SimpleParseFile(wsgifile, uwsgi.wsgi_file, Py_file_input);
2135        if (!wsgi_file_node) {
2136                PyErr_Print();
2137                fprintf(stderr,"failed to parse wsgi file %s\n", uwsgi.wsgi_file);
2138                exit(1);
2139        }
2140
2141        fclose(wsgifile);
2142
2143        wsgi_compiled_node = (PyObject *)PyNode_Compile(wsgi_file_node, uwsgi.wsgi_file);
2144
2145        if (!wsgi_compiled_node) {
2146                PyErr_Print();
2147                fprintf(stderr,"failed to compile wsgi file %s\n", uwsgi.wsgi_file);
2148                exit(1);
2149        }
2150
2151        wsgi_file_module = PyImport_ExecCodeModule("uwsgi_wsgi_file", wsgi_compiled_node);
2152        if (!wsgi_file_module) {
2153                PyErr_Print();
2154                exit(1);
2155        }
2156
2157        Py_DECREF(wsgi_compiled_node);
2158
2159        wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
2160        if (!wsgi_file_dict) {
2161                PyErr_Print();
2162                exit(1);
2163        }
2164
2165
2166        wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, "application");
2167        if (!wsgi_file_callable) {
2168                PyErr_Print();
2169                fprintf(stderr,"unable to find \"application\" callable in wsgi file %s\n", uwsgi.wsgi_file);
2170                exit(1);
2171        }
2172
2173        if (!PyFunction_Check (wsgi_file_callable) && !PyCallable_Check (wsgi_file_callable)) {
2174                fprintf(stderr,"\"application\" must be a callable object in wsgi file %s\n", uwsgi.wsgi_file);
2175                exit(1);
2176        }
2177
2178
2179        ret = init_uwsgi_app (NULL, wsgi_file_callable);
2180
2181}
2182
2183
2184void uwsgi_wsgi_config () {
2185
2186        PyObject *wsgi_module, *wsgi_dict;
2187#ifndef PYTHREE
2188        PyObject *uwsgi_module, *uwsgi_dict;
2189#endif
2190        PyObject *applications;
2191        PyObject *app_list;
2192        int ret ;
2193        Py_ssize_t i;
2194        PyObject *app_mnt, *app_app;
2195
2196        wsgi_module = PyImport_ImportModule (uwsgi.wsgi_config);
2197        if (!wsgi_module) {
2198                PyErr_Print ();
2199                exit (1);
2200        }
2201
2202        wsgi_dict = PyModule_GetDict (wsgi_module);
2203        if (!wsgi_dict) {
2204                PyErr_Print ();
2205                exit (1);
2206        }
2207
2208        fprintf (stderr, "...getting the applications list from the '%s' module...\n", uwsgi.wsgi_config);
2209
2210#ifndef PYTHREE
2211        uwsgi_module = PyImport_ImportModule ("uwsgi");
2212        if (!uwsgi_module) {
2213                PyErr_Print ();
2214                exit (1);
2215        }
2216
2217        uwsgi_dict = PyModule_GetDict (uwsgi_module);
2218        if (!uwsgi_dict) {
2219                PyErr_Print ();
2220                exit (1);
2221        }
2222
2223
2224
2225        applications = PyDict_GetItemString (uwsgi_dict, "applications");
2226        if (!PyDict_Check (applications)) {
2227                fprintf (stderr, "uwsgi.applications dictionary is not defined, trying with the \"applications\" one...\n");
2228#endif
2229                applications = PyDict_GetItemString (wsgi_dict, "applications");
2230                if (!applications) {
2231                        fprintf (stderr, "applications dictionary is not defined, trying with the \"application\" callable.\n");
2232                        app_app = PyDict_GetItemString (wsgi_dict, "application");
2233                        if (app_app) {
2234                                applications = PyDict_New ();
2235                                if (!applications) {
2236                                        fprintf (stderr, "could not initialize applications dictionary\n");
2237                                        exit (1);
2238                                }
2239                                if (PyDict_SetItemString (applications, "/", app_app)) {
2240                                        PyErr_Print ();
2241                                        fprintf (stderr, "unable to set default application\n");
2242                                        exit (1);
2243                                }
2244                        }
2245                        else {
2246                                fprintf (stderr, "static applications not defined, you have to used the dynamic one...\n");
2247                                return;
2248                        }
2249                }
2250#ifndef PYTHREE
2251        }
2252#endif
2253
2254        if (!PyDict_Check (applications)) {
2255                fprintf (stderr, "The 'applications' object must be a dictionary.\n");
2256                exit (1);
2257        }
2258
2259        app_list = PyDict_Keys (applications);
2260        if (!app_list) {
2261                PyErr_Print ();
2262                exit (1);
2263        }
2264        if (PyList_Size (app_list) < 1) {
2265                fprintf (stderr, "You must define an app.\n");
2266                exit (1);
2267        }
2268
2269        for (i = 0; i < PyList_Size (app_list); i++) {
2270                app_mnt = PyList_GetItem (app_list, i);
2271
2272                if (!PyString_Check (app_mnt)) {
2273                        fprintf (stderr, "the app mountpoint must be a string.\n");
2274                        exit (1);
2275                }
2276
2277                wsgi_req.script_name = PyString_AsString (app_mnt);
2278                wsgi_req.script_name_len = strlen (wsgi_req.script_name);
2279
2280                app_app = PyDict_GetItem (applications, app_mnt);
2281
2282                if (!PyString_Check (app_app) && !PyFunction_Check (app_app) && !PyCallable_Check (app_app)) {
2283                        fprintf (stderr, "the app callable must be a string, a function or a callable. (found %s)\n", app_app->ob_type->tp_name);
2284                        exit (1);
2285                }
2286
2287                if (PyString_Check (app_app)) {
2288                        wsgi_req.wsgi_callable = PyString_AsString (app_app);
2289                        wsgi_req.wsgi_callable_len = strlen (wsgi_req.wsgi_callable);
2290                        fprintf (stderr, "initializing [%s => %s] app...\n", wsgi_req.script_name, wsgi_req.wsgi_callable);
2291                        ret = init_uwsgi_app (wsgi_dict, NULL);
2292                }
2293                else {
2294                        fprintf (stderr, "initializing [%s] app...\n", wsgi_req.script_name);
2295                        ret = init_uwsgi_app (wsgi_dict, app_app);
2296                }
2297
2298                if (ret < 0) {
2299                        fprintf (stderr, "...goodbye cruel world...\n");
2300                        exit (1);
2301                }
2302                Py_DECREF (app_mnt);
2303                Py_DECREF (app_app);
2304        }
2305
2306}
2307
2308
2309#ifdef UNBIT
2310int uri_to_hex () {
2311        int i = 0, j = 0;
2312
2313        if (wsgi_req.uri_len < 1) {
2314                return 0;
2315        }
2316
2317        if (wsgi_req.uri_len * 2 > 8192) {
2318                return 0;
2319        }
2320
2321        for (i = 0; i < wsgi_req.uri_len; i++) {
2322                sprintf (tmp_filename + j, "%02X", wsgi_req.uri[i]);
2323                j += 2;
2324        }
2325
2326        return j;
2327}
2328#endif
2329
2330#ifdef UWSGI_EMBEDDED
2331void init_uwsgi_embedded_module () {
2332        PyObject *new_uwsgi_module, *zero;
2333        int i;
2334
2335        /* initialize for stats */
2336        uwsgi.workers_tuple = PyTuple_New (uwsgi.numproc);
2337        for (i = 0; i < uwsgi.numproc; i++) {
2338                zero = PyDict_New ();
2339                Py_INCREF (zero);
2340                PyTuple_SetItem (uwsgi.workers_tuple, i, zero);
2341        }
2342
2343
2344
2345        new_uwsgi_module = Py_InitModule ("uwsgi", null_methods);
2346        if (new_uwsgi_module == NULL) {
2347                fprintf (stderr, "could not initialize the uwsgi python module\n");
2348                exit (1);
2349        }
2350
2351        uwsgi.embedded_dict = PyModule_GetDict (new_uwsgi_module);
2352        if (!uwsgi.embedded_dict) {
2353                fprintf (stderr, "could not get uwsgi module __dict__\n");
2354                exit (1);
2355        }
2356
2357        if (PyDict_SetItemString (uwsgi.embedded_dict, "SPOOL_RETRY", PyInt_FromLong (17))) {
2358                PyErr_Print ();
2359                exit (1);
2360        }
2361
2362        if (PyDict_SetItemString (uwsgi.embedded_dict, "numproc", PyInt_FromLong (uwsgi.numproc))) {
2363                PyErr_Print ();
2364                exit (1);
2365        }
2366
2367#ifdef UNBIT
2368        if (PyDict_SetItemString (uwsgi.embedded_dict, "unbit", Py_True)) {
2369#else
2370        if (PyDict_SetItemString (uwsgi.embedded_dict, "unbit", Py_None)) {
2371#endif
2372                PyErr_Print ();
2373                exit (1);
2374        }
2375
2376        if (PyDict_SetItemString (uwsgi.embedded_dict, "buffer_size", PyInt_FromLong (uwsgi.buffer_size))) {
2377                PyErr_Print ();
2378                exit (1);
2379        }
2380
2381        if (PyDict_SetItemString (uwsgi.embedded_dict, "started_on", PyInt_FromLong (uwsgi.start_tv.tv_sec))) {
2382                PyErr_Print ();
2383                exit (1);
2384        }
2385
2386        if (PyDict_SetItemString (uwsgi.embedded_dict, "start_response", wsgi_spitout)) {
2387                PyErr_Print ();
2388                exit (1);
2389        }
2390
2391        if (PyDict_SetItemString (uwsgi.embedded_dict, "fastfuncs", PyList_New (256))) {
2392                PyErr_Print ();
2393                exit (1);
2394        }
2395
2396
2397        if (PyDict_SetItemString (uwsgi.embedded_dict, "applist", uwsgi.py_apps)) {
2398                PyErr_Print ();
2399                exit (1);
2400        }
2401
2402        if (PyDict_SetItemString (uwsgi.embedded_dict, "applications", Py_None)) {
2403                PyErr_Print ();
2404                exit (1);
2405        }
2406
2407        uwsgi.embedded_args = PyTuple_New (2);
2408        if (!uwsgi.embedded_args) {
2409                PyErr_Print ();
2410                exit (1);
2411        }
2412
2413        if (PyDict_SetItemString (uwsgi.embedded_dict, "message_manager_marshal", Py_None)) {
2414                PyErr_Print ();
2415                exit (1);
2416        }
2417
2418        uwsgi.fastfuncslist = PyDict_GetItemString (uwsgi.embedded_dict, "fastfuncs");
2419        if (!uwsgi.fastfuncslist) {
2420                PyErr_Print ();
2421                exit (1);
2422        }
2423
2424        init_uwsgi_module_advanced (new_uwsgi_module);
2425
2426#ifdef UWSGI_SPOOLER
2427        if (spool_dir != NULL) {
2428                init_uwsgi_module_spooler (new_uwsgi_module);
2429        }
2430#endif
2431
2432
2433        if (uwsgi.sharedareasize > 0 && uwsgi.sharedarea) {
2434                init_uwsgi_module_sharedarea (new_uwsgi_module);
2435        }
2436}
2437#endif
2438
2439#ifdef UWSGI_PROXY
2440pid_t proxy_start (has_master) {
2441       
2442        pid_t pid ;
2443
2444        char *tcp_port = strchr (uwsgi.proxy_socket_name, ':');
2445
2446        if (tcp_port == NULL) {
2447                uwsgi.proxyfd = bind_to_unix (uwsgi.proxy_socket_name, UWSGI_LISTEN_QUEUE, uwsgi.chmod_socket, uwsgi.abstract_socket);
2448        }
2449        else {
2450                uwsgi.proxyfd = bind_to_tcp (uwsgi.proxy_socket_name, UWSGI_LISTEN_QUEUE, tcp_port);
2451                tcp_port[0] = ':';
2452        }
2453
2454        if (uwsgi.proxyfd < 0) {
2455                fprintf (stderr, "unable to create the server socket.\n");
2456                exit (1);
2457        }
2458
2459        if (!has_master && uwsgi.numproc == 0) {
2460                uwsgi_proxy(uwsgi.proxyfd);
2461                // never here
2462                exit(1);
2463        }
2464        else {
2465                pid = fork() ;
2466                if (pid < 0) {
2467                        perror("fork()");
2468                        exit(1);
2469                }
2470                else if (pid > 0) {
2471                        close(uwsgi.proxyfd);
2472                        return pid ;
2473                        // continue with uWSGI spawn...
2474                }
2475                else {
2476                        uwsgi_proxy(uwsgi.proxyfd);
2477                        // never here
2478                        exit(1);
2479                }
2480        }
2481}
2482#endif
2483
2484#ifdef UWSGI_SPOOLER
2485pid_t spooler_start (int serverfd, PyObject * uwsgi_module) {
2486        pid_t pid;
2487
2488        pid = fork ();
2489        if (pid < 0) {
2490                perror ("fork()");
2491                exit (1);
2492        }
2493        else if (pid == 0) {
2494                close (serverfd);
2495                spooler (uwsgi_module);
2496        }
2497        else if (pid > 0) {
2498                fprintf (stderr, "spawned the uWSGI spooler on dir %s with pid %d\n", spool_dir, pid);
2499        }
2500
2501        return pid;
2502}
2503#endif
2504
2505void manage_opt(int i, char *optarg) {
2506
2507                switch (i) {
2508#ifndef UNBIT
2509                case LONG_ARGS_VERSION:
2510                        fprintf(stdout,"uWSGI %s\n", UWSGI_VERSION);
2511                        exit(0);
2512                case LONG_ARGS_PIDFILE:
2513                        uwsgi.pidfile = optarg;
2514                        break;
2515                case LONG_ARGS_UDP:
2516                        uwsgi.udp_socket = optarg;
2517                        uwsgi.master_process = 1;
2518                        break;
2519                case LONG_ARGS_CHROOT:
2520                        uwsgi.chroot = optarg;
2521                        break;
2522                case LONG_ARGS_GID:
2523                        uwsgi.gid = atoi (optarg);
2524                        break;
2525                case LONG_ARGS_UID:
2526                        uwsgi.uid = atoi (optarg);
2527                        break;
2528                case LONG_ARGS_BINARY_PATH:
2529                        uwsgi.binary_path = optarg;
2530                        break;
2531                case LONG_ARGS_WSGI_FILE:
2532                        uwsgi.single_interpreter = 1;
2533                        uwsgi.wsgi_file = optarg;
2534                        break;
2535#ifdef UWSGI_PROXY
2536                case LONG_ARGS_PROXY_NODE:
2537                        uwsgi_cluster_add_node(optarg, 1);
2538                        break;
2539                case LONG_ARGS_PROXY:
2540                        uwsgi.proxy_socket_name = optarg;
2541                        break;
2542#endif
2543#ifdef UWSGI_ERLANG
2544                case LONG_ARGS_ERLANG:
2545                        uwsgi.erlang_node = optarg;
2546                        break;
2547                case LONG_ARGS_ERLANG_COOKIE:
2548                        uwsgi.erlang_cookie = optarg;
2549                        break;
2550#endif
2551                case LONG_ARGS_PYTHONPATH:
2552                        if (uwsgi.python_path_cnt < 63) {
2553                                uwsgi.python_path[uwsgi.python_path_cnt] = optarg;
2554                                uwsgi.python_path_cnt++;
2555                        }
2556                        else {
2557                                fprintf(stderr,"you can specify at most 64 --pythonpath options\n");
2558                        }
2559                        break;
2560                case LONG_ARGS_LIMIT_AS:
2561                        uwsgi.rl.rlim_cur = (atoi (optarg)) * 1024 * 1024;
2562                        uwsgi.rl.rlim_max = uwsgi.rl.rlim_cur;
2563                        break;
2564                case LONG_ARGS_PASTE:
2565                        uwsgi.single_interpreter = 1;
2566                        uwsgi.paste = optarg;
2567                        break;
2568                case LONG_ARGS_CHECK_INTERVAL:
2569                        uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = atoi (optarg);
2570                        break;
2571                case LONG_ARGS_PYARGV:
2572                        uwsgi.pyargv = optarg;
2573                        break;
2574#endif
2575                case 'j':
2576                        uwsgi.test_module = optarg;
2577                        break;
2578                case 'H':
2579                        uwsgi.pyhome = optarg;
2580                        break;
2581                case 'A':
2582                        uwsgi.sharedareasize = atoi (optarg);
2583                        break;
2584                case 'L':
2585                        uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 0;
2586                        break;
2587#ifdef UWSGI_SPOOLER
2588                case 'Q':
2589                        spool_dir = optarg;
2590                        if (access (spool_dir, R_OK | W_OK | X_OK)) {
2591                                perror ("[spooler directory] access()");
2592                                exit (1);
2593                        }
2594                        uwsgi.master_process = 1;
2595                        break;
2596#endif
2597#ifdef UNBIT
2598                case 'E':
2599                        check_for_memory_errors = 1;
2600                        break;
2601                case 'S':
2602                        uwsgi.single_interpreter = 1;
2603                        single_app_mode = 1;
2604                        uwsgi.default_app = 0;
2605                        break;
2606                case 'C':
2607                        tmp_dir_fd = open (optarg, O_DIRECTORY);
2608                        if (tmp_dir_fd < 0) {
2609                                perror ("open()");
2610                                exit (1);
2611                        }
2612                        tmp_filename = malloc (8192);
2613                        if (!tmp_filename) {
2614                                fprintf (stderr, "unable to allocate space (8k) for tmp_filename\n");
2615                                exit (1);
2616                        }
2617                        memset (tmp_filename, 0, 8192);
2618                        break;
2619#endif
2620#ifndef UNBIT
2621                case 'd':
2622                        if (!uwsgi.is_a_reload) {
2623                                daemonize (optarg);
2624                        }
2625                        break;
2626                case 's':
2627                        uwsgi.socket_name = optarg;
2628                        break;
2629#ifdef UWSGI_XML
2630                case 'x':
2631                        uwsgi.xml_config = optarg;
2632                        break;
2633#endif
2634                case 'l':
2635                        uwsgi.listen_queue = atoi (optarg);
2636                        break;
2637#endif
2638                case 'v':
2639                        uwsgi.max_vars = atoi (optarg);
2640                        uwsgi.vec_size = 4 + 1 + (4 * uwsgi.max_vars);
2641                        break;
2642                case 'p':
2643                        uwsgi.numproc = atoi (optarg);
2644                        break;
2645                case 'r':
2646                        uwsgi.shared->options[UWSGI_OPTION_REAPER] = 1;
2647                        break;
2648                case 'w':
2649                        uwsgi.single_interpreter = 1;
2650                        uwsgi.wsgi_config = optarg;
2651                        break;
2652                case 'm':
2653                        uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] = 1;
2654                        break;
2655                case 'O':
2656                        uwsgi.py_optimize = atoi (optarg);
2657                        break;
2658                case 't':
2659                        uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] = atoi (optarg);
2660                        break;
2661                case 'b':
2662                        uwsgi.buffer_size = atoi (optarg);
2663                        break;
2664#ifndef UNBIT
2665                case 'c':
2666                        uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
2667                        break;
2668                case 'a':
2669                        uwsgi.abstract_socket = 1;
2670                        break;
2671                case 'C':
2672                        uwsgi.chmod_socket = 1;
2673                        break;
2674#endif
2675                case 'M':
2676                        uwsgi.master_process = 1;
2677                        break;
2678                case 'R':
2679                        uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] = atoi (optarg);
2680                        break;
2681                case 'z':
2682                        if (atoi (optarg) > 0) {
2683                                uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = atoi (optarg);
2684                        }
2685                        break;
2686                case 'T':
2687                        uwsgi.has_threads = 1;
2688                        uwsgi.shared->options[UWSGI_OPTION_THREADS] = 1;
2689                        break;
2690                case 'P':
2691                        uwsgi.enable_profiler = 1;
2692                        break;
2693                case 'i':
2694                        uwsgi.single_interpreter = 1;
2695                        break;
2696#ifndef UNBIT
2697                case 'h':
2698                        fprintf (stdout, "Usage: %s [options...]\n\
2699\t-s|--socket <name>\t\tpath (or name) of UNIX/TCP socket to bind to\n\
2700\t-l|--listen <num>\t\tset socket listen queue to <n> (default 64, maximum is system dependent)\n\
2701\t-z|--socket-timeout <sec>\tset socket timeout to <sec> seconds (default 4 seconds)\n\
2702\t-b|--buffer-size <n>\t\tset buffer size to <n> bytes\n\
2703\t-L|--disable-logging\t\tdisable request logging (only errors or server messages will be logged)\n\
2704\t-x|--xmlconfig <path>\t\tpath of xml config file\n\
2705\t-w|--module <module>\t\tname of python config module\n\
2706\t-t|--harakiri <sec>\t\tset harakiri timeout to <sec> seconds\n\
2707\t-p|--processes <n>\t\tspawn <n> uwsgi worker processes\n\
2708\t-O|--optimize <n>\t\tset python optimization level to <n>\n\
2709\t-v|--max-vars <n>\t\tset maximum number of vars/headers to <n>\n\
2710\t-A|--sharedarea <n>\t\tcreate a shared memory area of <n> pages\n\
2711\t-c|--cgi-mode\t\t\tset cgi mode\n\
2712\t-C|--chmod-socket\t\tchmod socket to 666\n\
2713\t-P|--profiler\t\t\tenable profiler\n\
2714\t-m|--memory-report\t\tenable memory usage report\n\
2715\t-i|--single-interpreter\t\tsingle interpreter mode\n\
2716\t-a|--abstract-socket\t\tset socket in the abstract namespace (Linux only)\n\
2717\t-T|--enable-threads\t\tenable threads support\n\
2718\t-M|--master\t\t\tenable master process manager\n\
2719\t-H|--home <path>\t\tset python home/virtualenv\n\
2720\t-h|--help\t\t\tthis help\n\
2721\t-r|--reaper\t\t\tprocess reaper (call waitpid(-1,...) after each request)\n\
2722\t-R|--max-requests\t\tmaximum number of requests for each worker\n\
2723\t-j|--test\t\t\ttest if uWSGI can import a module\n\
2724\t-Q|--spooler <dir>\t\trun the spooler on directory <dir>\n\
2725\t--pidfile <file>\t\twrite the masterpid to <file>\n\
2726\t--chroot <dir>\t\t\tchroot to directory <dir> (only root)\n\
2727\t--gid <id>\t\t\tsetgid to <id> (only root)\n\
2728\t--uid <id>\t\t\tsetuid to <id> (only root)\n\
2729\t--sync-log\t\t\tlet uWSGI does its best to avoid logfile mess\n\
2730\t--no-server\t\t\tinitialize the uWSGI server then exit. Useful for testing and using uwsgi embedded module\n\
2731\t--no-defer-accept\t\tdisable the no-standard way to defer the accept() call (TCP_DEFER_ACCEPT, SO_ACCEPTFILTER...)\n\
2732\t--paste <config:/egg:>\t\tload applications using paste.deploy.loadapp()\n\
2733\t--check-interval <sec>\t\tset the check interval (in seconds) of the master process\n\
2734\t--pythonpath <dir>\t\tadd <dir> to PYTHONPATH\n\
2735\t--pyargv <args>\t\t\tassign args to python sys.argv\n\
2736\t--limit-as <MB>\t\t\tlimit the address space of processes to MB megabytes\n\
2737\t--udp <ip:port>\t\t\tbind master process to udp socket on ip:port\n\
2738\t--erlang <name@ip>\t\tenable the Erlang server with node name <node@ip>\n\
2739\t--erlang-cookie <cookie>\ttset the erlang cookie to <cookie>\n\
2740\t--nagios\t\t\tdo a nagios check\n\
2741\t--binary-path <bin-path>\ttset the path for the next reload of uWSGI (needed for chroot environments)\n\
2742\t--proxy <socket>\t\trun the uwsgi proxy on socket <socket>\n\
2743\t--proxy-node <socket>\t\tadd the node <socket> to the proxy\n\
2744\t--proxy-max-connections <n>\tset the max number of concurrent connections mnaged by the proxy\n\
2745\t--wsgi-file <file>\t\tload the <file> wsgi file\n\
2746\t--version\t\t\tprint server version\n\
2747\t-d|--daemonize <logfile>\tdaemonize and log into <logfile>\n", uwsgi.binary_path);
2748                        exit (1);
2749                case 0:
2750                        break;
2751                default:
2752                        exit (1);
2753#endif
2754                }
2755        }
2756
2757
2758void uwsgi_cluster_add_node(char *nodename, int workers) {
2759
2760        int i ;
2761        struct uwsgi_cluster_node *ucn ;
2762        char *tcp_port ;
2763
2764        if (strlen(nodename) > 100) {
2765                fprintf(stderr,"invalid cluster node name %s\n", nodename);
2766                return;
2767        }
2768
2769        tcp_port = strchr (nodename, ':');
2770        if (tcp_port == NULL) {
2771                fprintf(stdout,"invalid cluster node name %s\n", nodename);
2772                return ;
2773        }
2774
2775        for(i=0;i<MAX_CLUSTER_NODES; i++) {
2776                ucn = &uwsgi.shared->nodes[i] ;
2777
2778                if (ucn->name[0] == 0) {
2779                        strcpy(ucn->name, nodename);
2780                        ucn->workers = workers ;
2781                        ucn->ucn_addr.sin_family = AF_INET ;
2782                        ucn->ucn_addr.sin_port = htons(atoi(tcp_port+1));
2783                        tcp_port[0] = 0 ;
2784                        if (nodename[0] == 0) {
2785                                ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY ;
2786                        }
2787                        else {
2788                                fprintf(stderr,"%s\n", nodename);
2789                                ucn->ucn_addr.sin_addr.s_addr = inet_addr(nodename);
2790                        }
2791
2792                        ucn->last_seen = time(NULL);
2793
2794                        return ;
2795                }
2796        }
2797       
2798        fprintf(stderr,"unable to add node %s\n", nodename);
2799}
Note: See TracBrowser for help on using the browser.