From 2e29b6b234f1cf64d01237e371b798a97eac08ec Mon Sep 17 00:00:00 2001 From: "roberto@sirius" Date: Wed, 10 Feb 2010 17:28:58 +0100 Subject: [PATCH] first (destructive) public commit for the 0.9.5 branch --- ChangeLog | 10 ++ Makefile | 2 + Makefile.Py24 | 2 + Makefile.Py26 | 2 + Makefile.Py30 | 2 + Makefile.Py31 | 2 + base.mk | 2 +- logging.c | 20 +-- logo_uWSGI.png | Bin 0 -> 5971 bytes plugins/example/example_plugin.c | 6 +- plugins/lua/lua_plugin.c | 241 +++++++++++++++++++++++++++++++ staticfile.py | 4 + testapp.py | 2 +- uwsgi.c | 106 +++++++------- uwsgi.h | 5 +- uwsgi_pymodule.c | 9 +- wsgi_handlers.c | 132 ++++++++--------- 17 files changed, 408 insertions(+), 139 deletions(-) create mode 100644 logo_uWSGI.png create mode 100644 plugins/lua/lua_plugin.c create mode 100644 staticfile.py diff --git a/ChangeLog b/ChangeLog index 08a6f197..e1a6a50e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +*** february 2010 *** + * Maintenance release * + +- better support for NetBSD +- threading fix for FreeBSD +- sendfile portability fixes +- new makefiles +- example app for testing static file serving +- fixes for ROCK_SOLID mode + *** january 2010 *** - Integrated Spooler diff --git a/Makefile b/Makefile index c4c325b6..93708602 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ XML_LIBS=`xml2-config --libs` CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) +UWSGI_BASEFLAGS=`python2.5 ucheck.py` + PROGRAM=uwsgi include base.mk diff --git a/Makefile.Py24 b/Makefile.Py24 index 4d79918e..c72a57d9 100644 --- a/Makefile.Py24 +++ b/Makefile.Py24 @@ -8,6 +8,8 @@ XML_LIBS=`xml2-config --libs` CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) +UWSGI_BASEFLAGS=`python2.4 ucheck.py` + PROGRAM=uwsgi24 include base.mk diff --git a/Makefile.Py26 b/Makefile.Py26 index ff1feba0..60f8bc26 100644 --- a/Makefile.Py26 +++ b/Makefile.Py26 @@ -8,6 +8,8 @@ XML_LIBS=`xml2-config --libs` CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) +UWSGI_BASEFLAGS=`python2.6 ucheck.py` + PROGRAM=uwsgi26 include base.mk diff --git a/Makefile.Py30 b/Makefile.Py30 index 88b217a2..70c98a77 100644 --- a/Makefile.Py30 +++ b/Makefile.Py30 @@ -8,6 +8,8 @@ XML_LIBS=`xml2-config --libs` CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) +UWSGI_BASEFLAGS=`python3.0 ucheck.py` + PROGRAM=uwsgi30 include base.mk diff --git a/Makefile.Py31 b/Makefile.Py31 index 5aad3aa3..3028c6b7 100644 --- a/Makefile.Py31 +++ b/Makefile.Py31 @@ -8,6 +8,8 @@ XML_LIBS=`xml2-config --libs` CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) +UWSGI_BASEFLAGS=`python3.1 ucheck.py` + PROGRAM=uwsgi31 include base.mk diff --git a/base.mk b/base.mk index 34ffb89f..dab8d98f 100644 --- a/base.mk +++ b/base.mk @@ -14,7 +14,7 @@ LD_FLAGS := $(LD_FLAGS) $(UWSGI_LD_FLAGS) all: clean uwsgi uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o logging.o snmp.o wsgihandlers.o basehandlers.o main.o - $(CC) $(LD_FLAGS) utils.o protocol.o socket.o spooler.o logging.o snmp.o pymodule.o wsgihandlers.o basehandlers.o main.o -o $(PROGRAM) + $(CC) $(LD_FLAGS) $(UWSGI_BASEFLAGS) -lpthread utils.o protocol.o socket.o spooler.o logging.o snmp.o pymodule.o wsgihandlers.o basehandlers.o main.o -o $(PROGRAM) utils.o: utils.c $(CC) -c $(CFLAGS) utils.c diff --git a/logging.c b/logging.c index cd3555b8..4e3cb7c7 100644 --- a/logging.c +++ b/logging.c @@ -4,7 +4,6 @@ extern struct uwsgi_server uwsgi; void log_request(struct wsgi_request *wsgi_req) { char *time_request ; - struct timeval end_request ; time_t microseconds, microseconds2; @@ -27,20 +26,19 @@ void log_request(struct wsgi_request *wsgi_req) { } } via = msg2 ; + if (wsgi_req->sendfile_fd > -1) { via = msg1 ; } #endif time_request = ctime( (const time_t *) &wsgi_req->start_of_request.tv_sec); - gettimeofday(&end_request, NULL) ; - microseconds = end_request.tv_sec*1000000+end_request.tv_usec ; + microseconds = wsgi_req->end_of_request.tv_sec*1000000+wsgi_req->end_of_request.tv_usec ; microseconds2 = wsgi_req->start_of_request.tv_sec*1000000+wsgi_req->start_of_request.tv_usec ; #ifndef ROCK_SOLID - if (uwsgi.options[UWSGI_OPTION_MEMORY_DEBUG] == 1) { - get_memusage(); + if (uwsgi.options[UWSGI_OPTION_MEMORY_DEBUG] == 1) { #ifndef UNBIT if (uwsgi.synclog) { snprintf(uwsgi.sync_page, uwsgi.page_size, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size/1024/1024, uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size/1024/1024) ; @@ -55,8 +53,6 @@ void log_request(struct wsgi_request *wsgi_req) { } #endif - uwsgi.workers[uwsgi.mywid].running_time += (double) (( (double)microseconds-(double)microseconds2)/ (double)1000.0) ; - #ifdef ROCK_SOLID fprintf(stderr, "[pid: %d|req: %llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %d bytes in %ld msecs (%.*s %d) %d headers in %d bytes\n", uwsgi.mypid, uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, @@ -81,8 +77,7 @@ void get_memusage() { #ifdef UNBIT uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356); -#else -#ifdef __linux__ +#elif defined(__linux__) FILE *procfile; int i; procfile = fopen("/proc/self/stat","r"); @@ -94,9 +89,8 @@ void get_memusage() { fclose(procfile); } uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size*uwsgi.page_size; -#endif -#ifdef __APPLE__ - /* darwin documentation says that the value are in pages, bot they are bytes !!! */ +#elif defined( __APPLE__) + /* darwin documentation says that the value are in pages, but they are bytes !!! */ struct task_basic_info t_info; mach_msg_type_number_t t_size = sizeof(struct task_basic_info); @@ -104,8 +98,8 @@ void get_memusage() { uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size; uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size; } +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#endif #endif } #endif diff --git a/logo_uWSGI.png b/logo_uWSGI.png new file mode 100644 index 0000000000000000000000000000000000000000..1455d2bf8486a8e63ca8cadbeef22b8ce424b96a GIT binary patch literal 5971 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 +#include + + +static struct uwsgi_lua { + struct lua_State *L ; + struct uwsgi_server *uwsgi; +} ulua; + +static void *uwsgi_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { + if(nsize == 0) { + free(ptr); + return NULL; + } + + return realloc(ptr, nsize); +} + +static const char *uwsgi_read_lua(lua_State *L, void *data, size_t *size) { + + int fd = *(int *)data; + static char buf[4096]; + + *size = read(fd, buf, 4096); + + if (size == 0) { + return NULL; + } + + return buf; +} + +static int uwsgi_lua_input(lua_State *L) { + + int n = lua_gettop(L); + + static char *buf = "" ; + + fprintf(stderr,"richiesti %d bytes\n", n); + + //sum = read(ulua.uwsgi->poll.fd,); + + lua_pushlstring(L, buf, 0); + + return 1; +} + +void uwsgi_init(struct uwsgi_server *uwsgi, char *args){ + + int fd, i; + + fprintf(stderr,"Initializing Lua environment...\n"); + + + + + ulua.L = lua_newstate(uwsgi_lua_alloc, NULL); + + luaL_openlibs(ulua.L); + + + fd = open(args, O_RDONLY) ; + if (fd < 0) { + perror("open()"); + return ; + } + + + i = lua_load(ulua.L, uwsgi_read_lua, &fd, "uwsgi"); + + fprintf(stderr,"lua_load: %d\n" ,i); + + // use a pcall + lua_call(ulua.L, 0, 1); + + fprintf(stderr,"%s\n", lua_typename(ulua.L, lua_type(ulua.L, -1))); + + // ok the lua engine is ready + return ; + + +} + +int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { + + char *ptrbuf; + char *bufferend; + uint16_t strsize = 0; + int i; + const char *http ; + size_t slen ; + + /* Standard WSAPI request */ + if (!wsgi_req->size) { + fprintf (stderr, "Invalid WSAPI request. skip.\n"); + return -1; + } + + ptrbuf = buffer; + bufferend = ptrbuf + wsgi_req->size; + + /* set an HTTP 500 status as default */ + wsgi_req->status = 500; + + while (ptrbuf < bufferend) { + if (ptrbuf + 2 < bufferend) { + memcpy (&strsize, ptrbuf, 2); +#ifdef __BIG_ENDIAN__ + strsize = uwsgi_swap16 (strsize); +#endif + ptrbuf += 2; + if (ptrbuf + strsize < bufferend) { + // var key + uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf; + uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize; + ptrbuf += strsize; + if (ptrbuf + 2 < bufferend) { + memcpy (&strsize, ptrbuf, 2); +#ifdef __BIG_ENDIAN__ + strsize = uwsgi_swap16 (strsize); +#endif + ptrbuf += 2; + if (ptrbuf + strsize <= bufferend) { + if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) { + wsgi_req->var_cnt++; + } + else { + fprintf (stderr, "max vec size reached. skip this header.\n"); + break; + } + // var value + uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf; + uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize; + if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) { + wsgi_req->var_cnt++; + } + else { + fprintf (stderr, "max vec size reached. skip this header.\n"); + break; + } + ptrbuf += strsize; + } + else { + break; + } + } + else { + break; + } + } + } + else { + break; + } + } + + // put function in the stack + lua_pushvalue(ulua.L, -1); + lua_getfield(ulua.L, -1, "run"); + + // put cgi vars in the stack + lua_newtable(ulua.L); + lua_pushstring(ulua.L, ""); + lua_setfield(ulua.L, -2, "CONTENT_TYPE"); + for(i=0;ivar_cnt;i++) { + lua_pushlstring(ulua.L, (char *)uwsgi->hvec[i+1].iov_base, uwsgi->hvec[i+1].iov_len); + // transform it in a valid c string TODO this is ugly + ptrbuf = uwsgi->hvec[i].iov_base+uwsgi->hvec[i].iov_len ; + *ptrbuf = 0 ; + lua_setfield(ulua.L, -2, (char *)uwsgi->hvec[i].iov_base); + //fprintf(stderr,"%.*s=%.*s\n", uwsgi->hvec[i].iov_len, uwsgi->hvec[i].iov_base, uwsgi->hvec[i+1].iov_len, uwsgi->hvec[i+1].iov_base); + i++; + } + + + // put "input" table + lua_newtable(ulua.L); + lua_pushcfunction(ulua.L, uwsgi_lua_input); + lua_setfield(ulua.L, -2, "read"); + lua_setfield(ulua.L, -2, "input"); + + + // call function + i = lua_pcall(ulua.L, 1, 3, 0); + if (i != 0) { + fprintf(stderr,"%s\n", lua_tostring(ulua.L, -1)); + lua_pop(ulua.L, 1); + return -1 ; + } + + fprintf(stderr,"%d %s %s %s\n",i,lua_typename(ulua.L, lua_type(ulua.L, -3)), lua_typename(ulua.L, lua_type(ulua.L, -2)) , lua_typename(ulua.L, lua_type(ulua.L, -1))); + + // send status + if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) { + http = lua_tolstring(ulua.L, -3, &slen); + write(uwsgi->poll.fd, "HTTP/1.1 ", 9); + write(uwsgi->poll.fd, http, slen); + write(uwsgi->poll.fd, "\r\n", 2); + } + + // send headers + + lua_pushnil(ulua.L); + while(lua_next(ulua.L, -3) != 0) { + http = lua_tolstring(ulua.L, -2, &slen); + write(uwsgi->poll.fd, http, slen); + write(uwsgi->poll.fd, ": ", 2); + http = lua_tolstring(ulua.L, -1, &slen); + write(uwsgi->poll.fd, http, slen); + write(uwsgi->poll.fd, "\r\n", 2); + lua_pop(ulua.L, 1); + } + + write(uwsgi->poll.fd, "\r\n", 2); + + // send body with coroutine + lua_pushvalue(ulua.L, -1); + + while ( (i = lua_pcall(ulua.L, 0, 1, 0)) == 0) { + if (lua_type(ulua.L, -1) == LUA_TSTRING) { + http = lua_tolstring(ulua.L, -1, &slen); + write(uwsgi->poll.fd, http, slen); + //fprintf(stderr,"%.*s\n", slen, http); + } + lua_pop(ulua.L, 1); + lua_pushvalue(ulua.L, -1); + } + + lua_pop(ulua.L, 4); + + return 0; + +} + +void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { + return; +} diff --git a/staticfile.py b/staticfile.py new file mode 100644 index 00000000..f8ab2f6f --- /dev/null +++ b/staticfile.py @@ -0,0 +1,4 @@ +def application(environ, start_response): + start_response('200 OK', [('Content-Type', 'image/png')]) + fd = open('logo_uWSGI.png','r') + return environ['wsgi.file_wrapper'](fd, 4096) diff --git a/testapp.py b/testapp.py index bfad7078..1d834065 100644 --- a/testapp.py +++ b/testapp.py @@ -10,7 +10,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' #import django.core.handlers.wsgi -uwsgi.load_plugin(0, "plugins/rack/rack_plugin.so") +uwsgi.load_plugin(0, "plugins/example/example_plugin.so", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa") from threading import Thread diff --git a/uwsgi.c b/uwsgi.c index 9ca444bc..1b4a9472 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -207,31 +207,6 @@ void internal_server_error (int fd, char *message) { wsgi_req.response_size += write (fd, message, strlen (message)); } -#ifndef ROCK_SOLID -PyObject *py_uwsgi_sendfile (PyObject * self, PyObject * args) { - - //PyObject *zero ; - - uwsgi.py_sendfile = PyTuple_GetItem (args, 0); - -#ifdef PYTHREE - if ((wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile)) >= 0) { - Py_INCREF (uwsgi.py_sendfile); - } -#else - if (PyFile_Check (uwsgi.py_sendfile)) { - //zero = PyFile_Name(uwsgi.py_sendfile) ; - //fprintf(stderr,"->serving %s as static file...", PyString_AsString(zero)); - wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile); - Py_INCREF (uwsgi.py_sendfile); - } -#endif - - - return PyTuple_New (0); -} -#endif - PyObject *py_uwsgi_write (PyObject * self, PyObject * args) { PyObject *data; char *content; @@ -450,6 +425,30 @@ PyObject *py_uwsgi_spit (PyObject * self, PyObject * args) { return Py_None; } +#ifndef ROCK_SOLID +PyObject *py_uwsgi_sendfile (PyObject * self, PyObject * args) { + + //PyObject *zero ; + + uwsgi.py_sendfile = PyTuple_GetItem (args, 0); + +#ifdef PYTHREE + if ((wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile)) >= 0) { + Py_INCREF (uwsgi.py_sendfile); + } +#else + if (PyFile_Check (uwsgi.py_sendfile)) { + //zero = PyFile_Name(uwsgi.py_sendfile) ; + //fprintf(stderr,"->serving %s as static file...", PyString_AsString(zero)); + wsgi_req.sendfile_fd = PyObject_AsFileDescriptor (uwsgi.py_sendfile); + Py_INCREF (uwsgi.py_sendfile); + } +#endif + + + return PyTuple_New (0); +} +#endif PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} }; @@ -474,6 +473,15 @@ int single_app_mode = 0; char *spool_dir = NULL; +static int unconfigured_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { + fprintf(stderr, "-- unavailable modifier requested: %d --\n", wsgi_req->modifier); + return -1; +} + +static void unconfigured_after_hook(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { + return; +} + int main (int argc, char *argv[], char *envp[]) { struct timeval check_interval = {.tv_sec = 1,.tv_usec = 0 }; @@ -549,8 +557,8 @@ int main (int argc, char *argv[], char *envp[]) { signal (SIGTERM, SIG_IGN); for(i=0;i<0xFF;i++) { - uwsgi.hooks[i] = NULL; - uwsgi.after_hooks[i] = NULL; + uwsgi.hooks[i] = unconfigured_hook; + uwsgi.after_hooks[i] = unconfigured_after_hook; } memset (&uwsgi, 0, sizeof (struct uwsgi_server)); @@ -1802,30 +1810,36 @@ int main (int argc, char *argv[], char *envp[]) { } #endif - ret = -1 ; + // enter harakiri mode if (uwsgi.options[UWSGI_OPTION_HARAKIRI] > 0) { set_harakiri(uwsgi.options[UWSGI_OPTION_HARAKIRI]); } - if (uwsgi.hooks[wsgi_req.modifier] != NULL) { - ret = (*uwsgi.hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); - if (!ret) { - if (uwsgi.after_hooks[wsgi_req.modifier] != NULL) { - ret = (*uwsgi.after_hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); - } - } - } - else { - fprintf(stderr,"unknown uwsgi request type received: %d\n", wsgi_req.modifier); - } + + ret = (*uwsgi.hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); + // calculate execution time + gettimeofday(&wsgi_req.end_of_request, NULL) ; + uwsgi.workers[uwsgi.mywid].running_time += (double) (( (double)(wsgi_req.end_of_request.tv_sec*1000000+wsgi_req.end_of_request.tv_usec)-(double)(wsgi_req.start_of_request.tv_sec*1000000+wsgi_req.start_of_request.tv_usec))/ (double)1000.0) ; + +#ifndef ROCK_SOLID + // get memory usage + if (uwsgi.options[UWSGI_OPTION_MEMORY_DEBUG] == 1) + get_memusage(); +#endif + + // close the connection with the webserver + close(uwsgi.poll.fd); + uwsgi.workers[0].requests++; + uwsgi.workers[uwsgi.mywid].requests++; + + if (!ret) + (*uwsgi.after_hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); + // leave harakiri mode if (uwsgi.workers[uwsgi.mywid].harakiri > 0) { set_harakiri(0); } - close(uwsgi.poll.fd); - uwsgi.workers[0].requests++; - uwsgi.workers[uwsgi.mywid].requests++; // defunct process reaper if (uwsgi.options[UWSGI_OPTION_REAPER] == 1) { @@ -1839,7 +1853,6 @@ int main (int argc, char *argv[], char *envp[]) { } #endif - if (uwsgi.options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.options[UWSGI_OPTION_MAX_REQUESTS]) { goodbye_cruel_world (); } @@ -1855,13 +1868,6 @@ int main (int argc, char *argv[], char *envp[]) { } #endif -/* - } - else { - fprintf (stderr, "Unsupported uwsgi modifier requested: %d\n", wsgi_req.modifier); - } -*/ - } if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) { diff --git a/uwsgi.h b/uwsgi.h index 623e15e0..fdb588c0 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -188,6 +188,7 @@ struct __attribute__ ((packed)) wsgi_request { int app_id; #endif struct timeval start_of_request; + struct timeval end_of_request; char *uri; unsigned short uri_len; char *remote_addr; @@ -240,7 +241,7 @@ struct __attribute__ ((packed)) wsgi_request { #endif int (*hooks[0xFF])(struct uwsgi_server *, struct wsgi_request*, char*) ; - int (*after_hooks[0xFF])(struct uwsgi_server *, struct wsgi_request*, char*) ; + void (*after_hooks[0xFF])(struct uwsgi_server *, struct wsgi_request*, char*) ; // iovec struct iovec *hvec; @@ -428,7 +429,7 @@ struct __attribute__ ((packed)) wsgi_request { /* included HOOKS */ int uwsgi_request_wsgi(struct uwsgi_server*, struct wsgi_request*, char *); -int uwsgi_after_request_wsgi(struct uwsgi_server*, struct wsgi_request*, char *); +void uwsgi_after_request_wsgi(struct uwsgi_server*, struct wsgi_request*, char *); int uwsgi_request_admin(struct uwsgi_server*, struct wsgi_request*, char *); int uwsgi_request_spooler(struct uwsgi_server*, struct wsgi_request*, char *); diff --git a/uwsgi_pymodule.c b/uwsgi_pymodule.c index 328f41f2..2e535bb7 100644 --- a/uwsgi_pymodule.c +++ b/uwsgi_pymodule.c @@ -549,13 +549,14 @@ PyObject *py_uwsgi_set_option(PyObject *self, PyObject *args) { PyObject *py_uwsgi_load_plugin(PyObject *self, PyObject *args) { uint8_t modifier ; char *plugin_name = NULL ; + char *pargs = NULL ; void *plugin_handle; - void (*plugin_init)(struct uwsgi_server *); + void (*plugin_init)(struct uwsgi_server *, char *); int (*plugin_request)(struct uwsgi_server *, struct wsgi_request*, char*) ; - int (*plugin_after_request)(struct uwsgi_server *, struct wsgi_request*, char*) ; + void (*plugin_after_request)(struct uwsgi_server *, struct wsgi_request*, char*) ; - if (!PyArg_ParseTuple(args, "is:load_plugin", &modifier, &plugin_name)) { + if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) { return NULL ; } @@ -567,7 +568,7 @@ PyObject *py_uwsgi_load_plugin(PyObject *self, PyObject *args) { else { plugin_init = dlsym(plugin_handle, "uwsgi_init"); if (plugin_init) { - (*plugin_init)(&uwsgi); + (*plugin_init)(&uwsgi, pargs); } plugin_request = dlsym(plugin_handle, "uwsgi_request"); diff --git a/wsgi_handlers.c b/wsgi_handlers.c index 1ad72b22..4b33df8e 100644 --- a/wsgi_handlers.c +++ b/wsgi_handlers.c @@ -1,5 +1,7 @@ #include "uwsgi.h" +static int uwsgi_sendfile(struct uwsgi_server *, int , int ) ; + int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { char *ptrbuf; @@ -18,10 +20,7 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re PyObject *wsgi_result, *wsgi_chunks, *wchunk; - int rlen; - /* Standard WSGI request */ - if (!wsgi_req->size) { fprintf (stderr, "Invalid WSGI request. skip.\n"); return -1; @@ -231,29 +230,6 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re } - - /* max 1 minute before harakiri */ - if (uwsgi->options[UWSGI_OPTION_HARAKIRI] > 0) { -#ifdef UNBIT - if (wsgi_req->modifier != 0) { - switch (wsgi_req->modifier) { - case UWSGI_MODIFIER_HT_S: - set_harakiri (wsgi_req->modifier_arg); - case UWSGI_MODIFIER_HT_M: - set_harakiri (wsgi_req->modifier_arg * 60); - case UWSGI_MODIFIER_HT_H: - set_harakiri (wsgi_req->modifier_arg * 3600); - } - } - else { -#endif - set_harakiri (uwsgi->options[UWSGI_OPTION_HARAKIRI]); -#ifdef UNBIT - } -#endif - } - - for (i = 0; i < wsgi_req->var_cnt; i += 2) { /*fprintf(stderr,"%.*s: %.*s\n", uwsgi->hvec[i].iov_len, uwsgi->hvec[i].iov_base, uwsgi->hvec[i+1].iov_len, uwsgi->hvec[i+1].iov_base); */ pydictkey = PyString_FromStringAndSize (uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len); @@ -279,8 +255,6 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re } - - // set wsgi vars wsgi_socket = PyFile_FromFile (wsgi_file, "wsgi_input", "r", NULL); @@ -324,8 +298,6 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re #endif - - // call #ifndef ROCK_SOLID if (uwsgi->enable_profiler == 1) { @@ -358,39 +330,7 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re #ifndef ROCK_SOLID if (wsgi_req->sendfile_fd > -1) { - rlen = lseek (wsgi_req->sendfile_fd, 0, SEEK_END); - if (rlen > 0) { - lseek (wsgi_req->sendfile_fd, 0, SEEK_SET); -#ifndef __linux__ -#if defined(__FreeBSD__) || defined(__DragonFly__) - - wsgi_req->response_size = sendfile (wsgi_req->sendfile_fd, uwsgi->poll.fd, 0, 0, NULL, (off_t *) & rlen, 0); -#elif __OpenBSD__ || __sun__ - char *no_sendfile_buf[4096]; - int jlen = 0; - i = 0; - while (i < rlen) { - jlen = read (wsgi_req->sendfile_fd, no_sendfile_buf, 4096); - if (jlen <= 0) { - perror ("read()"); - break; - } - i += jlen; - jlen = write (uwsgi->poll.fd, no_sendfile_buf, jlen); - if (jlen <= 0) { - perror ("write()"); - break; - } - - } -#else - wsgi_req->response_size = sendfile (wsgi_req->sendfile_fd, uwsgi->poll.fd, 0, (off_t *) & rlen, NULL, 0); -#endif -#else - wsgi_req->response_size = sendfile (uwsgi->poll.fd, wsgi_req->sendfile_fd, NULL, rlen); -#endif - } - Py_DECREF (uwsgi->py_sendfile); + wsgi_req->response_size = uwsgi_sendfile(uwsgi, wsgi_req->sendfile_fd, uwsgi->poll.fd); } else { @@ -474,10 +414,70 @@ int uwsgi_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re } -int uwsgi_after_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { +void uwsgi_after_request_wsgi (struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) { if (uwsgi->options[UWSGI_OPTION_LOGGING]) log_request(wsgi_req) ; - - return 0; } + +#ifndef ROCK_SOLID +static int uwsgi_sendfile(struct uwsgi_server *uwsgi, int fd, int sockfd) { + + int rlen,i ; + +#ifdef __sun__ + struct stat stat_buf; + if (fstat(fd, &stat_buf)) { + perror("fstat()"); + return 0; + } + else { + rlen = stat_buf.st_size ; + } +#else + rlen = lseek(fd, 0, SEEK_END) ; +#endif + + if (rlen > 0) { + lseek(fd, 0, SEEK_SET) ; +#if !defined(__linux__) && !defined(__sun__) + #if defined(__FreeBSD__) || defined(__DragonFly__) + + if (sendfile(fd, sockfd, 0, 0, NULL, (off_t *) &rlen, 0)) { + perror("sendfile()"); + } + #elif __APPLE__ + if (sendfile(fd, sockfd, 0, (off_t *) &rlen, NULL, 0)) { + perror("sendfile()"); + } + #else + char *no_sendfile_buf[4096] ; + int jlen = 0 ; + rlen = 0 ; + i = 0 ; + while(i < rlen) { + jlen = read(fd, no_sendfile_buf, 4096); + if (jlen<=0) { + perror("read()"); + break; + } + i += jlen; + jlen = write(sockfd, no_sendfile_buf, jlen); + if (jlen<=0) { + perror("write()"); + break; + } + rlen += jlen; + } + #endif +#else + i = 0 ; + rlen = sendfile(sockfd, fd, (off_t *) &i, rlen) ; +#endif + + } + Py_DECREF(uwsgi->py_sendfile); + + return rlen; +} +#endif