void *uwsgi_python_tracebacker_thread(void *foobar) { struct iovec iov[9]; PyObject *new_thread = uwsgi_python_setup_thread("uWSGITraceBacker"); if (!new_thread) return NULL; struct sockaddr_un so_sun; socklen_t so_sun_len = 0; char *str_wid = uwsgi_num2str(uwsgi.mywid); char *sock_path = uwsgi_concat2(up.tracebacker, str_wid); int current_defer_accept = uwsgi.no_defer_accept; uwsgi.no_defer_accept = 1; int fd = bind_to_unix(sock_path, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); uwsgi.no_defer_accept = current_defer_accept; PyObject *threading_module = PyImport_ImportModule("threading"); if (!threading_module) return NULL; //PyObject *threading_dict = PyModule_GetDict(threading_module); PyObject *traceback_module = PyImport_ImportModule("traceback"); if (!traceback_module) return NULL; PyObject *traceback_dict = PyModule_GetDict(traceback_module); PyObject *extract_stack = PyDict_GetItemString(traceback_dict, "extract_stack"); PyObject *sys_module = PyImport_ImportModule("sys"); PyObject *sys_dict = PyModule_GetDict(sys_module); PyObject *_current_frames = PyDict_GetItemString(sys_dict, "_current_frames"); uwsgi_log("python tracebacker for worker %d available on %s\n", uwsgi.mywid, sock_path); for(;;) { UWSGI_RELEASE_GIL; int client_fd = accept(fd, (struct sockaddr *) &so_sun, &so_sun_len); if (client_fd < 0) { uwsgi_error("accept()"); UWSGI_GET_GIL; continue; } UWSGI_GET_GIL; // here is the core of the tracebacker PyObject *current_frames = PyEval_CallObject(_current_frames, (PyObject *)NULL); if (!current_frames) goto end; uwsgi_log("current_frames = %p\n", current_frames); PyObject *current_frames_items = PyObject_GetAttrString(current_frames, "items"); if (!current_frames_items) goto end; uwsgi_log("current_frames_items = %p\n", current_frames_items); PyObject *frames_ret = PyEval_CallObject(current_frames_items, (PyObject *)NULL); if (!frames_ret) goto end; uwsgi_log("frames_ret = %p\n", frames_ret); PyObject *frames_iter = PyObject_GetIter(frames_ret); uwsgi_log("frames_iter = %p\n", frames_iter); PyObject *frame = PyIter_Next(frames_iter); while(frame) { uwsgi_log("frame = %p\n", frame); PyObject *stack = PyTuple_GetItem(frame, 1); uwsgi_log("stack = %p\n", stack); PyObject *arg_tuple = PyTuple_New(1); PyTuple_SetItem(arg_tuple, 0, stack); PyObject *stacktrace = PyEval_CallObject( extract_stack, arg_tuple); uwsgi_log("stacktrace = %p\n", stacktrace); PyObject *stacktrace_iter = PyObject_GetIter(stacktrace); PyObject *st_items = PyIter_Next(stacktrace_iter); while(st_items) { uwsgi_log("st_items = %p\n", st_items); PyObject *st_filename = PyTuple_GetItem(st_items, 0); PyObject *st_lineno = PyTuple_GetItem(st_items, 1); PyObject *st_name = PyTuple_GetItem(st_items, 2); PyObject *st_line = PyTuple_GetItem(st_items, 3); iov[0].iov_base = "filename = "; iov[0].iov_len = 11; iov[1].iov_base = PyString_AsString(st_filename); iov[1].iov_len = strlen(iov[1].iov_base); iov[2].iov_base = " lineno = "; iov[2].iov_len = 10 ; iov[3].iov_base = uwsgi_num2str(PyInt_AsLong(st_lineno)); iov[3].iov_len = strlen(iov[3].iov_base); iov[4].iov_base = " function = "; iov[4].iov_len = 12 ; iov[5].iov_base = PyString_AsString(st_name); iov[5].iov_len = strlen(iov[5].iov_base); iov[6].iov_base = "\n"; iov[6].iov_len = 1 ; if (st_line) { } if (writev(client_fd, iov, 7) < 0) { uwsgi_error("writev()"); } st_items = PyIter_Next(stacktrace_iter); } frame = PyIter_Next(frames_iter); } end: close(client_fd); } return NULL; }
void *uwsgi_python_autoreloader_thread(void *foobar) { PyObject *new_thread = uwsgi_python_setup_thread("uWSGIAutoReloader"); if (!new_thread) return NULL; PyObject *modules = PyImport_GetModuleDict(); if (uwsgi.mywid == 1) { uwsgi_log("Python auto-reloader enabled\n"); } PyObject *times_dict = PyDict_New(); char *filename; for(;;) { UWSGI_RELEASE_GIL; sleep(up.auto_reload); UWSGI_GET_GIL; // do not start monitoring til the first app is loaded (required for lazy mode) if (uwsgi_apps_cnt == 0) continue; #ifdef UWSGI_PYTHON_OLD int pos = 0; #else Py_ssize_t pos = 0; #endif PyObject *mod_name, *mod; while (PyDict_Next(modules, &pos, &mod_name, &mod)) { int found = 0; struct uwsgi_string_list *usl = up.auto_reload_ignore; while(usl) { if (!strcmp(usl->value, PyString_AsString(mod_name))) { found = 1; break; } usl = usl->next; } if (found) continue; if (!PyObject_HasAttrString(mod, "__file__")) continue; PyObject *mod_file = PyObject_GetAttrString(mod, "__file__"); if (!mod_file) continue; #ifdef PYTHREE PyObject *zero = PyUnicode_AsUTF8String(mod_file); char *mod_filename = PyString_AsString(zero); #else char *mod_filename = PyString_AsString(mod_file); #endif if (!mod_filename) { #ifdef PYTHREE Py_DECREF(zero); #endif continue; } char *ext = strrchr(mod_filename, '.'); if (ext && (!strcmp(ext+1, "pyc") || !strcmp(ext+1, "pyd") || !strcmp(ext+1, "pyo"))) { filename = uwsgi_concat2n(mod_filename, strlen(mod_filename)-1, "", 0); } else { filename = uwsgi_concat2(mod_filename, ""); } if (uwsgi_check_python_mtime(times_dict, filename)) { UWSGI_RELEASE_GIL; return NULL; } free(filename); #ifdef PYTHREE Py_DECREF(zero); #endif } } return NULL; }
void *uwsgi_python_tracebacker_thread(void *foobar) { struct iovec iov[11]; PyObject *new_thread = uwsgi_python_setup_thread("uWSGITraceBacker"); if (!new_thread) return NULL; struct sockaddr_un so_sun; socklen_t so_sun_len = 0; char *str_wid = uwsgi_num2str(uwsgi.mywid); char *sock_path = uwsgi_concat2(up.tracebacker, str_wid); int current_defer_accept = uwsgi.no_defer_accept; uwsgi.no_defer_accept = 1; int fd = bind_to_unix(sock_path, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); if (fd < 0) { uwsgi.no_defer_accept = current_defer_accept; free(str_wid); free(sock_path); return NULL; } uwsgi.no_defer_accept = current_defer_accept; PyObject *traceback_module = PyImport_ImportModule("traceback"); if (!traceback_module) { free(str_wid); free(sock_path); close(fd); return NULL; } PyObject *traceback_dict = PyModule_GetDict(traceback_module); PyObject *extract_stack = PyDict_GetItemString(traceback_dict, "extract_stack"); PyObject *sys_module = PyImport_ImportModule("sys"); PyObject *sys_dict = PyModule_GetDict(sys_module); PyObject *_current_frames = PyDict_GetItemString(sys_dict, "_current_frames"); uwsgi_log("python tracebacker for worker %d available on %s\n", uwsgi.mywid, sock_path); for(;;) { UWSGI_RELEASE_GIL; int client_fd = accept(fd, (struct sockaddr *) &so_sun, &so_sun_len); if (client_fd < 0) { uwsgi_error("accept()"); UWSGI_GET_GIL; continue; } UWSGI_GET_GIL; // here is the core of the tracebacker PyObject *current_frames = PyEval_CallObject(_current_frames, (PyObject *)NULL); if (!current_frames) goto end2; PyObject *current_frames_items = PyObject_GetAttrString(current_frames, "items"); if (!current_frames_items) goto end; PyObject *frames_ret = PyEval_CallObject(current_frames_items, (PyObject *)NULL); if (!frames_ret) goto end3; PyObject *frames_iter = PyObject_GetIter(frames_ret); if (!frames_iter) goto end4; // we have the first frame, lets parse it if (write(client_fd, "*** uWSGI Python tracebacker output ***\n\n", 41) < 0) { uwsgi_error("write()"); } PyObject *frame = PyIter_Next(frames_iter); while(frame) { PyObject *thread_id = PyTuple_GetItem(frame, 0); if (!thread_id) goto next2; PyObject *stack = PyTuple_GetItem(frame, 1); if (!stack) goto next2; PyObject *arg_tuple = PyTuple_New(1); PyTuple_SetItem(arg_tuple, 0, stack); Py_INCREF(stack); PyObject *stacktrace = PyEval_CallObject( extract_stack, arg_tuple); Py_DECREF(arg_tuple); if (!stacktrace) goto next2; PyObject *stacktrace_iter = PyObject_GetIter(stacktrace); if (!stacktrace_iter) { Py_DECREF(stacktrace); goto next2;} PyObject *st_items = PyIter_Next(stacktrace_iter); // we have the first traceback item while(st_items) { #ifdef PYTHREE int thread_name_need_free = 0; #endif PyObject *st_filename = PyTuple_GetItem(st_items, 0); if (!st_filename) { Py_DECREF(st_items); goto next; } PyObject *st_lineno = PyTuple_GetItem(st_items, 1); if (!st_lineno) {Py_DECREF(st_items); goto next;} PyObject *st_name = PyTuple_GetItem(st_items, 2); if (!st_name) {Py_DECREF(st_items); goto next;} PyObject *st_line = PyTuple_GetItem(st_items, 3); iov[0].iov_base = "thread_id = "; iov[0].iov_len = 12; iov[1].iov_base = uwsgi_python_get_thread_name(thread_id); if (!iov[1].iov_base) { iov[1].iov_base = "<UnnamedPythonThread>"; } #ifdef PYTHREE else { thread_name_need_free = 1; } #endif iov[1].iov_len = strlen(iov[1].iov_base); iov[2].iov_base = " filename = "; iov[2].iov_len = 12; #ifdef PYTHREE PyObject *st_filename_utf8 = PyUnicode_AsUTF8String(st_filename); if (!st_filename_utf8) { if (thread_name_need_free) free(iov[1].iov_base); goto next; } iov[3].iov_base = PyString_AsString(st_filename_utf8); #else iov[3].iov_base = PyString_AsString(st_filename); #endif iov[3].iov_len = strlen(iov[3].iov_base); iov[4].iov_base = " lineno = "; iov[4].iov_len = 10 ; iov[5].iov_base = uwsgi_num2str(PyInt_AsLong(st_lineno)); iov[5].iov_len = strlen(iov[5].iov_base); iov[6].iov_base = " function = "; iov[6].iov_len = 12 ; #ifdef PYTHREE PyObject *st_name_utf8 = PyUnicode_AsUTF8String(st_name); if (!st_name_utf8) { if (thread_name_need_free) free(iov[1].iov_base); Py_DECREF(st_filename_utf8); goto next; } iov[7].iov_base = PyString_AsString(st_name_utf8); #else iov[7].iov_base = PyString_AsString(st_name); #endif iov[7].iov_len = strlen(iov[7].iov_base); iov[8].iov_base = ""; iov[8].iov_len = 0 ; iov[9].iov_base = ""; iov[9].iov_len = 0; iov[10].iov_base = "\n"; iov[10].iov_len = 1; #ifdef PYTHREE PyObject *st_line_utf8 = NULL; #endif if (st_line) { iov[8].iov_base = " line = "; iov[8].iov_len = 8; #ifdef PYTHREE PyObject *st_line_utf8 = PyUnicode_AsUTF8String(st_line); if (!st_line_utf8) { if (thread_name_need_free) free(iov[1].iov_base); Py_DECREF(st_filename_utf8); Py_DECREF(st_name_utf8); goto next; } iov[9].iov_base = PyString_AsString(st_line_utf8); #else iov[9].iov_base = PyString_AsString(st_line); #endif iov[9].iov_len = strlen(iov[9].iov_base); } if (writev(client_fd, iov, 11) < 0) { uwsgi_error("writev()"); } // free the line_no free(iov[5].iov_base); Py_DECREF(st_items); #ifdef PYTHREE Py_DECREF(st_filename_utf8); Py_DECREF(st_name_utf8); if (st_line_utf8) { Py_DECREF(st_line_utf8); } if (thread_name_need_free) free(iov[1].iov_base); #endif st_items = PyIter_Next(stacktrace_iter); } if (write(client_fd, "\n", 1) < 0) { uwsgi_error("write()"); } next: Py_DECREF(stacktrace_iter); Py_DECREF(stacktrace); next2: Py_DECREF(frame); frame = PyIter_Next(frames_iter); } Py_DECREF(frames_iter); end4: Py_DECREF(frames_ret); end3: Py_DECREF(current_frames_items); end: Py_DECREF(current_frames); end2: close(client_fd); } return NULL; }