trying to understand why multirheading is flaky on pypy

This commit is contained in:
Unbit
2013-05-18 12:17:43 +02:00
parent a508c7f53e
commit c2f36968c3
2 changed files with 87 additions and 40 deletions
+39 -21
View File
@@ -26,7 +26,7 @@ void (*pypy_init_threads)(void);
// the hooks you can override with pypy
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_request)(void *);
void (*uwsgi_pypy_hook_request)(int);
extern struct uwsgi_server uwsgi;
struct uwsgi_plugin pypy_plugin;
@@ -43,43 +43,51 @@ int uwsgi_pypy_helper_register_signal(int signum, char *kind, void *handler) {
return uwsgi_register_signal(signum, kind, handler, pypy_plugin.modifier1);
}
int uwsgi_pypy_helper_vars(void *r) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
int uwsgi_pypy_helper_register_rpc(char *name, int argc, void *func) {
return uwsgi_register_rpc(name, &pypy_plugin, argc, func);
}
int uwsgi_pypy_helper_vars(int core) {
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
return wsgi_req->var_cnt;
}
char *uwsgi_pypy_helper_key(void *r, int pos) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
char *uwsgi_pypy_helper_key(int core, int pos) {
uwsgi_log("[key] core = %d pos = %d\n", core, pos);
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
return wsgi_req->hvec[pos].iov_base;
}
int uwsgi_pypy_helper_keylen(void *r, int pos) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
int uwsgi_pypy_helper_keylen(int core, int pos) {
uwsgi_log("[keylen] core = %d pos = %d\n", core, pos);
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
return wsgi_req->hvec[pos].iov_len;
}
char *uwsgi_pypy_helper_val(void *r, int pos) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
char *uwsgi_pypy_helper_val(int core, int pos) {
uwsgi_log("[val] core = %d pos = %d\n", core, pos);
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
return wsgi_req->hvec[pos+1].iov_base;
}
int uwsgi_pypy_helper_vallen(void *r, int pos) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
int uwsgi_pypy_helper_vallen(int core, int pos) {
uwsgi_log("[vallen] core = %d pos = %d\n", core, pos);
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
return wsgi_req->hvec[pos+1].iov_len;
}
void uwsgi_pypy_helper_status(void *r, char *status, int status_len) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
void uwsgi_pypy_helper_status(int core, char *status, int status_len) {
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
uwsgi_response_prepare_headers(wsgi_req, status, status_len);
}
void uwsgi_pypy_helper_header(void *r, char *k, int kl, char *v, int vl) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
void uwsgi_pypy_helper_header(int core, char *k, int kl, char *v, int vl) {
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
uwsgi_response_add_header(wsgi_req, k, kl, v, vl);
}
void uwsgi_pypy_helper_write(void *r, char *body, int len) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) r;
void uwsgi_pypy_helper_write(int core, char *body, int len) {
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core].req;
uwsgi_response_write_body_do(wsgi_req, body, len);
}
@@ -172,7 +180,7 @@ static int uwsgi_pypy_request(struct wsgi_request *wsgi_req) {
}
if (uwsgi_pypy_hook_request) {
uwsgi_pypy_hook_request(wsgi_req);
uwsgi_pypy_hook_request(wsgi_req->async_id);
}
return UWSGI_OK;
}
@@ -205,14 +213,12 @@ static struct uwsgi_option uwsgi_pypy_options[] = {
static void uwsgi_pypy_enable_threads() {
if (pypy_init_threads) {
pypy_init_threads();
uwsgi_log("THREADS ENABLED !!!\n");
}
}
static void uwsgi_pypy_init_thread() {
uwsgi_log("initializing thread...\n");
if (pypy_thread_attach) {
//pypy_thread_attach();
pypy_thread_attach();
}
}
@@ -222,6 +228,17 @@ static int uwsgi_pypy_signal_handler(uint8_t sig, void *handler) {
return 0;
}
static uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
int iargvs[UMAX8];
int i;
int (*pypy_func)(int, char **, int*, char *) = (int (*)(int, char **, int*, char *)) func;
// we convert 16bit to int
for(i=0;i<argc;i++) {
iargvs[i] = (int) argvs[i];
}
return pypy_func(argc, argv, iargvs, buffer);
}
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
.modifier1 = 0,
@@ -233,4 +250,5 @@ struct uwsgi_plugin pypy_plugin = {
.init_thread = uwsgi_pypy_init_thread,
.signal_handler = uwsgi_pypy_signal_handler,
.enable_threads = uwsgi_pypy_enable_threads,
.rpc = uwsgi_python_rpc,
};
+48 -19
View File
@@ -1,28 +1,31 @@
import sys
sys.path.insert(0, '.')
import cffi
# this is a list holding object we do not want to be freed (like callback and handlers)
uwsgi_gc = []
defines = '''
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_request)(void *);
void (*uwsgi_pypy_hook_request)(int);
char *uwsgi_pypy_helper_key(void *, int);
int uwsgi_pypy_helper_keylen(void *, int);
char *uwsgi_pypy_helper_key(int, int);
int uwsgi_pypy_helper_keylen(int, int);
char *uwsgi_pypy_helper_val(void *, int);
int uwsgi_pypy_helper_vallen(void *, int);
char *uwsgi_pypy_helper_val(int, int);
int uwsgi_pypy_helper_vallen(int, int);
int uwsgi_pypy_helper_vars(void *);
int uwsgi_pypy_helper_vars(int);
void uwsgi_pypy_helper_status(void *, char *, int);
void uwsgi_pypy_helper_header(void *, char *, int, char *, int);
void uwsgi_pypy_helper_status(int, char *, int);
void uwsgi_pypy_helper_header(int, char *, int, char *, int);
void uwsgi_pypy_helper_write(void *, char *, int);
void uwsgi_pypy_helper_write(int, char *, int);
char *uwsgi_pypy_helper_version();
int uwsgi_pypy_helper_register_signal(int, char *, void *);
int uwsgi_pypy_helper_register_rpc(char *, int, void *);
void uwsgi_pypy_helper_signal(int);
'''
@@ -42,39 +45,42 @@ def uwsgi_pypy_loader(module):
mod = __import__(m)
wsgi_application = getattr(mod, c)
@ffi.callback("void(void *)")
def uwsgi_pypy_wsgi_handler(wsgi_req):
@ffi.callback("void(int)")
def uwsgi_pypy_wsgi_handler(core):
global wsgi_application
def writer(data):
lib.uwsgi_pypy_helper_write(wsgi_req, ffi.new("char[]", data), len(data))
lib.uwsgi_pypy_helper_write(core, ffi.new("char[]", data), len(data))
def start_response(status, headers, exc_info=None):
lib.uwsgi_pypy_helper_status(wsgi_req, ffi.new("char[]", status), len(status))
lib.uwsgi_pypy_helper_status(core, ffi.new("char[]", status), len(status))
for hh in headers:
lib.uwsgi_pypy_helper_header(wsgi_req, ffi.new("char[]", hh[0]), len(hh[0]), ffi.new("char[]", hh[1]), len(hh[1]))
lib.uwsgi_pypy_helper_header(core, ffi.new("char[]", hh[0]), len(hh[0]), ffi.new("char[]", hh[1]), len(hh[1]))
return writer
class WSGIinput():
pass
environ = {}
n = lib.uwsgi_pypy_helper_vars(wsgi_req)
n = lib.uwsgi_pypy_helper_vars(core)
print "[n] core = %d vars = %d" % (core, n)
for i in range(0, n, 2):
key = ffi.string( lib.uwsgi_pypy_helper_key(wsgi_req, i), lib.uwsgi_pypy_helper_keylen(wsgi_req, i) )
value = ffi.string( lib.uwsgi_pypy_helper_val(wsgi_req, i), lib.uwsgi_pypy_helper_vallen(wsgi_req, i) )
key = ffi.string( lib.uwsgi_pypy_helper_key(core, i), lib.uwsgi_pypy_helper_keylen(core, i) )
value = ffi.string( lib.uwsgi_pypy_helper_val(core, i), lib.uwsgi_pypy_helper_vallen(core, i) )
environ[key] = value
environ['wsgi.version'] = (1, 0)
scheme = 'http'
if 'HTTPS' in environ:
if environ['HTTPS'] in ('on', 'ON', 'On', '1', 'true', 'TRUE'):
if environ['HTTPS'] in ('on', 'ON', 'On', '1', 'true', 'TRUE', 'True'):
scheme = 'https'
environ['wsgi.url_scheme'] = environ.get('UWSGI_SCHEME', scheme)
environ['wsgi.input'] = WSGIinput
environ['wsgi.errors'] = sys.stderr
environ['wsgi.run_once'] = False
environ['uwsgi.core'] = core
response = wsgi_application(environ, start_response)
if type(response) == 'str':
writer(response)
@@ -95,12 +101,35 @@ sys.modules['uwsgi'] = uwsgi
uwsgi.version = ffi.string( lib.uwsgi_pypy_helper_version() )
def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
global uwsgi_gc
uwsgi_gc.append(handler)
if lib.uwsgi_pypy_helper_register_signal(signum, ffi.new("char[]", kind), ffi.callback('void(int)', handler)) < 0:
raise Exception("unable to register signal %d" % signum)
uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal
class uwsgi_pypy_RPC():
def __init__(self, func):
self.func = func
def __call__(self, argc, argv, argvs, buf):
pargs = []
for i in range(0, argc):
pargs.append(ffi.string(argv[i],argvs[i]))
response = self.func(*pargs)
if len(response) > 0 and len(response) <= 65535:
dst = ffi.buffer(buf, 65536)
dst[:len(response)] = response
return len(response)
def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
global uwsgi_gc
uwsgi_gc.append(func)
if lib.uwsgi_pypy_helper_register_rpc(ffi.new("char[]", name), argc, ffi.callback("int(int, char*[], int[], char*)", uwsgi_pypy_RPC(func))) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
def uwsgi_pypy_uwsgi_signal(signum):
lib.uwsgi_pypy_helper_signal(signum)
uwsgi.signal = uwsgi_pypy_uwsgi_signal
print "Initialized PyPy with Python",sys.version