a huge list of threading fixes, we are near to ROCK SOLID threading mode

This commit is contained in:
roberto@sirius
2011-01-13 11:42:59 +01:00
parent f9158b39d8
commit c94206f7ba
14 changed files with 147 additions and 85 deletions
+2 -2
View File
@@ -5,11 +5,11 @@ extern struct uwsgi_python up;
void gil_real_get() {
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
}
void gil_real_release() {
pthread_setspecific(up.upt_save_key, (void *) PyThreadState_Swap(NULL));
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
}
+12 -13
View File
@@ -158,7 +158,6 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
#endif
// check function args
// by defaut it is a WSGI app
wi->argc = 2;
@@ -247,22 +246,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
#endif
}
if (interpreter == NULL && id) {
if (uwsgi.threads > 1 && id) {
// if we have multiple threads we need to initialize a PyThreadState for each one
if (uwsgi.threads > 1) {
for(i=0;i<uwsgi.threads;i++) {
uwsgi.workers[uwsgi.mywid].cores[i]->ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
if (!uwsgi.workers[uwsgi.mywid].cores[i]->ts[id]) {
uwsgi_log("unable to allocate new PyThreadState structure for app %s", mountpoint);
goto doh;
}
for(i=0;i<uwsgi.threads;i++) {
uwsgi.core[i]->ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
if (!uwsgi.core[i]->ts[id]) {
uwsgi_log("unable to allocate new PyThreadState structure for app %s", mountpoint);
goto doh;
}
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
else {
PyThreadState_Swap(up.main_thread);
}
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) );
}
else if (interpreter == NULL && id) {
PyThreadState_Swap(up.main_thread);
}
uwsgi_log("done\n");
if (wi->argc == 1) {
uwsgi_log( "Web3 application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
+11
View File
@@ -124,6 +124,9 @@ int uwsgi_python_init() {
up.gil_get = gil_fake_get;
up.gil_release = gil_fake_release;
up.swap_ts = simple_swap_ts;
up.reset_ts = simple_reset_ts;
return 1;
}
@@ -671,12 +674,19 @@ int uwsgi_python_mount_app(char *mountpoint, char *app) {
uwsgi_error("pthread_key_create()");
exit(1);
}
if (pthread_key_create(&up.upt_gil_key, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
pthread_setspecific(up.upt_save_key, (void *) PyThreadState_Get());
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Get());
pthread_mutex_init(&up.lock_pyloaders, NULL);
pthread_atfork(uwsgi_python_pthread_prepare, uwsgi_python_pthread_parent, uwsgi_python_pthread_child);
up.gil_get = gil_real_get;
up.gil_release = gil_real_release;
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
uwsgi_log("threads support enabled\n");
}
@@ -686,6 +696,7 @@ int uwsgi_python_mount_app(char *mountpoint, char *app) {
PyThreadState *pts;
pts = PyThreadState_New(up.main_thread->interp);
pthread_setspecific(up.upt_save_key, (void *) pts);
pthread_setspecific(up.upt_gil_key, (void *) pts);
}
+14 -8
View File
@@ -410,6 +410,16 @@ PyObject *py_uwsgi_signal(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_log_this(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->log_this = 1;
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_recv_frame(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -763,19 +773,12 @@ PyObject *py_uwsgi_warning(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
char *logline;
time_t tt;
if (!PyArg_ParseTuple(args, "s:log", &logline)) {
return NULL;
}
tt = time(NULL);
if (logline[strlen(logline)] != '\n') {
uwsgi_log( UWSGI_LOGBASE " %.*s] %s\n", 24, ctime(&tt), logline);
}
else {
uwsgi_log( UWSGI_LOGBASE " %.*s] %s", 24, ctime(&tt), logline);
}
uwsgi_log( "%s\n", logline);
Py_INCREF(Py_True);
return Py_True;
@@ -1837,7 +1840,9 @@ PyObject *py_uwsgi_cl(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
#ifdef UWSGI_DEBUG
uwsgi_log( "disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
#endif
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1;
@@ -2111,6 +2116,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"request_id", py_uwsgi_request_id, METH_VARARGS, ""},
{"worker_id", py_uwsgi_worker_id, METH_VARARGS, ""},
{"log", py_uwsgi_log, METH_VARARGS, ""},
{"log_this_request", py_uwsgi_log_this, METH_VARARGS, ""},
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
+9
View File
@@ -108,8 +108,12 @@ struct uwsgi_python {
int current_recursion_depth;
struct _frame* current_frame;
void (*swap_ts)(struct wsgi_request *, struct uwsgi_app *);
void (*reset_ts)(struct wsgi_request *, struct uwsgi_app *);
#ifdef UWSGI_THREADING
pthread_key_t upt_save_key;
pthread_key_t upt_gil_key;
pthread_mutex_t lock_pyloaders;
void (*gil_get) (void);
void (*gil_release) (void);
@@ -209,3 +213,8 @@ void init_uwsgi_module_sharedarea(PyObject *);
void init_uwsgi_module_cache(PyObject *);
PyObject *uwsgi_pyimport_by_filename(char *, char *);
void threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_swap_ts(struct wsgi_request *, struct uwsgi_app *);
void threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
+50 -38
View File
@@ -191,29 +191,15 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
wi = &uwsgi.apps[wsgi_req->app_id];
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
if (!wi->interpreter) {
internal_server_error(wsgi_req->poll.fd, "wsgi application's %d interpreter not found");
goto clear2;
}
// set the interpreter
UWSGI_GET_GIL
if (uwsgi.threads > 1) {
PyThreadState_Swap(uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id]->ts[wsgi_req->app_id]);
}
else {
PyThreadState_Swap(wi->interpreter);
}
UWSGI_RELEASE_GIL
if (wi->chdir) {
up.swap_ts(wsgi_req, wi);
if (wi->chdir) {
#ifdef UWSGI_DEBUG
uwsgi_debug("chdir to %s\n", wi->chdir);
uwsgi_debug("chdir to %s\n", wi->chdir);
#endif
if (chdir(wi->chdir)) {
uwsgi_error("chdir()");
}
}
if (chdir(wi->chdir)) {
uwsgi_error("chdir()");
}
}
@@ -241,8 +227,8 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
UWSGI_GET_GIL
// no fear of race conditions for this counter as it is already protected by the GIL
wi->requests++;
// no fear of race conditions for this counter as it is already protected by the GIL
wi->requests++;
Py_INCREF((PyObject *)wsgi_req->async_environ);
@@ -291,10 +277,11 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
UWSGI_RELEASE_GIL
if (wsgi_req->async_result) {
UWSGI_RELEASE_GIL
while (wi->response_subhandler(wsgi_req) != UWSGI_OK) {
wsgi_req->switches++;
#ifdef UWSGI_ASYNC
@@ -332,7 +319,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
goto clear;
}
// print the error
UWSGI_GET_GIL
PyErr_Print();
UWSGI_RELEASE_GIL
// ...resume the original stderr, in case of error we are damaged forever !!!
if (dup2(tmp_stderr, 2) < 0) {
uwsgi_error("dup2()");
@@ -342,19 +331,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
clear:
UWSGI_GET_GIL
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
// restoring main interpreter
if (uwsgi.threads > 1) {
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
}
else {
PyThreadState_Swap(up.main_thread);
}
}
UWSGI_RELEASE_GIL
up.reset_ts(wsgi_req, wi);
clear2:
@@ -365,7 +342,7 @@ clear2:
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING]) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING] || wsgi_req->log_this) {
log_request(wsgi_req);
}
else {
@@ -416,3 +393,38 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
return (PyObject *) wsgi_req->sendfile_obj;
}
#endif
void threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
UWSGI_GET_GIL
PyThreadState_Swap(uwsgi.core[wsgi_req->async_id]->ts[wsgi_req->app_id]);
UWSGI_RELEASE_GIL
}
}
void threaded_reset_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
UWSGI_GET_GIL
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
UWSGI_RELEASE_GIL
}
}
void simple_reset_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
// restoring main interpreter
PyThreadState_Swap(up.main_thread);
}
}
void simple_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
// set the interpreter
PyThreadState_Swap(wi->interpreter);
}
}