1 #include "uwsgi_python.h"
2
3 /* notes
4
5 exit(1) on every malloc error: apps can be dinamically loaded so on memory problem
6 it is better to let the master process manager respawn the worker.
7
8 TODO dynamic loading on prefork+thread looks flaky... NEED TO FIX IT
9 */
10
11 extern struct uwsgi_server uwsgi;
12 extern struct uwsgi_python up;
13 extern struct uwsgi_plugin python_plugin;
14
15 extern char **environ;
16
17 PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
18
19 PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
20 PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
21
set_dyn_pyhome(char * home,uint16_t pyhome_len)22 void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
23
24
25 char venv_version[30];
26 PyObject *site_module;
27
28 PyObject *pysys_dict = get_uwsgi_pydict("sys");
29
30 PyObject *pypath = PyDict_GetItemString(pysys_dict, "path");
31 if (!pypath) {
32 PyErr_Print();
33 exit(1);
34 }
35
36 // simulate a pythonhome directive
37 if (uwsgi.wsgi_req->home_len > 0) {
38
39 PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->home, uwsgi.wsgi_req->home_len);
40
41 #ifdef UWSGI_DEBUG
42 uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->home_len, uwsgi.wsgi_req->home);
43 #endif
44
45 PyDict_SetItemString(pysys_dict, "prefix", venv_path);
46 PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
47
48 bzero(venv_version, 30);
49 if (snprintf(venv_version, 30, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
50 return;
51 }
52
53 // check here
54 PyString_Concat(&venv_path, PyString_FromString(venv_version));
55
56 if (PyList_Insert(pypath, 0, venv_path)) {
57 PyErr_Print();
58 }
59
60 site_module = PyImport_ImportModule("site");
61 if (site_module) {
62 PyImport_ReloadModule(site_module);
63 }
64
65 }
66 }
67
68
init_uwsgi_app(int loader,void * arg1,struct wsgi_request * wsgi_req,PyThreadState * interpreter,int app_type)69 int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) {
70
71 PyObject *app_list = NULL, *applications = NULL;
72
73
74 if (uwsgi_apps_cnt >= uwsgi.max_apps) {
75 uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
76 return -1;
77 }
78
79
80 int id = uwsgi_apps_cnt;
81
82 int multiapp = 0;
83
84 int i;
85
86 struct uwsgi_app *wi;
87
88 time_t now = uwsgi_now();
89
90 if (uwsgi_get_app_id(NULL, wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
91 uwsgi_log( "mountpoint %.*s already configured. skip.\n", wsgi_req->appid_len, wsgi_req->appid);
92 return -1;
93 }
94
95 wi = &uwsgi_apps[id];
96
97 memset(wi, 0, sizeof(struct uwsgi_app));
98 wi->modifier1 = python_plugin.modifier1;
99 wi->mountpoint_len = wsgi_req->appid_len < 0xff ? wsgi_req->appid_len : (0xff-1);
100 strncpy(wi->mountpoint, wsgi_req->appid, wi->mountpoint_len);
101
102 // dynamic chdir ?
103 if (wsgi_req->chdir_len > 0) {
104 strncpy(wi->chdir, wsgi_req->chdir, wsgi_req->chdir_len < 0xff ? wsgi_req->chdir_len : (0xff-1));
105 #ifdef UWSGI_DEBUG
106 uwsgi_debug("chdir to %s\n", wi->chdir);
107 #endif
108 if (chdir(wi->chdir)) {
109 uwsgi_error("chdir()");
110 }
111 }
112
113 // Initialize a new environment for the new interpreter
114
115 // reload "os" environ to allow dynamic setenv()
116 if (up.reload_os_env) {
117
118 char **e, *p;
119 PyObject *k, *env_value;
120
121 PyObject *os_module = PyImport_ImportModule("os");
122 if (os_module) {
123 PyObject *os_module_dict = PyModule_GetDict(os_module);
124 PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
125 if (py_environ) {
126 for (e = environ; *e != NULL; e++) {
127 p = strchr(*e, '=');
128 if (p == NULL) continue;
129
130 k = PyString_FromStringAndSize(*e, (int)(p-*e));
131 if (k == NULL) {
132 PyErr_Print();
133 continue;
134 }
135
136 env_value = PyString_FromString(p+1);
137 if (env_value == NULL) {
138 PyErr_Print();
139 Py_DECREF(k);
140 continue;
141 }
142
143 #ifdef UWSGI_DEBUG
144 uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value));
145 #endif
146
147 if (PyObject_SetItem(py_environ, k, env_value)) {
148 PyErr_Print();
149 }
150
151 Py_DECREF(k);
152 Py_DECREF(env_value);
153
154 }
155
156 }
157 }
158 }
159
160 if (interpreter == NULL && id) {
161
162 wi->interpreter = Py_NewInterpreter();
163 if (!wi->interpreter) {
164 uwsgi_log( "unable to initialize the new python interpreter\n");
165 exit(1);
166 }
167 PyThreadState_Swap(wi->interpreter);
168 init_pyargv();
169
170 // we need to initialize an embedded module for every interpreter
171 init_uwsgi_embedded_module();
172 init_uwsgi_vars();
173
174 }
175 else if (interpreter) {
176 wi->interpreter = interpreter;
177 }
178 else {
179 wi->interpreter = up.main_thread;
180 }
181
182 if (wsgi_req->home_len) {
183 set_dyn_pyhome(wsgi_req->home, wsgi_req->home_len);
184 }
185
186 if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
187 struct stat trst;
188 strncpy(wi->touch_reload, wsgi_req->touch_reload, wsgi_req->touch_reload_len);
189 if (!stat(wi->touch_reload, &trst)) {
190 wi->touch_reload_mtime = trst.st_mtime;
191 }
192 }
193
194 wi->callable = up.loaders[loader](arg1);
195
196 if (!wi->callable) {
197 uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, wi->mountpoint);
198 goto doh;
199 }
200
201 // the module contains multiple apps
202 if (PyDict_Check((PyObject *)wi->callable)) {
203 applications = wi->callable;
204 uwsgi_log("found a multiapp module...\n");
205 app_list = PyDict_Keys(applications);
206 multiapp = PyList_Size(app_list);
207 if (multiapp < 1) {
208 uwsgi_log("you have to define at least one app in the applications dictionary\n");
209 goto doh;
210 }
211
212 PyObject *app_mnt = PyList_GetItem(app_list, 0);
213 if (!PyString_Check(app_mnt)) {
214 uwsgi_log("the app mountpoint must be a string\n");
215 goto doh;
216 }
217 char *tmp_mountpoint = PyString_AsString(app_mnt);
218 wi->mountpoint_len = strlen(wi->mountpoint) < 0xff ? strlen(wi->mountpoint) : (0xff-1);
219 strncpy(wi->mountpoint, tmp_mountpoint, wi->mountpoint_len);
220 wsgi_req->appid = wi->mountpoint;
221 wsgi_req->appid_len = wi->mountpoint_len;
222 #ifdef UWSGI_DEBUG
223 uwsgi_log("main mountpoint = %s\n", wi->mountpoint);
224 #endif
225 wi->callable = PyDict_GetItem(applications, app_mnt);
226 if (PyString_Check((PyObject *) wi->callable)) {
227 PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
228 if (callables_dict) {
229 wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable);
230 if (!wi->callable) {
231 uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
232 goto multiapp;
233 }
234 }
235 }
236 }
237
238 Py_INCREF((PyObject *)wi->callable);
239
240 wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
241 if (!wi->environ) {
242 uwsgi_error("malloc()");
243 exit(1);
244 }
245
246 for(i=0;i<uwsgi.cores;i++) {
247 wi->environ[i] = PyDict_New();
248 if (!wi->environ[i]) {
249 uwsgi_log("unable to allocate new env dictionary for app\n");
250 exit(1);
251 }
252 }
253
254 wi->argc = 1;
255
256 if (app_type == PYTHON_APP_TYPE_WSGI) {
257 #ifdef UWSGI_DEBUG
258 uwsgi_log("-- WSGI callable selected --\n");
259 #endif
260 wi->request_subhandler = uwsgi_request_subhandler_wsgi;
261 wi->response_subhandler = uwsgi_response_subhandler_wsgi;
262 wi->argc = 2;
263 }
264 else if (app_type == PYTHON_APP_TYPE_WEB3) {
265 #ifdef UWSGI_DEBUG
266 uwsgi_log("-- Web3 callable selected --\n");
267 #endif
268 wi->request_subhandler = uwsgi_request_subhandler_web3;
269 wi->response_subhandler = uwsgi_response_subhandler_web3;
270 }
271 else if (app_type == PYTHON_APP_TYPE_PUMP) {
272 #ifdef UWSGI_DEBUG
273 uwsgi_log("-- Pump callable selected --\n");
274 #endif
275 wi->request_subhandler = uwsgi_request_subhandler_pump;
276 wi->response_subhandler = uwsgi_response_subhandler_pump;
277 }
278
279 wi->args = malloc(sizeof(PyObject*)*uwsgi.cores);
280 if (!wi->args) {
281 uwsgi_error("malloc()");
282 exit(1);
283 }
284
285 for(i=0;i<uwsgi.cores;i++) {
286 wi->args[i] = PyTuple_New(wi->argc);
287 if (!wi->args[i]) {
288 uwsgi_log("unable to allocate new tuple for app args\n");
289 exit(1);
290 }
291 Py_INCREF(Py_None);
292 PyTuple_SetItem(wi->args[i], 0, Py_None);
293
294 // add start_response on WSGI app
295 if (app_type == PYTHON_APP_TYPE_WSGI) {
296 Py_INCREF((PyObject *)up.wsgi_spitout);
297 if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
298 uwsgi_log("unable to set start_response in args tuple\n");
299 exit(1);
300 }
301 }
302 }
303
304 if (app_type == PYTHON_APP_TYPE_WSGI) {
305 // prepare sendfile() for WSGI app
306 wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
307
308 wi->eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL);
309 wi->eventfd_write = PyCFunction_New(uwsgi_eventfd_write_method, NULL);
310 }
311
312 // cache most used values
313 wi->error = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
314 Py_INCREF((PyObject *)wi->error);
315
316 wi->gateway_version = PyTuple_New(2);
317 PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
318 PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0));
319 Py_INCREF((PyObject *)wi->gateway_version);
320
321 wi->uwsgi_version = PyString_FromString(UWSGI_VERSION);
322 Py_INCREF((PyObject *)wi->uwsgi_version);
323
324 wi->uwsgi_node = PyString_FromString(uwsgi.hostname);
325 Py_INCREF((PyObject *)wi->uwsgi_node);
326
327 if (uwsgi.threads > 1 && id) {
328 // if we have multiple threads we need to initialize a PyThreadState for each one
329 for(i=0;i<uwsgi.threads;i++) {
330 uwsgi.workers[uwsgi.mywid].cores[i].ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
331 //uwsgi_log("%p\n", uwsgi.workers[uwsgi.mywid].cores[i].ts[id]);
332 if (!uwsgi.workers[uwsgi.mywid].cores[i].ts[id]) {
333 uwsgi_log("unable to allocate new PyThreadState structure for app %s", wi->mountpoint);
334 goto doh;
335 }
336 // cow ?
337 if (uwsgi.mywid == 0) {
338 int j;
339 for(j=1;j<=uwsgi.numproc;j++) {
340 uwsgi.workers[j].cores[i].ts[id] = uwsgi.workers[0].cores[i].ts[id];
341 }
342 }
343 }
344 PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) );
345 }
346 else if (interpreter == NULL && id) {
347 PyThreadState_Swap(up.main_thread);
348 }
349
350 const char *default_app = "";
351
352 if (!uwsgi.no_default_app) {
353 if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
354 default_app = " (default app)" ;
355 uwsgi.default_app = id;
356 }
357 }
358
359 wi->started_at = now;
360 wi->startup_time = uwsgi_now() - now;
361
362 if (app_type == PYTHON_APP_TYPE_WSGI) {
363 uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
364 }
365 else if (app_type == PYTHON_APP_TYPE_WEB3) {
366 uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
367 }
368 else if (app_type == PYTHON_APP_TYPE_PUMP) {
369 uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
370 }
371
372
373 uwsgi_apps_cnt++;
374
375 multiapp:
376 if (multiapp > 1) {
377 for(i=1;i<multiapp;i++) {
378 PyObject *app_mnt = PyList_GetItem(app_list, i);
379 if (!PyString_Check(app_mnt)) {
380 uwsgi_log("applications dictionary key must be a string, skipping.\n");
381 continue;
382 }
383
384 wsgi_req->appid = PyString_AsString(app_mnt);
385 wsgi_req->appid_len = strlen(wsgi_req->appid);
386 PyObject *a_callable = PyDict_GetItem(applications, app_mnt);
387 if (PyString_Check(a_callable)) {
388
389 PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
390 if (callables_dict) {
391 a_callable = PyDict_GetItem(callables_dict, a_callable);
392 }
393 }
394 if (!a_callable) {
395 uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
396 continue;
397 }
398 init_uwsgi_app(LOADER_CALLABLE, a_callable, wsgi_req, wi->interpreter, app_type);
399 }
400 }
401
402 // emulate COW
403 uwsgi_emulate_cow_for_apps(id);
404
405 return id;
406
407 doh:
408 if (PyErr_Occurred())
409 PyErr_Print();
410 if (interpreter == NULL && id) {
411 Py_EndInterpreter(wi->interpreter);
412 if (uwsgi.threads > 1) {
413 PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
414 }
415 else {
416 PyThreadState_Swap(up.main_thread);
417 }
418 }
419 return -1;
420 }
421
get_uwsgi_pymodule(char * module)422 char *get_uwsgi_pymodule(char *module) {
423
424 char *quick_callable;
425
426 if ( (quick_callable = strchr(module, ':')) ) {
427 quick_callable[0] = 0;
428 quick_callable++;
429 return quick_callable;
430 }
431
432 return NULL;
433 }
434
get_uwsgi_pydict(char * module)435 PyObject *get_uwsgi_pydict(char *module) {
436
437 PyObject *wsgi_module, *wsgi_dict;
438
439 wsgi_module = PyImport_ImportModule(module);
440 if (!wsgi_module) {
441 PyErr_Print();
442 return NULL;
443 }
444
445 wsgi_dict = PyModule_GetDict(wsgi_module);
446 if (!wsgi_dict) {
447 PyErr_Print();
448 return NULL;
449 }
450
451 return wsgi_dict;
452
453 }
454
uwsgi_uwsgi_loader(void * arg1)455 PyObject *uwsgi_uwsgi_loader(void *arg1) {
456
457 PyObject *wsgi_dict;
458
459 char *quick_callable;
460
461 PyObject *tmp_callable;
462 PyObject *applications;
463 PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
464
465 char *module = (char *) arg1;
466
467 quick_callable = get_uwsgi_pymodule(module);
468 if (quick_callable == NULL) {
469 if (up.callable) {
470 quick_callable = up.callable;
471 }
472 else {
473 quick_callable = "application";
474 }
475 wsgi_dict = get_uwsgi_pydict(module);
476 }
477 else {
478 wsgi_dict = get_uwsgi_pydict(module);
479 module[strlen(module)] = ':';
480 }
481
482 if (!wsgi_dict) {
483 return NULL;
484 }
485
486 applications = PyDict_GetItemString(uwsgi_dict, "applications");
487 if (applications && PyDict_Check(applications)) return applications;
488
489 applications = PyDict_GetItemString(wsgi_dict, "applications");
490 if (applications && PyDict_Check(applications)) return applications;
491
492 // quick callable -> thanks gunicorn for the idea
493 // we have extended the concept a bit...
494 if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
495 quick_callable[strlen(quick_callable) -2 ] = 0;
496 tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
497 quick_callable[strlen(quick_callable)] = '(';
498 if (tmp_callable) {
499 return python_call(tmp_callable, PyTuple_New(0), 0, NULL);
500 }
501 }
502
503 return PyDict_GetItemString(wsgi_dict, quick_callable);
504
505 }
506
507 /* this is the mount loader, it loads app on mountpoint automagically */
uwsgi_mount_loader(void * arg1)508 PyObject *uwsgi_mount_loader(void *arg1) {
509
510 PyObject *callable = NULL;
511 char *what = (char *) arg1;
512
513 if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
514 callable = uwsgi_file_loader((void *)what);
515 if (!callable) exit(UWSGI_FAILED_APP_CODE);
516 }
517 else if (!strcmp(what+strlen(what)-4, ".ini")) {
518 callable = uwsgi_paste_loader((void *)what);
519 }
520 else if (strchr(what, ':')) {
521 callable = uwsgi_uwsgi_loader((void *)what);
522 }
523
524 return callable;
525 }
526
527
528 /* this is the dynamic loader, it loads app reading information from a wsgi_request */
uwsgi_dyn_loader(void * arg1)529 PyObject *uwsgi_dyn_loader(void *arg1) {
530
531 PyObject *callable = NULL;
532 char *tmpstr;
533
534 struct wsgi_request *wsgi_req = (struct wsgi_request *) arg1;
535
536 // MANAGE UWSGI_SCRIPT
537 if (wsgi_req->script_len > 0) {
538 tmpstr = uwsgi_strncopy(wsgi_req->script, wsgi_req->script_len);
539 callable = uwsgi_uwsgi_loader((void *)tmpstr);
540 free(tmpstr);
541 }
542 // MANAGE UWSGI_MODULE
543 else if (wsgi_req->module_len > 0) {
544 if (wsgi_req->callable_len > 0) {
545 tmpstr = uwsgi_concat3n(wsgi_req->module, wsgi_req->module_len, ":", 1, wsgi_req->callable, wsgi_req->callable_len);
546 }
547 else {
548 tmpstr = uwsgi_strncopy(wsgi_req->module, wsgi_req->module_len);
549 }
550 callable = uwsgi_uwsgi_loader((void *)tmpstr);
551 free(tmpstr);
552 }
553 // MANAGE UWSGI_FILE
554 else if (wsgi_req->file_len > 0) {
555 tmpstr = uwsgi_strncopy(wsgi_req->file, wsgi_req->file_len);
556 callable = uwsgi_file_loader((void *)tmpstr);
557 free(tmpstr);
558 }
559 // TODO MANAGE UWSGI_PASTE
560 /*
561 else if (wsgi_req->wsgi_paste_len > 0) {
562 tmpstr = uwsgi_strncopy(wsgi_req->paste, wsgi_req->paste_len);
563 callable = uwsgi_paste_loader((void *)tmpstr);
564 free(tmpstr);
565 }
566 */
567
568 return callable;
569 }
570
571
572 /* trying to emulate Graham's mod_wsgi, this will allows easy and fast migrations */
uwsgi_file_loader(void * arg1)573 PyObject *uwsgi_file_loader(void *arg1) {
574
575 char *filename = (char *) arg1;
576 PyObject *wsgi_file_module, *wsgi_file_dict;
577 PyObject *wsgi_file_callable;
578
579 char *callable = up.callable;
580 if (!callable) callable = "application";
581
582 char *pythonized_filename = uwsgi_pythonize(filename);
583 char *py_filename = uwsgi_concat2("uwsgi_file_", pythonized_filename);
584 free(pythonized_filename);
585
586 wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
587 if (!wsgi_file_module) {
588 PyErr_Print();
589 free(py_filename);
590 return NULL;
591 }
592
593 wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
594 if (!wsgi_file_dict) {
595 PyErr_Print();
596 Py_DECREF(wsgi_file_module);
597 free(py_filename);
598 return NULL;
599 }
600
601 wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
602 if (!wsgi_file_callable) {
603 PyErr_Print();
604 Py_DECREF(wsgi_file_dict);
605 Py_DECREF(wsgi_file_module);
606 free(py_filename);
607 uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
608 return NULL;
609 }
610
611 if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
612 uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
613 Py_DECREF(wsgi_file_callable);
614 Py_DECREF(wsgi_file_dict);
615 Py_DECREF(wsgi_file_module);
616 free(py_filename);
617 return NULL;
618 }
619
620 free(py_filename);
621
622 return wsgi_file_callable;
623
624 }
625
uwsgi_pecan_loader(void * arg1)626 PyObject *uwsgi_pecan_loader(void *arg1) {
627
628 char *pecan = (char *) arg1;
629 PyObject *pecan_module, *pecan_dict, *pecan_deploy;
630 PyObject *pecan_arg, *pecan_app;
631
632 uwsgi_log( "Loading pecan environment: %s\n", pecan);
633
634 pecan_module = PyImport_ImportModule("pecan.deploy");
635 if (!pecan_module) {
636 PyErr_Print();
637 exit(UWSGI_FAILED_APP_CODE);
638 }
639
640 pecan_dict = PyModule_GetDict(pecan_module);
641 if (!pecan_dict) {
642 PyErr_Print();
643 exit(UWSGI_FAILED_APP_CODE);
644 }
645
646 pecan_deploy = PyDict_GetItemString(pecan_dict, "deploy");
647 if (!pecan_deploy) {
648 PyErr_Print();
649 exit(UWSGI_FAILED_APP_CODE);
650 }
651
652 pecan_arg = PyTuple_New(1);
653 if (!pecan_arg) {
654 PyErr_Print();
655 exit(UWSGI_FAILED_APP_CODE);
656 }
657
658 if (PyTuple_SetItem(pecan_arg, 0, UWSGI_PYFROMSTRING(pecan))) {
659 PyErr_Print();
660 exit(UWSGI_FAILED_APP_CODE);
661 }
662
663 pecan_app = PyObject_CallObject(pecan_deploy, pecan_arg);
664 if (!pecan_app) {
665 PyErr_Print();
666 exit(UWSGI_FAILED_APP_CODE);
667 }
668
669 return pecan_app;
670 }
671
uwsgi_paste_loader(void * arg1)672 PyObject *uwsgi_paste_loader(void *arg1) {
673
674 char *paste = (char *) arg1;
675 PyObject *paste_module, *paste_dict, *paste_loadapp;
676 PyObject *paste_arg, *paste_app;
677
678 uwsgi_log( "Loading paste environment: %s\n", paste);
679
680 if (up.paste_logger) {
681 PyObject *paste_logger_dict = get_uwsgi_pydict("logging.config");
682 if (paste_logger_dict) {
683 PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
684 if (paste_logger_fileConfig) {
685 PyObject *paste_logger_arg = PyTuple_New(1);
686 if (!paste_logger_arg) {
687 PyErr_Print();
688 exit(UWSGI_FAILED_APP_CODE);
689 }
690 PyTuple_SetItem(paste_logger_arg, 0, UWSGI_PYFROMSTRING(paste+7));
691 if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
692 PyErr_Print();
693 }
694 }
695 }
696 }
697
698 paste_module = PyImport_ImportModule("paste.deploy");
699 if (!paste_module) {
700 PyErr_Print();
701 exit(UWSGI_FAILED_APP_CODE);
702 }
703
704 paste_dict = PyModule_GetDict(paste_module);
705 if (!paste_dict) {
706 PyErr_Print();
707 exit(UWSGI_FAILED_APP_CODE);
708 }
709
710 paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
711 if (!paste_loadapp) {
712 PyErr_Print();
713 exit(UWSGI_FAILED_APP_CODE);
714 }
715
716 paste_arg = PyTuple_New(1);
717 if (!paste_arg) {
718 PyErr_Print();
719 exit(UWSGI_FAILED_APP_CODE);
720 }
721
722 if (PyTuple_SetItem(paste_arg, 0, UWSGI_PYFROMSTRING(paste))) {
723 PyErr_Print();
724 exit(UWSGI_FAILED_APP_CODE);
725 }
726
727 paste_app = PyObject_CallObject(paste_loadapp, paste_arg);
728 if (!paste_app) {
729 PyErr_Print();
730 exit(UWSGI_FAILED_APP_CODE);
731 }
732
733 return paste_app;
734 }
735
uwsgi_eval_loader(void * arg1)736 PyObject *uwsgi_eval_loader(void *arg1) {
737
738 char *code = (char *) arg1;
739
740 PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
741
742 PyObject *wsgi_compiled_node;
743
744 wsgi_compiled_node = Py_CompileString(code, "uwsgi_eval_config", Py_file_input);
745 if (!wsgi_compiled_node) {
746 PyErr_Print();
747 uwsgi_log( "failed to compile eval code\n");
748 exit(UWSGI_FAILED_APP_CODE);
749 }
750
751 wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
752 if (!wsgi_eval_module) {
753 PyErr_Print();
754 exit(UWSGI_FAILED_APP_CODE);
755 }
756
757
758 Py_DECREF(wsgi_compiled_node);
759
760 up.loader_dict = PyModule_GetDict(wsgi_eval_module);
761 if (!up.loader_dict) {
762 PyErr_Print();
763 exit(UWSGI_FAILED_APP_CODE);
764 }
765
766
767 if (up.callable) {
768 wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, up.callable);
769 }
770 else {
771
772 wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, "application");
773 }
774
775 if (wsgi_eval_callable) {
776 if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
777 uwsgi_log( "you must define a callable object in your code\n");
778 exit(UWSGI_FAILED_APP_CODE);
779 }
780 }
781
782 return wsgi_eval_callable;
783
784 }
785
uwsgi_callable_loader(void * arg1)786 PyObject *uwsgi_callable_loader(void *arg1) {
787 return (PyObject *) arg1;
788 }
789
uwsgi_string_callable_loader(void * arg1)790 PyObject *uwsgi_string_callable_loader(void *arg1) {
791 char *callable = (char *) arg1;
792
793 return PyDict_GetItem(up.loader_dict, UWSGI_PYFROMSTRING(callable));
794 }
795