root/uwsgi.c

Revision 217:c605344fd503, 90.0 KB (checked in by roberto@…, 5 days ago)

remove get_free_memory function. Is useless on modern systems

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