119
119
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
120
120
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
122
#ifdef UWSGI_THREADING
123
{"py-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
124
{"py-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
125
{"python-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
126
{"python-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
127
{"py-auto-reload-ignore", required_argument, 0, "ignore the specified module during auto-reload scan (can be specified multiple times)", uwsgi_opt_add_string_list, &up.auto_reload_ignore, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
122
130
{0, 0, 0, 0, 0, 0, 0},
143
151
#ifndef UWSGI_PYPY
144
152
char *pyversion = strchr(Py_GetVersion(), '\n');
145
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
154
uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
157
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
147
160
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
151
163
if (up.home != NULL) {
153
165
wchar_t *wpyhome;
166
178
uwsgi_log("Set PythonHome to %s\n", up.home);
170
183
wchar_t pname[6];
171
184
mbstowcs(pname, "uWSGI", 6);
172
185
Py_SetProgramName(pname);
175
187
Py_SetProgramName("uWSGI");
179
192
Py_OptimizeFlag = up.optimize;
197
if (!uwsgi.has_threads) {
198
uwsgi_log("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
186
201
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
187
202
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
1054
1078
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
1057
1082
if (uwsgi.profiler) {
1059
1083
if (!strcmp(uwsgi.profiler, "pycall")) {
1060
1084
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
1086
else if (!strcmp(uwsgi.profiler, "pyline")) {
1087
PyEval_SetTrace(uwsgi_python_tracer, NULL);
1065
1092
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
1066
1093
if (uwsgi_dict) {
1198
#ifdef UWSGI_THREADING
1199
int uwsgi_check_python_mtime(PyObject *times_dict, char *filename) {
1202
PyObject *py_mtime = PyDict_GetItemString(times_dict, filename);
1204
if (stat(filename, &st)) {
1207
PyDict_SetItemString(times_dict, filename, PyLong_FromLong(st.st_mtime));
1209
// the record is already tracked;
1211
long mtime = PyLong_AsLong(py_mtime);
1213
if (stat(filename, &st)) {
1217
if ((long) st.st_mtime != mtime) {
1218
uwsgi_log("[uwsgi-python-reloader] module/file %s has been modified\n", filename);
1219
kill(uwsgi.workers[0].pid, SIGHUP);
1225
void *uwsgi_python_autoreloader_thread(void *foobar) {
1229
// block signals on this thread
1233
sigdelset(&smask, SIGSEGV);
1235
pthread_sigmask(SIG_BLOCK, &smask, NULL);
1237
PyThreadState *pts = PyThreadState_New(up.main_thread->interp);
1238
pthread_setspecific(up.upt_save_key, (void *) pts);
1239
pthread_setspecific(up.upt_gil_key, (void *) pts);
1241
PyObject *threading_module = PyImport_ImportModule("threading");
1242
if (threading_module) {
1243
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
1244
if (threading_module_dict) {
1246
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
1248
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
1250
if (threading_current) {
1251
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
1252
if (!current_thread) {
1257
PyObject_SetAttrString(current_thread, "name", PyString_FromString("uWSGIAutoReloader"));
1258
Py_INCREF(current_thread);
1259
modules = PyImport_GetModuleDict();
1268
if (uwsgi.mywid == 1) {
1269
uwsgi_log("Python auto-reloader enabled\n");
1271
PyObject *times_dict = PyDict_New();
1275
sleep(up.auto_reload);
1277
// do not start monitoring til the first app is loaded (required for lazy mode)
1278
if (uwsgi_apps_cnt == 0) continue;
1279
#ifdef UWSGI_PYTHON_OLD
1284
PyObject *mod_name, *mod;
1285
while (PyDict_Next(modules, &pos, &mod_name, &mod)) {
1287
struct uwsgi_string_list *usl = up.auto_reload_ignore;
1289
if (!strcmp(usl->value, PyString_AsString(mod_name))) {
1295
if (found) continue;
1296
if (!PyObject_HasAttrString(mod, "__file__")) continue;
1297
PyObject *mod_file = PyObject_GetAttrString(mod, "__file__");
1298
if (!mod_file) continue;
1300
PyObject *zero = PyUnicode_AsUTF8String(mod_file);
1301
char *mod_filename = PyString_AsString(zero);
1303
char *mod_filename = PyString_AsString(mod_file);
1305
if (!mod_filename) {
1311
char *ext = strrchr(mod_filename, '.');
1312
if (ext && (!strcmp(ext+1, "pyc") || !strcmp(ext+1, "pyd") || !strcmp(ext+1, "pyo"))) {
1313
filename = uwsgi_concat2n(mod_filename, strlen(mod_filename)-1, "", 0);
1316
filename = uwsgi_concat2(mod_filename, "");
1318
if (uwsgi_check_python_mtime(times_dict, filename)) {
1171
1333
#ifndef UWSGI_PYPY
1172
1334
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {