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