Compare commits

..
73 Commits
Author SHA1 Message Date
roberto@sirius 174116c48b a bunch of fixes for release candidate 2010-04-14 07:25:58 +02:00
roberto@sirius 4be5830fc3 removed base.mk 2010-04-14 07:07:47 +02:00
roberto@sirius 5f55357e17 remove UNBIT makefiles 2010-04-14 07:06:12 +02:00
roberto@sirius 8d033159b8 uwsgiplugin.py for Lua and example 2010-04-13 08:47:33 +02:00
roberto@sirius 299fd9cf8a introduced open PSGI plugin for uWSGI 2010-04-13 08:39:49 +02:00
roberto@sirius 8caee1b15b remove packed attribute from wsgi_request 2010-04-12 13:58:35 +02:00
roberto@sirius c2d963aa0d Plack::Handler:Uwsgi fixes 2010-04-12 13:11:08 +02:00
roberto@sirius 94691b3cc3 Plack::Handler:Uwsgi 2010-04-12 13:07:25 +02:00
roberto@sirius 9073a2856b added uwsgi Rack handler 2010-04-11 20:41:23 +02:00
roberto@sirius 4c26f34239 spooler fixes, and a new example (rrdtool and cron-like spooling) 2010-04-10 09:07:53 +02:00
roberto@sirius ad0cc774e1 shebang on ugreenchat 2010-04-09 11:56:55 +02:00
roberto@sirius d238fc50d0 new uGreen functions, sample comet chat included 2010-04-09 11:13:01 +02:00
roberto@fedora-arm dcf16c994e python headers check 2010-04-08 06:06:54 -04:00
roberto@sirius 65cc44e611 multicast fixes 2010-04-06 14:21:36 +02:00
roberto@sirius 9887177d9a startup logic fixes 2010-04-06 13:58:28 +02:00
roberto@voldemort 6b11777bb3 udp logging fixes 2010-04-06 13:02:04 +02:00
roberto@sirius 604b412f4a remove junk from udp logging 2010-04-06 12:57:17 +02:00
roberto@sirius 1d9da31f18 udp logging support 2010-04-06 12:38:04 +02:00
roberto@sirius fadf640f41 shebang friendly getopt_long() 2010-04-06 10:37:56 +02:00
roberto@sirius 743432a53d Sun fixes 2010-04-02 08:56:02 +02:00
roberto@sirius c1956fc371 /dev/poll support 2010-04-01 10:31:04 +02:00
roberto@sirius 3d098358da SO_ACCEPTFILTER 2010-04-01 09:25:15 +02:00
roberto@sirius 757e908372 uGreen timeout implementation 2010-03-31 15:17:04 +02:00
roberto@sirius dd12caa6f3 interrupt compilation if XML+libxml2 is requested but libxml2 headers are unavailable 2010-03-31 11:34:10 +02:00
roberto@sirius 0bfa5c4f46 Wally's patch for not compiled-in options 2010-03-31 11:15:24 +02:00
roberto@sirius cb252e4f0a OSX re-fix 2010-03-31 10:01:07 +02:00
roberto@sirius bdab4dcf84 uGreen fd async waiting support 2010-03-31 09:57:16 +02:00
roberto@sirius 474860cd39 uGreen configurable stack size 2010-03-30 20:07:50 +02:00
roberto@fierobecco 82f722b1f9 OSX fixes for uGreen 2010-03-29 13:05:36 +02:00
roberto@sirius 919501e92c uGreen little refactoring and fixes 2010-03-29 10:30:03 +02:00
roberto@sirius b1f3e48b2b uGreen fix 2010-03-28 18:21:23 +02:00
roberto@sirius 314df1d809 ugreen support 2010-03-28 18:18:23 +02:00
roberto@sirius 0416914951 fixed async wsgi mode 2010-03-26 17:01:13 +01:00
roberto@sirius 159a5660b2 Added tag 0.9.5beta2 for changeset 63560de14789 2010-03-26 09:24:55 +01:00
roberto@sirius 6ea9ee4ee9 re-enabled environment 2010-03-26 09:24:46 +01:00
roberto@sirius c60a81db47 uWSGI 0.9.5beta2 2010-03-26 09:19:03 +01:00
roberto@sirius b71634c76b erlang support is dependent on python embedded module 2010-03-26 09:17:53 +01:00
roberto@sirius 9a23c42262 another setrlimit() fix 2010-03-26 09:01:37 +01:00
roberto@sirius 680df4cff6 setrlimit() fixes 2010-03-26 08:59:33 +01:00
roberto@sirius 27fa8df9e6 automatically rise RLIMIT_NOFILE if possibile 2010-03-26 08:45:40 +01:00
roberto@sirius 2151b17aa3 check on RLIMIT_NOFILE beforse allocating async cores 2010-03-26 08:34:37 +01:00
roberto@sirius b93d0cc2b0 kevent() on pre-forking fix 2010-03-25 17:55:08 +01:00
roberto@sirius 1729275f8c async fix for fd waiting on kevent() 2010-03-25 17:35:58 +01:00
roberto@sirius 9b2460f8df another fix errno in tests.iobound_async 2010-03-25 17:21:05 +01:00
roberto@sirius 5451ff490c fix errno in tests.iobound_async 2010-03-25 17:17:33 +01:00
roberto@sirius 5a828aefdc python 3k full support 2010-03-25 16:04:40 +01:00
roberto@unbit 6a4332ca4d use distutils.sysconfig instead of python-config 2010-03-25 11:07:12 +01:00
roberto@sirius 7f3750b174 no fd-leak in stackless and async mode 2010-03-25 08:05:17 +01:00
roberto@sirius 7b1672497e stackless python support 2010-03-24 15:32:36 +01:00
roberto@sirius 113223567a typo fixes 2010-03-23 10:47:48 +01:00
roberto@fierobecco ecf23f93d1 osx erlang help 2010-03-22 15:32:01 +01:00
roberto@freebsd 2504af4dd1 FreeBSD sendfile fixes 2010-03-22 15:12:17 +01:00
roberto@netbsd c340e972ad NetBSD sendfile fixes, memory report and typecasting 2010-03-22 15:45:03 +01:00
roberto@sirius e382de291f expat implementation 2010-03-22 11:14:58 +01:00
roberto@sirius 51d97fadd9 nagios refactoring 2010-03-22 09:06:32 +01:00
roberto@sirium 878b515e23 code refactoring 2010-03-22 08:22:21 +01:00
roberto@sirius 03bdaa50b6 linux sendfile fix 2010-03-21 21:05:33 +01:00
roberto@sirius 34dbfc597e proxy refactoring 2010-03-21 21:01:27 +01:00
roberto@fierobecco 05efe4b7b3 kqueue fixes, sendfile osx, fix on apache2 module 2010-03-21 19:50:20 +01:00
roberto@sirius a18bc5f148 sendfile async implementation, still broken on BSD 2010-03-21 14:38:26 +01:00
roberto@sirius 9852b2fa62 async sleep implementation, kqueue re-broken, profiler leaks memory 2010-03-21 08:53:36 +01:00
roberto@sirius 9cedbb6716 WSGI handler refactoring 2010-03-18 18:14:06 +01:00
roberto@sirius 96a6c5eff4 report async switches 2010-03-18 17:42:22 +01:00
roberto@sirius e5233f09cc fix for a stupid typo 2010-03-18 13:53:53 +01:00
roberto@sirius 2f7bf001e8 new async test for I/O 2010-03-18 13:39:41 +01:00
roberto@fierobecco 1caea3dbeb async support for BSD systems (kqueue based) 2010-03-18 13:35:11 +01:00
roberto@sirius 6805e5ee9f merge 2010-03-18 12:38:21 +01:00
roberto@sirius 82f33591ae revert snmp fix 2010-03-18 12:37:37 +01:00
roberto@sirius b3e3e2ca1d async.c (only epoll) 2010-03-18 12:34:23 +01:00
roberto@sirius 4ae0361f6d little snmp fix 2010-03-18 12:34:12 +01:00
roberto@sirius.local 5706dd0a31 remove non-included option from getopt 2010-03-18 09:09:28 +01:00
roberto@sirius d8cd5580b7 preliminary async support 2010-03-17 18:08:53 +01:00
roberto@sirius e16c9b46ed little tag fix 2010-03-12 11:23:26 +01:00
57 changed files with 4591 additions and 1605 deletions
+1
View File
@@ -1 +1,2 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
-11
View File
@@ -1,11 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.4-config --cflags`
PYTHON_LIBS=`python2.4-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi24
include base.mk
-11
View File
@@ -1,11 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python2.5-config --cflags`
PYTHON_LIBS=`python2.5-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi
include base.mk
-15
View File
@@ -1,15 +0,0 @@
CC=gcc
BASE=/opt/packages/python/26
export LD_LIBRARY_PATH=$(BASE)/lib
PYTHON_CFLAGS=`$(BASE)/bin/python2.6-config --cflags`
PYTHON_LIBS=`$(BASE)/bin/python2.6-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -L$(BASE)/lib -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi26
include base.mk
-11
View File
@@ -1,11 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python3.0-config --cflags`
PYTHON_LIBS=`python3.0-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi30
include base.mk
-11
View File
@@ -1,11 +0,0 @@
CC=gcc
PYTHON_CFLAGS=`python3.1-config --cflags`
PYTHON_LIBS=`python3.1-config --libs`
CFLAGS=$(PYTHON_CFLAGS) -DUNBIT -D_GNU_SOURCE
LD_FLAGS=$(PYTHON_LIBS) -DUNBIT -D_GNU_SOURCE
PROGRAM=/usr/share/unbit/uwsgi31
include base.mk
+2 -2
View File
@@ -512,7 +512,7 @@ static int uwsgi_handler(request_rec *r) {
return ap_pass_brigade(r->output_filters, bb) ;
}
static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const char *location) {
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *location) {
uwsgi_cfg *c = cfg;
if (strlen(location) <= 255 && location[0] == '/') {
@@ -526,7 +526,7 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
}
static const char * cmd_uwsgi_force_script_name(cmd_parms *cmd, void *cfg, const char *scheme) {
static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const char *scheme) {
uwsgi_cfg *c = cfg;
if (strlen(scheme) < 9 & strlen(scheme) > 0) {
+454
View File
@@ -0,0 +1,454 @@
#ifdef UWSGI_ASYNC
#include "uwsgi.h"
#ifdef __linux__
#include <sys/epoll.h>
int async_queue_init(int serverfd) {
int epfd ;
struct epoll_event ee;
epfd = epoll_create(256);
if (epfd < 0) {
perror("epoll_create()");
return -1 ;
}
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = EPOLLIN;
ee.data.fd = serverfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &ee)) {
perror("epoll_ctl()");
close(epfd);
return -1;
}
return epfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
}
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = epoll_wait(queuefd, (struct epoll_event *) events, nevents, timeout);
if (ret < 0) {
perror("epoll_wait()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_ADD, fd, &ee)) {
perror("epoll_ctl()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_MOD, fd, &ee)) {
perror("epoll_ctl()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.events = etype;
ee.data.fd = fd;
if (epoll_ctl(queuefd, EPOLL_CTL_DEL, fd, &ee)) {
perror("epoll_ctl()");
return -1;
}
return 0;
}
#elif defined(__sun__)
int async_queue_init(int serverfd) {
int dpfd ;
struct pollfd dpev;
dpfd = open("/dev/poll", O_RDWR);
if (dpfd < 0) {
perror("open()");
return -1 ;
}
dpev.fd = serverfd;
dpev.events = POLLIN ;
if (write(dpfd, &dpev, sizeof(struct pollfd)) < 0) {
perror("write()");
return -1;
}
return dpfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret ;
struct dvpoll dv ;
if (timeout <= 0) {
timeout = block;
}
else {
timeout = timeout*1000;
}
dv.dp_fds = (struct pollfd *) events;
dv.dp_nfds = nevents;
dv.dp_timeout = timeout;
//fprintf(stderr,"waiting with timeout %d nevents %d\n", timeout, nevents);
ret = ioctl(queuefd, DP_POLL, &dv);
if (ret < 0) {
perror("ioctl()");
}
return ret ;
}
int async_add(int queuefd, int fd, int etype) {
struct pollfd pl;
pl.fd = fd ;
pl.events = etype ;
if (write(queuefd, &pl, sizeof(struct pollfd))) {
perror("write()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
// using the same fd will overwrite existing rule
return async_add(queuefd, fd, etype);
}
int async_del(int queuefd, int fd, int etype) {
// to remove an fd from /dev/poll you have to simply close it
return 0;
}
#else
int async_queue_init(int serverfd) {
int kfd ;
struct kevent kev;
kfd = kqueue();
if (kfd < 0) {
perror("kqueue()");
return -1 ;
}
EV_SET(&kev, serverfd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kfd, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
return -1;
}
return kfd;
}
int async_wait(int queuefd, void *events, int nevents, int block, int timeout) {
int ret;
struct timespec ts ;
if (timeout <= 0) {
if (!block) {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
else {
ret = kevent(queuefd, NULL, 0, events, nevents, NULL);
}
}
else {
memset(&ts, 0, sizeof(struct timespec));
ts.tv_sec = timeout ;
ret = kevent(queuefd, NULL, 0, events, nevents, &ts);
}
if (ret < 0) {
perror("kevent()");
}
return ret;
}
int async_add(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
return -1;
}
return 0;
}
int async_mod(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, ASYNC_OUT, EV_DISABLE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
return -1;
}
EV_SET(&kev, fd, etype, EV_ADD, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
return -1;
}
return 0;
}
int async_del(int queuefd, int fd, int etype) {
struct kevent kev;
EV_SET(&kev, fd, etype, EV_DELETE, 0, 0, 0);
if (kevent(queuefd, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
return -1;
}
return 0;
}
#endif
struct wsgi_request *next_wsgi_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
uint8_t *ptr = (uint8_t *) wsgi_req ;
ptr += sizeof(struct wsgi_request)+(uwsgi->buffer_size-1) ;
return (struct wsgi_request *) ptr ;
}
int async_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void async_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_OK) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += (sizeof(struct wsgi_request)+(uwsgi->buffer_size-1)) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
return NULL ;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
}
void async_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
perror("write()");
}
else {
wsgi_req->response_size += rlen ;
}
}
}
}
void async_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req ;
int i ;
uwsgi->async_running = -1 ;
wsgi_req = uwsgi->wsgi_requests ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
if (async_add(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type)) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
}
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi->async_running = 0 ;
// st global wsgi_req for python functions
uwsgi->wsgi_req = wsgi_req ;
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
wsgi_req->async_switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL;
}
#endif
-46
View File
@@ -1,46 +0,0 @@
all: clean uwsgi
uwsgi: utils.o protocol.o socket.o pymodule.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o wsgihandlers.o basehandlers.o main.o
$(CC) -lpthread utils.o protocol.o socket.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o pymodule.o wsgihandlers.o basehandlers.o main.o -o $(PROGRAM) $(LD_FLAGS)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
protocol.o: protocol.c
$(CC) -c $(CFLAGS) protocol.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
spooler.o: spooler.c
$(CC) -c $(CFLAGS) spooler.c
logging.o: logging.c
$(CC) -c $(CFLAGS) logging.c
xmlconf.o: xmlconf.c
$(CC) -c $(CFLAGS) xmlconf.c
snmp.o: snmp.c
$(CC) -c $(CFLAGS) snmp.c
proxy.o: proxy.c
$(CC) -c $(CFLAGS) proxy.c
erlang.o: erlang.c
$(CC) -c $(CFLAGS) erlang.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
basehandlers.o: uwsgi_handlers.c
$(CC) -c $(CFLAGS) -o basehandlers.o uwsgi_handlers.c
wsgihandlers.o: wsgi_handlers.c
$(CC) -c $(CFLAGS) -o wsgihandlers.o wsgi_handlers.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o protocol.o socket.o pymodule.o spooler.o logging.o xmlconf.o snmp.o proxy.o erlang.o wsgihandlers.o basehandlers.o main.o
+137
View File
@@ -0,0 +1,137 @@
package Plack::Handler::Uwsgi;
use strict;
use warnings;
use IO::Socket::INET;
use HTTP::Status;
use Plack::Util;
sub new {
my $class = shift;
my $self = bless {@_}, $class;
$self;
}
sub run {
my ($self, $app) = @_;
my $server = IO::Socket::INET->new(LocalPort => $self->{port}, LocalAddr => $self->{host}, Listen => 100, ReuseAddr => 1);
while ( my $client = $server->accept ) {
my $head = '';
my $remains = 4 ;
while($remains) {
$client->recv(my $buf, $remains);
last unless $buf;
$head.=$buf;
$remains -= length($buf);
}
if (length($head) != 4) {
$client->close ;
next;
}
my ($mod1, $envsize, $mod2) = unpack('CvC', $head) ;
unless ($envsize) {
$client->close ;
next;
}
$remains = $envsize ;
my $envbuf = '' ;
while($remains) {
my $buf ;
if ($remains >= 4096) {
$client->recv($buf, 4096);
}
else {
$client->recv($buf, $remains);
}
unless($buf) {
$client->close ;
next;
}
$envbuf.=$buf;
$remains -= length($buf);
}
if (length($envbuf) != $envsize ) {
$client->close ;
next;
}
my %env ;
my $i = 0;
while($i < $envsize) {
my $kl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
my $key = substr($envbuf, $i, $kl); $i+=$kl;
my $vl = unpack('v', substr($envbuf, $i, 2)) ; $i+=2;
$env{$key} = substr($envbuf, $i, $vl); $i+=$vl;
}
my $env = {
%env,
'psgi.version' => [1,1],
'psgi.url_scheme' => ($env{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
'psgi.input' => $client,
'psgi.errors' => *STDERR,
'psgi.multithread' => Plack::Util::FALSE,
'psgi.multiprocess' => Plack::Util::TRUE,
'psgi.run_once' => Plack::Util::FALSE,
'psgi.streaming' => Plack::Util::TRUE,
'psgi.nonblocking' => Plack::Util::FALSE,
};
my $res = Plack::Util::run_app $app, $env;
if (ref $res eq 'ARRAY') {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $res);
}
elsif (ref $res eq 'CODE') {
$res->(sub {
$self->_handle_response($client, $env{'SERVER_PROTOCOL'}, $_[0]);
});
}
else {
die "Bad response $res";
}
$client->close ;
}
}
sub _handle_response {
my ($self, $client, $protocol, $res) = @_;
$client->send($protocol.' '.$res->[0].' '.HTTP::Status::status_message( $res->[0] )."\r\n");
my $headers = $res->[1];
my $hdrs = '';
while (my ($k, $v) = splice @$headers, 0, 2) {
$hdrs .= "$k: $v\r\n";
}
$hdrs .= "\r\n";
$client->send($hdrs);
my $cb = sub { $client->send($_[0]) };
my $body = $res->[2];
if (defined $body) {
Plack::Util::foreach($body, $cb);
}
else {
return Plack::Util::inline_object write => $cb,close => sub { };
}
}
1;
+145
View File
@@ -0,0 +1,145 @@
require 'socket'
require 'rack/content_length'
require 'rack/rewindable_input'
module Rack
module Handler
class Uwsgi
def self.run(app, options={})
server = TCPServer.new(options[:Host], options[:Port])
while client = server.accept
serve client, app
end
end
def self.serve(client, app)
head, sender = client.recvfrom(4)
unless head
client.close
return
end
mod1, size, mod2 = head.unpack('CvC')
if size == 0 or size.nil?
client.close
return
end
vars, sender = client.recvfrom(size)
if vars.length != size
client.close
return
end
env = Hash.new
i = 0
while i < size
kl = vars[i, 2].unpack('v')[0]
i = i + 2
key = vars[i, kl]
i = i + kl
vl = vars[i, 2].unpack('v')[0]
i = i + 2
value = vars[i, vl]
i = i + vl
env[key] = value
end
env.delete "HTTP_CONTENT_LENGTH"
env.delete "HTTP_CONTENT_TYPE"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
if env["CONTENT_LENGTH"].to_i > 4096
rack_input = Rack::RewindableInput::Tempfile.new('Rack_uwsgi_Input')
rack_input.chmod(0000)
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
rack_input.binmode
if RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
rack_input.unlink
end
remains = env["CONTENT_LENGTH"].to_i
while remains > 0
if remains >= 4096
buf, sender = client.recvfrom(4096)
else
buf, sender = client.recvfrom(remains)
end
rack_input.write( buf )
remains -= buf.length
end
elsif env["CONTENT_LENGTH"].to_i > 0
rack_input = StringIO.new(client.recvfrom(env["CONTENT_LENGTH"].to_i)[0])
else
rack_input = StringIO.new('')
end
rack_input.rewind
env.update({"rack.version" => [1,1],
"rack.input" => rack_input,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
app = Rack::ContentLength.new(app)
begin
status, headers, body = app.call(env)
begin
send_headers client, env["HTTP_VERSION"] ,status, headers
send_body client, body
ensure
body.close if body.respond_to? :close
end
rescue Errno::EPIPE, Errno::ECONNRESET
ensure
rack_input.close
client.close
end
end
def self.send_headers(client, protocol, status, headers)
client.print "#{protocol} #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}\r\n"
headers.each { |k, vs|
vs.split("\n").each { |v|
client.print "#{k}: #{v}\r\n"
}
}
client.print "\r\n"
client.flush
end
def self.send_body(client, body)
body.each { |part|
client.print part
client.flush
}
end
end
end
end
+6 -6
View File
@@ -594,7 +594,7 @@ PyObject *eterm_to_py(ETERM * obj) {
return eobj;
}
void erlang_loop() {
void erlang_loop(struct wsgi_request *wsgi_req) {
ErlConnect econn;
ErlMessage em;
@@ -617,13 +617,13 @@ void erlang_loop() {
UWSGI_CLEAR_STATUS;
uwsgi.poll.fd = erl_accept(uwsgi.erlangfd, &econn);
wsgi_req->poll.fd = erl_accept(uwsgi.erlangfd, &econn);
if (uwsgi.poll.fd >= 0) {
if (wsgi_req->poll.fd >= 0) {
UWSGI_SET_ERLANGING;
for (;;) {
if (erl_receive_msg(uwsgi.poll.fd, (unsigned char *) uwsgi.buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (erl_receive_msg(wsgi_req->poll.fd, (unsigned char *) &wsgi_req->buffer, uwsgi.buffer_size, &em) == ERL_MSG) {
if (em.type == ERL_TICK)
continue;
@@ -660,7 +660,7 @@ void erlang_loop() {
if (erlang_result) {
eresponse = py_to_eterm(erlang_result);
if (eresponse) {
erl_send(uwsgi.poll.fd, em.from, eresponse);
erl_send(wsgi_req->poll.fd, em.from, eresponse);
erl_free_compound(eresponse);
}
Py_DECREF(erlang_result);
@@ -679,7 +679,7 @@ void erlang_loop() {
break;
}
}
erl_close_connection(uwsgi.poll.fd);
erl_close_connection(wsgi_req->poll.fd);
UWSGI_UNSET_ERLANGING;
}
+38
View File
@@ -0,0 +1,38 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# this is a cron emulator done with the Spooler :)
def rrdtool_updater(env):
uwsgi.set_spooler_frequency(s_freq)
rrdtool.update('../test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.send_to_spooler({})
uwsgi.spooler = rrdtool_updater
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
yield 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
fd = open('uwsgi_graph.png', 'r')
# send file to browser
return env['wsgi.file_wrapper'](fd, 4096)
# start the simil-cron
uwsgi.send_to_spooler({})
uwsgi.applications = {'/': hello_world, '/graph':graph}
+35 -7
View File
@@ -12,16 +12,16 @@ void log_request(struct wsgi_request *wsgi_req) {
char *time_request;
time_t microseconds, microseconds2;
static char *empty = "";
char *first_part = empty;
int app_req = -1;
char *msg2 = " ";
char *via = msg2;
#ifdef UWSGI_SENDFILE
char *msg1 = " via sendfile() ";
char *msg2 = " ";
char *via;
static char *empty = "";
char *first_part = empty;
struct uwsgi_app *wi;
int app_req = -1;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req->app_id];
@@ -55,7 +55,27 @@ void log_request(struct wsgi_request *wsgi_req) {
#endif
}
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %d bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes\n", first_part, uwsgi.mypid, wsgi_req->app_id, app_req, uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->size, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->response_size, (long int) (microseconds - microseconds2) / 1000, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, wsgi_req->headers_size);
fprintf(stderr, "%s[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
first_part,
uwsgi.mypid,
wsgi_req->app_id,
app_req,
uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(uint64_t) wsgi_req->response_size,
(long int) (microseconds - microseconds2) / 1000,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
wsgi_req->headers_size,
wsgi_req->async_switches, wsgi_req->async_id);
}
@@ -87,17 +107,25 @@ void get_memusage() {
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__OpenBSD__)
kvm_t *kv;
int cnt;
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct kinfo_proc *kproc;
int cnt;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
}
#elif defined(__NetBSD__)
struct kinfo_proc2 *kproc2;
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
if (kproc2 && cnt > 0) {
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
}
#endif
kvm_close(kv);
+51
View File
@@ -0,0 +1,51 @@
#include "uwsgi.h"
void nagios(struct uwsgi_server *uwsgi) {
struct pollfd nagios_poll;
// connect and send
if (uwsgi->socket_name == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
char *tcp_port = strchr(uwsgi->socket_name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
nagios_poll.fd = connect_to_tcp(uwsgi->socket_name, atoi(tcp_port + 1), uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (nagios_poll.fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
uwsgi->wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
uwsgi->wsgi_req->uh.pktsize = 0;
uwsgi->wsgi_req->uh.modifier2 = 0;
if (write(nagios_poll.fd, uwsgi->wsgi_req, 4) != 4) {
perror("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_poll.events = POLLIN;
if (!uwsgi_parse_response(&nagios_poll, uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) uwsgi->wsgi_req, &uwsgi->wsgi_req->buffer)) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else {
if (uwsgi->wsgi_req->uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uwsgi->wsgi_req->uh.pktsize, &uwsgi->wsgi_req->buffer);
exit(1);
}
else {
fprintf(stdout, "UWSGI OK: armed and ready\n");
exit(0);
}
}
// never here
fprintf(stdout, "UWSGI UNKNOWN: probably you hit a bug of uWSGI !!!\n");
exit(3);
}
+3 -5
View File
@@ -1,17 +1,15 @@
#include "../../uwsgi.h"
/* gcc `python-config --cflags` `python ../../uwsgiconfig.py --cflags` -o example_plugin.so -fPIC -shared example_plugin.c */
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
return 0;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>" ;
wsgi_req->response_size += write(uwsgi->poll.fd, http, strlen(http));
fprintf(stderr,"UWSGI POLL: %p\n", &uwsgi->poll);
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n<h1>Hello World</h1>" ;
wsgi_req->response_size += write(wsgi_req->poll.fd, http, strlen(http));
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
NAME='example'
CFLAGS = ''
LDFLAGS = ''
+21 -76
View File
@@ -87,77 +87,21 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *ptrbuf;
char *buffer = uwsgi->buffer ;
char *bufferend;
uint16_t strsize = 0;
int i;
const char *http ;
size_t slen ;
char *ptrbuf;
/* Standard WSAPI request */
if (!wsgi_req->size) {
if (!wsgi_req->uh.pktsize) {
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;
}
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid WSAPI request. skip.\n");
return -1;
}
// put function in the stack
lua_pushvalue(ulua.L, -1);
@@ -168,12 +112,11 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
lua_pushstring(ulua.L, "");
lua_setfield(ulua.L, -2, "CONTENT_TYPE");
for(i=0;i<wsgi_req->var_cnt;i++) {
lua_pushlstring(ulua.L, (char *)uwsgi->hvec[i+1].iov_base, uwsgi->hvec[i+1].iov_len);
lua_pushlstring(ulua.L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->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 = wsgi_req->hvec[i].iov_base+wsgi_req->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);
lua_setfield(ulua.L, -2, (char *)wsgi_req->hvec[i].iov_base);
i++;
}
@@ -198,15 +141,15 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
// send status
if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) {
http = lua_tolstring(ulua.L, -3, &slen);
if (write(uwsgi->poll.fd, "HTTP/1.1 ", 9) != 9) {
if (write(wsgi_req->poll.fd, "HTTP/1.1 ", 9) != 9) {
perror("write()");
return -1 ;
}
if (write(uwsgi->poll.fd, http, slen) != slen) {
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
@@ -217,27 +160,27 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
lua_pushnil(ulua.L);
while(lua_next(ulua.L, -3) != 0) {
http = lua_tolstring(ulua.L, -2, &slen);
if (write(uwsgi->poll.fd, http, slen) != slen) {
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(uwsgi->poll.fd, ": ", 2) != 2) {
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
perror("write()");
return -1 ;
}
http = lua_tolstring(ulua.L, -1, &slen);
if (write(uwsgi->poll.fd, http, slen) != slen) {
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
lua_pop(ulua.L, 1);
}
if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
perror("write()");
return -1 ;
}
@@ -248,7 +191,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
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);
if (write(uwsgi->poll.fd, http, slen) != slen) {
if (write(wsgi_req->poll.fd, http, slen) != slen) {
perror("write()");
return -1 ;
}
@@ -265,5 +208,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
return;
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+5
View File
@@ -0,0 +1,5 @@
import os,sys
NAME='lua'
CFLAGS = '-I /usr/include/lua5.1'
LDFLAGS = '-llua5.1'
+375
View File
@@ -0,0 +1,375 @@
#include <uwsgi.h>
#include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
static SV *psgi_func ;
/* statistically ordered */
static struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{ "", NULL },
};
/* automatically generated */
EXTERN_C void xs_init (pTHX);
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void
xs_init(pTHX)
{
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}
/* end of automagically generated part */
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
char *pargs[2] ;
char *psgibuffer ;
int fd ;
struct stat stat_psgi;
struct http_status_codes *http_sc ;
char *embedding[] = { "", "-e", "0" };
fprintf(stderr,"initializing Perl environment: %s\n", args);
my_perl = perl_alloc();
if (!my_perl) {
fprintf(stderr,"unable to allocate perl interpreter\n");
return -1;
}
pargs[0] = "" ;
pargs[1] = args ;
perl_construct(my_perl);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
perl_parse(my_perl, xs_init, 3, embedding, NULL);
perl_eval_pv("use IO::Handle;", 0);
fd = open(args, O_RDONLY);
if (fd < 0) {
perror("open()");
goto clear ;
}
if (fstat(fd, &stat_psgi)) {
perror("fstat()");
close(fd);
goto clear;
}
psgibuffer = malloc(stat_psgi.st_size);
if (!psgibuffer) {
perror("malloc()");
close(fd);
goto clear;
}
if (read(fd, psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
perror("read()");
close(fd);
free(psgibuffer);
goto clear;
}
psgibuffer[stat_psgi.st_size] = 0 ;
psgi_func = perl_eval_pv(psgibuffer, 0);
if (!psgi_func) {
fprintf(stderr,"unable to find PSGI function entry point.\n");
close(fd);
free(psgibuffer);
goto clear;
}
free(psgibuffer);
close(fd);
return 0;
clear:
perl_destruct(my_perl);
perl_free(my_perl);
return -1;
}
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
HV *env ;
SV **item ;
AV *response, *headers, *body ;
SV **status_code, **hitem, *io_new, *io_err, *io, *chunk;
char *chitem ;
STRLEN hlen ;
struct http_status_codes *http_sc;
int i,vi, base ;
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
fprintf (stderr, "Invalid PSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid PSGI request. skip.\n");
return -1;
}
dSP;
ENTER;
SAVETMPS;
env = (HV*)sv_2mortal((SV*)newHV());
// fill perl hash
for(i=0;i<wsgi_req->var_cnt;i++) {
if (wsgi_req->hvec[i+1].iov_len > 0) {
item = hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
newSVpv(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len), 0);
}
else {
item = hv_store(env, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, newSVpv("", 0), 0);
}
i++;
}
item = hv_store(env, "psgi.url_scheme", 15, newSVpv("http", 4), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal( newSVpv( "IO::Handle", 10 )));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_new = newSVsv(POPs);
PUSHMARK(SP);
XPUSHs( sv_2mortal(io_new) );
XPUSHs( sv_2mortal( newSViv( wsgi_req->poll.fd)));
XPUSHs( sv_2mortal( newSVpv( "r", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
item = hv_store(env, "psgi.input", 10, newSVsv(POPs), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal( newSVpv( "IO::Handle", 10 )));
PUTBACK;
perl_call_method( "new", G_SCALAR);
SPAGAIN;
io_err = newSVsv(POPs);
PUSHMARK(SP);
XPUSHs( sv_2mortal(io_err) );
XPUSHs( sv_2mortal( newSViv( 2 )));
XPUSHs( sv_2mortal( newSVpv( "w", 1)));
PUTBACK;
perl_call_method( "fdopen", G_SCALAR);
SPAGAIN;
item = hv_store(env, "psgi.errors", 11, newSVsv(POPs), 0);
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV *)env )) );
PUTBACK;
perl_call_sv(psgi_func, G_SCALAR);
SPAGAIN;
// dereference output
response = (AV *) SvRV( sv_2mortal(newSVsv(POPs)) ) ;
status_code = av_fetch(response, 0, 0);
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
wsgi_req->hvec[0].iov_len = 9 ;
wsgi_req->hvec[1].iov_base = SvPV(*status_code, hlen);
wsgi_req->hvec[1].iov_len = 3 ;
wsgi_req->hvec[2].iov_base = " ";
wsgi_req->hvec[2].iov_len = 1 ;
wsgi_req->hvec[3].iov_len = 0 ;
// get the status code
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, wsgi_req->hvec[1].iov_base, 3)) {
wsgi_req->hvec[3].iov_base = http_sc->message ;
wsgi_req->hvec[3].iov_len = http_sc->message_size ;
break;
}
}
if (wsgi_req->hvec[3].iov_len == 0) {
wsgi_req->hvec[3].iov_base = "Unknown" ;
wsgi_req->hvec[3].iov_len = 7;
}
wsgi_req->hvec[4].iov_base = "\r\n";
wsgi_req->hvec[4].iov_len = 2 ;
hitem = av_fetch(response, 1, 0) ;
headers = (AV *) SvRV(*hitem);
base = 5 ;
// put them in hvec
for(i=0; i<=av_len(headers); i++) {
vi = (i*2)+base ;
hitem = av_fetch(headers,i,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->hvec[vi].iov_base = chitem ; wsgi_req->hvec[vi].iov_len = hlen ;
wsgi_req->hvec[vi+1].iov_base = ": " ; wsgi_req->hvec[vi+1].iov_len = 2 ;
hitem = av_fetch(headers,i+1,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->hvec[vi+2].iov_base = chitem ; wsgi_req->hvec[vi+2].iov_len = hlen ;
wsgi_req->hvec[vi+3].iov_base = "\r\n" ; wsgi_req->hvec[vi+3].iov_len = 2 ;
i++;
}
vi = (i*2)+base ;
wsgi_req->hvec[vi].iov_base = "\r\n" ; wsgi_req->hvec[vi].iov_len = 2 ;
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, vi+1)) < 0) {
perror("writev()");
}
hitem = av_fetch(response, 2, 0) ;
io = *hitem;
if (SvTYPE(SvRV(io)) == SVt_PVGV) {
for(;;) {
PUSHMARK(SP);
XPUSHs(io) ;
PUTBACK;
perl_call_method("getline", G_SCALAR);
SPAGAIN;
chunk = sv_2mortal(newSVsv(POPs));
chitem = SvPV(chunk, hlen);
if (hlen <= 0) {
break;
}
wsgi_req->response_size += write(wsgi_req->poll.fd, chitem, hlen);
}
}
else if (SvTYPE(SvRV(io)) == SVt_PVAV) {
body = (AV *) SvRV(io);
for(i=0; i<=av_len(body); i++) {
hitem = av_fetch(body,i,0);
chitem = SvPV(*hitem, hlen);
wsgi_req->response_size += write(wsgi_req->poll.fd, chitem, hlen);
}
}
FREETMPS;
LEAVE;
return 0;
}
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
+5
View File
@@ -0,0 +1,5 @@
import os,sys
NAME='psgi'
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip()
LDFLAGS = os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip()
+69 -15
View File
@@ -292,14 +292,14 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *buffer = uwsgi->buffer;
char *buffer = &wsgi_req->buffer;
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->size;
bufferend = ptrbuf + wsgi_req->uh.pktsize;
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
@@ -310,17 +310,17 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
/* key cannot be null */
if (!strsize) {
fprintf(stderr, "uwsgi key cannot be null. skip this request.\n");
return -1;
}
if (!strsize) {
fprintf(stderr, "uwsgi key cannot be null. skip this request.\n");
return -1;
}
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;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
@@ -329,6 +329,59 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
if (!strncmp("SCRIPT_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->script_name = ptrbuf;
wsgi_req->script_name_len = strsize;
}
else if (!strncmp("SERVER_PROTOCOL", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
wsgi_req->protocol_len = strsize;
}
else if (!strncmp("REQUEST_URI", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->uri = ptrbuf;
wsgi_req->uri_len = strsize;
}
else if (!strncmp("QUERY_STRING", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->query_string = ptrbuf;
wsgi_req->query_string_len = strsize;
}
else if (!strncmp("REQUEST_METHOD", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!strncmp("REMOTE_ADDR", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!strncmp("REMOTE_USER", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_user = ptrbuf;
wsgi_req->remote_user_len = strsize;
}
else if (!strncmp("UWSGI_SCHEME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->scheme = ptrbuf;
wsgi_req->scheme_len = strsize;
}
else if (!strncmp("UWSGI_SCRIPT",wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->wsgi_script = ptrbuf;
wsgi_req->wsgi_script_len = strsize;
}
else if (!strncmp("UWSGI_MODULE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_module = ptrbuf;
wsgi_req->wsgi_module_len = strsize;
}
else if (!strncmp("UWSGI_CALLABLE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->wsgi_callable = ptrbuf;
wsgi_req->wsgi_callable_len = strsize;
}
else if (!strncmp("HTTPS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
#ifdef UNBIT
else if (!strncmp("UNBIT_FLAGS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
}
#endif
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
@@ -337,8 +390,8 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
return -1;
}
// var value
uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
@@ -362,6 +415,7 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
}
}
return 0;
}
@@ -391,16 +445,16 @@ int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
return -1;
}
wsgi_req->modifier = UWSGI_MODIFIER_PING;
wsgi_req->size = 0;
wsgi_req->modifier_arg = 0;
wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
if (write(uwsgi_poll.fd, wsgi_req, 4) != 4) {
perror("write()");
return -1;
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, uwsgi.buffer)) {
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, &wsgi_req->buffer)) {
return -1;
}
+92 -176
View File
@@ -14,41 +14,6 @@
#include "uwsgi.h"
#ifdef __linux__
#include <sys/epoll.h>
#define UWSGI_PROXY_USE_EPOLL 1
#define EV_FD eevents[i].data.fd
#define EV_EV eevents[i].events
#define EV_IN EPOLLIN
#define EV_OUT EPOLLOUT
#define NEV_FD ee.data.fd
#define NEV_EV ee.events
#define NEV_ADD epoll_ctl(epfd, EPOLL_CTL_ADD, NEV_FD, &ee)
#define NEV_MOD epoll_ctl(epfd, EPOLL_CTL_MOD, NEV_FD, &ee)
#define EV_NAME "epoll_ctl()"
#define EV_IS_IN EV_EV & EV_IN
#define EV_IS_OUT EV_EV & EV_OUT
#elif defined(__sun__)
#else
#include <sys/event.h>
#define UWSGI_PROXY_USE_KQUEUE 1
#define EV_FD krevents[i].ident
#define EV_EV krevents[i].filter
#define EV_IN EVFILT_READ
#define EV_OUT EVFILT_WRITE
#define NEV_FD kev.ident
#define NEV_EV kev.filter
#define NEV_ADD kevent(kq, &kev, 1, NULL, 0, NULL) < 0
#define NEV_MOD kevent(kq, &kev, 1, NULL, 0, NULL) < 0
#define EV_NAME "kevent()"
#define EV_IS_IN EV_EV == EV_IN
#define EV_IS_OUT EV_EV == EV_OUT
#endif
#include <sys/ioctl.h>
#define UWSGI_PROXY_CONNECTING 1
#define UWSGI_PROXY_WAITING 2
@@ -139,14 +104,17 @@ static int uwsgi_proxy_find_next_node(int current_node) {
void uwsgi_proxy(int proxyfd) {
int efd ;
#ifdef __linux__
int epfd;
struct epoll_event ee;
struct epoll_event *eevents;
struct epoll_event ev;
#elif defined(__sun__)
struct pollfd *eevents;
struct pollfd ev;
#else
int kq;
struct kevent *krevents;
struct kevent kev;
struct kevent *eevents;
struct kevent ev;
#endif
int max_events = 64;
@@ -183,53 +151,28 @@ void uwsgi_proxy(int proxyfd) {
}
memset(upcs, 0, sizeof(struct uwsgi_proxy_connection) * max_connections);
#ifdef __linux__
//init epoll
epfd = epoll_create(256);
if (epfd < 0) {
perror("epoll_create()");
efd = async_queue_init(proxyfd);
if (efd < 0) {
exit(1);
}
// allocate memory for events
#ifdef __linux__
eevents = malloc(sizeof(struct epoll_event) * max_events);
memset(&ev, 0, sizeof(struct epoll_event));
#elif defined(__sun)
eevents = malloc(sizeof(struct pollfd) * max_events);
memset(&ev, 0, sizeof(struct pollfd));
#else
eevents = malloc(sizeof(struct kevent) * max_events);
memset(&ev, 0, sizeof(struct kevent));
#endif
if (!eevents) {
perror("malloc()");
exit(1);
}
// now add the proxyfd to the epoll list
ee.events = EPOLLIN;
ee.data.fd = proxyfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, proxyfd, &ee)) {
perror("epoll_ctl()");
exit(1);
}
#else
kq = kqueue();
if (kq < 0) {
perror("kqueue()");
exit(1);
}
// allocate memory for events
krevents = malloc(sizeof(struct kevent) * max_events);
if (!krevents) {
perror("malloc()");
exit(1);
}
EV_SET(&kev, proxyfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
if (kevent(kq, &kev, 1, NULL, 0, NULL) < 0) {
perror("kevent()");
exit(1);
}
#endif
signal(SIGINT, (void *) &end_proxy);
signal(SIGTERM, (void *) &reload_proxy);
signal(SIGHUP, (void *) &reload_proxy);
@@ -237,107 +180,92 @@ void uwsgi_proxy(int proxyfd) {
for (;;) {
#ifdef __linux__
nevents = epoll_wait(epfd, eevents, max_events, -1);
nevents = async_wait(efd, eevents, max_events, -1, 0);
if (nevents < 0) {
perror("epoll_wait()");
continue;
}
#else
nevents = kevent(kq, NULL, 0, krevents, max_events, NULL);
if (nevents < 0) {
perror("kevent()");
continue;
}
#endif
for (i = 0; i < nevents; i++) {
if (EV_FD == proxyfd) {
if (eevents[i].ASYNC_FD == proxyfd) {
if (EV_IS_IN) {
if (eevents[i].ASYNC_IS_IN) {
// new connection, accept it
NEV_FD = accept(proxyfd, (struct sockaddr *) &upc_addr, &upc_len);
if (NEV_FD < 0) {
ev.ASYNC_FD = accept(proxyfd, (struct sockaddr *) &upc_addr, &upc_len);
if (ev.ASYNC_FD < 0) {
perror("accept()");
continue;
}
upcs[NEV_FD].node = -1;
upcs[ev.ASYNC_FD].node = -1;
// now connect to the first worker available
upcs[NEV_FD].dest_fd = socket(AF_INET, SOCK_STREAM, 0);
if (upcs[NEV_FD].dest_fd < 0) {
upcs[ev.ASYNC_FD].dest_fd = socket(AF_INET, SOCK_STREAM, 0);
if (upcs[ev.ASYNC_FD].dest_fd < 0) {
perror("socket()");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[NEV_FD].dest_fd].node = -1;
upcs[upcs[ev.ASYNC_FD].dest_fd].node = -1;
// set nonblocking
if (ioctl(upcs[NEV_FD].dest_fd, FIONBIO, &nonblocking)) {
if (ioctl(upcs[ev.ASYNC_FD].dest_fd, FIONBIO, &nonblocking)) {
perror("ioctl()");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[NEV_FD].status = 0;
upcs[NEV_FD].retry = 0;
upcs[ev.ASYNC_FD].status = 0;
upcs[ev.ASYNC_FD].retry = 0;
next_node = uwsgi_proxy_find_next_node(next_node);
if (next_node == -1) {
fprintf(stderr, "unable to find an available worker in the cluster !\n");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[NEV_FD].dest_fd].node = next_node;
rc = connect(upcs[NEV_FD].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
upcs[upcs[ev.ASYNC_FD].dest_fd].node = next_node;
rc = connect(upcs[ev.ASYNC_FD].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
uwsgi.shared->nodes[next_node].connections++;
if (!rc) {
// connected to worker, put it in the epoll_list
NEV_EV = EV_IN;
if (NEV_ADD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
upcs[upcs[NEV_FD].dest_fd].dest_fd = NEV_FD;
upcs[upcs[NEV_FD].dest_fd].status = 0;
upcs[upcs[NEV_FD].dest_fd].retry = 0;
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = 0;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
NEV_FD = upcs[NEV_FD].dest_fd;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
NEV_EV = EV_IN;
if (NEV_ADD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(upcs[upcs[NEV_FD].dest_fd].dest_fd, FIONBIO, &blocking)) {
if (ioctl(upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd, FIONBIO, &blocking)) {
perror("ioctl()");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else if (errno == EINPROGRESS) {
// the socket is waiting, set status to CONNECTING
upcs[NEV_FD].status = UWSGI_PROXY_WAITING;
upcs[upcs[NEV_FD].dest_fd].dest_fd = NEV_FD;
upcs[upcs[NEV_FD].dest_fd].status = UWSGI_PROXY_CONNECTING;
upcs[upcs[NEV_FD].dest_fd].retry = 0;
upcs[ev.ASYNC_FD].status = UWSGI_PROXY_WAITING;
upcs[upcs[ev.ASYNC_FD].dest_fd].dest_fd = ev.ASYNC_FD;
upcs[upcs[ev.ASYNC_FD].dest_fd].status = UWSGI_PROXY_CONNECTING;
upcs[upcs[ev.ASYNC_FD].dest_fd].retry = 0;
NEV_FD = upcs[NEV_FD].dest_fd;
NEV_EV = EV_OUT;
if (NEV_ADD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
if (async_add(efd, ev.ASYNC_FD, ASYNC_OUT)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
@@ -345,7 +273,7 @@ void uwsgi_proxy(int proxyfd) {
// connection failed, retry with the next node ?
perror("connect()");
// close only when all node are tried
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
@@ -358,110 +286,98 @@ void uwsgi_proxy(int proxyfd) {
}
else {
// this is for clients/workers
if (EV_IS_IN) {
if (eevents[i].ASYNC_IS_IN) {
// is this a connected client/worker ?
//fprintf(stderr,"ready %d\n", upcs[eevents[i].data.fd].status);
if (!upcs[EV_FD].status) {
if (upcs[EV_FD].dest_fd >= 0) {
if (!upcs[eevents[i].ASYNC_FD].status) {
if (upcs[eevents[i].ASYNC_FD].dest_fd >= 0) {
rlen = read(EV_FD, buffer, 4096);
rlen = read(eevents[i].ASYNC_FD, buffer, 4096);
if (rlen < 0) {
perror("read()");
uwsgi_proxy_close(upcs, EV_FD);
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else if (rlen == 0) {
uwsgi_proxy_close(upcs, EV_FD);
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
else {
wlen = write(upcs[EV_FD].dest_fd, buffer, rlen);
wlen = write(upcs[eevents[i].ASYNC_FD].dest_fd, buffer, rlen);
if (wlen != rlen) {
perror("write()");
uwsgi_proxy_close(upcs, EV_FD);
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
}
else {
uwsgi_proxy_close(upcs, EV_FD);
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
else if (upcs[EV_FD].status == UWSGI_PROXY_WAITING) {
else if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_WAITING) {
// disconnected node
continue;
}
else {
fprintf(stderr, "UNKNOWN STATUS %d\n", upcs[EV_FD].status);
fprintf(stderr, "UNKNOWN STATUS %d\n", upcs[eevents[i].ASYNC_FD].status);
continue;
}
}
else if (EV_IS_OUT) {
if (upcs[EV_FD].status == UWSGI_PROXY_CONNECTING) {
else if (eevents[i].ASYNC_IS_OUT) {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
#ifdef UWSGI_PROXY_USE_KQUEUE
if (getsockopt(EV_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
perror("getsockopt()");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
/* is something bad ? */
if (soopt) {
fprintf(stderr, "connect() %s\n", strerror(soopt));
// increase errors on node
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[EV_FD].node, uwsgi.shared->nodes[upcs[EV_FD].node].name);
uwsgi.shared->nodes[upcs[EV_FD].node].errors++;
uwsgi.shared->nodes[upcs[EV_FD].node].status = UWSGI_NODE_FAILED;
uwsgi_proxy_close(upcs, NEV_FD);
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// increase errors on node
#endif
NEV_FD = upcs[EV_FD].dest_fd;
NEV_EV = EV_IN;
upcs[NEV_FD].status = 0;
if (NEV_ADD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
ev.ASYNC_FD = upcs[eevents[i].ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
if (async_add(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
NEV_FD = upcs[NEV_FD].dest_fd;
upcs[NEV_FD].status = 0;
ev.ASYNC_FD = upcs[ev.ASYNC_FD].dest_fd;
upcs[ev.ASYNC_FD].status = 0;
#ifdef UWSGI_PROXY_USE_KQUEUE
EV_SET(&kev, NEV_FD, EVFILT_WRITE, EV_ADD | EV_DISABLE, 0, 0, NULL);
if (NEV_MOD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
continue;
}
EV_SET(&kev, NEV_FD, EVFILT_READ, EV_ADD, 0, 0, NULL);
#endif
if (NEV_MOD) {
perror(EV_NAME);
uwsgi_proxy_close(upcs, NEV_FD);
if (async_mod(efd, ev.ASYNC_FD, ASYNC_IN)) {
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
// re-set blocking
if (ioctl(NEV_FD, FIONBIO, &blocking)) {
if (ioctl(ev.ASYNC_FD, FIONBIO, &blocking)) {
perror("ioctl()");
uwsgi_proxy_close(upcs, NEV_FD);
uwsgi_proxy_close(upcs, ev.ASYNC_FD);
continue;
}
}
else {
fprintf(stderr, "strange event for %d\n", (int) EV_FD);
fprintf(stderr, "strange event for %d\n", (int) eevents[i].ASYNC_FD);
}
}
else {
if (upcs[EV_FD].status == UWSGI_PROXY_CONNECTING) {
if (getsockopt(EV_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
if (upcs[eevents[i].ASYNC_FD].status == UWSGI_PROXY_CONNECTING) {
if (getsockopt(eevents[i].ASYNC_FD, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
perror("getsockopt()");
}
/* is something bad ? */
@@ -470,14 +386,14 @@ void uwsgi_proxy(int proxyfd) {
}
// increase errors on node
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[EV_FD].node, uwsgi.shared->nodes[upcs[EV_FD].node].name);
uwsgi.shared->nodes[upcs[EV_FD].node].errors++;
uwsgi.shared->nodes[upcs[EV_FD].node].status = UWSGI_NODE_FAILED;
fprintf(stderr, "*** marking cluster node %d/%s as failed ***\n", upcs[eevents[i].ASYNC_FD].node, uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].name);
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].errors++;
uwsgi.shared->nodes[upcs[eevents[i].ASYNC_FD].node].status = UWSGI_NODE_FAILED;
}
else {
fprintf(stderr, "STRANGE EVENT !!! %d %d %d\n", (int) EV_FD, EV_EV, upcs[EV_FD].status);
fprintf(stderr, "STRANGE EVENT !!! %d %d %d\n", (int) eevents[i].ASYNC_FD, (int) eevents[i].ASYNC_EV, upcs[eevents[i].ASYNC_FD].status);
}
uwsgi_proxy_close(upcs, EV_FD);
uwsgi_proxy_close(upcs, eevents[i].ASYNC_FD);
continue;
}
}
+3
View File
@@ -0,0 +1,3 @@
import uwsgi
uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "test.psgi")
+146
View File
@@ -0,0 +1,146 @@
#include "uwsgi.h"
int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *pychunk ;
ssize_t wsize ;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0 ;
#endif
//fprintf(stderr,"managing request for %d %p\n", wsgi_req->async_id, wsgi_req);
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
perror("write()");
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#ifdef PYTHREE
if (PyBytes_Check((PyObject *)wsgi_req->async_result)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(wsgi_req->async_result), PyBytes_Size(wsgi_req->async_result))) < 0) {
perror("write()");
Py_DECREF(wsgi_req->async_result);
goto clear;
}
wsgi_req->response_size += wsize;
goto clear;
}
#endif
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
return UWSGI_AGAIN;
}
}
#endif
goto clear;
}
#endif
// ok its a yield
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (!wsgi_req->async_placeholder) {
goto clear2;
}
Py_DECREF((PyObject *)wsgi_req->async_result);
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
perror("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#ifdef PYTHREE
if (PyBytes_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(pychunk), PyBytes_Size(pychunk))) < 0) {
perror("write()");
Py_DECREF(pychunk);
goto clear;
}
wsgi_req->response_size += wsize;
}
#endif
Py_DECREF(pychunk);
return UWSGI_AGAIN ;
clear:
if (wsgi_req->sendfile_fd != -1) {
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
}
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1 ;
}
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
return UWSGI_OK;
}
PyObject *python_call(PyObject *callable, PyObject *args) {
PyObject *pyret;
pyret = PyEval_CallObject(callable, args);
if (PyErr_Occurred()) {
PyErr_Print();
}
return pyret;
}
int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
wsgi_req->async_result = python_call(callable, args);
if (wsgi_req->async_result) {
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
}
return UWSGI_OK;
}
+160
View File
@@ -0,0 +1,160 @@
#ifdef UWSGI_SENDFILE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
}
#endif
return PyTuple_New(0);
}
ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int fd = wsgi_req->sendfile_fd ;
int sockfd = wsgi_req->poll.fd ;
struct stat stat_buf;
int sf_ret;
if (!wsgi_req->sendfile_fd_size) {
if (fstat(fd, &stat_buf)) {
perror("fstat()");
return 0;
}
else {
wsgi_req->sendfile_fd_size = stat_buf.st_size;
}
}
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
#if defined(__FreeBSD__) || defined(__DragonFly__)
off_t sf_len = wsgi_req->sendfile_fd_size ;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, 0, NULL, &sf_len, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret) {
perror("sendfile()");
return 0;
}
return sf_len;
#elif __APPLE__
off_t sf_len = wsgi_req->sendfile_fd_size ;
if (uwsgi->async > 1) {
sf_len = wsgi_req->sendfile_fd_chunk;
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, &sf_len, NULL, 0);
wsgi_req->sendfile_fd_pos += sf_len ;
}
else {
sf_ret = sendfile(fd, sockfd, 0, &sf_len, NULL, 0);
}
if (sf_ret) {
perror("sendfile()");
return 0;
}
return sf_len;
#elif defined(__linux__) || defined(__sun__)
if (uwsgi->async > 1) {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_chunk);
}
else {
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size);
}
if (sf_ret < 0) {
perror("sendfile()");
return 0;
}
return sf_ret ;
#else
static nosf_buf_size = 0 ;
static char *nosf_buf ;
ssize_t jlen = 0;
ssize_t rlen = 0;
ssize_t i = 0;
if (!nosf_buf) {
nosf_buf = malloc(wsgi_req->sendfile_fd_chunk);
}
else if (wsgi_req->sendfile_fd_chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, wsgi_req->sendfile_fd_chunk);
}
nosf_buf_size = wsgi_req->sendfile_fd_chunk ;
if (uwsgi->async > 1) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
if (jlen <= 0) {
perror("read()");
return 0;
}
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
perror("write()");
return 0;
}
return jlen ;
}
while (i < wsgi_req->sendfile_fd_size) {
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
if (jlen <= 0) {
perror("read()");
break;
}
i += jlen;
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
perror("write()");
break;
}
rlen += jlen ;
}
return rlen;
#endif
}
return 0;
}
#endif
+3 -2
View File
@@ -1,3 +1,4 @@
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain; charset=UTF-32')])
return "hello world"
#print env
start_response('200 Ok', [('Content-type', 'text/plain')])
yield "hello world"
+6
View File
@@ -0,0 +1,6 @@
import uwsgi
def print_logs(ip, port, message):
print(ip, port, message)
uwsgi.udp_callable = print_logs
+1 -1
View File
@@ -315,7 +315,7 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
if (oid_sz < 0)
if (oid_sz < 1)
return -1;
oid_sz--;
+37 -15
View File
@@ -125,7 +125,9 @@ int bind_to_udp(char *socket_name) {
struct sockaddr_in uws_addr;
char *udp_port;
#ifdef UWSGI_MULTICAST
struct ip_mreq mc;
#endif
udp_port = strchr(socket_name, ':');
if (udp_port == NULL) {
@@ -136,8 +138,15 @@ int bind_to_udp(char *socket_name) {
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(atoi(udp_port + 1));
//uws_addr.sin_addr.s_addr = inet_addr(socket_name);
uws_addr.sin_addr.s_addr = INADDR_ANY;
if (socket_name[0] != 0) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
else {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
if (serverfd < 0) {
@@ -145,14 +154,19 @@ int bind_to_udp(char *socket_name) {
return -1;
}
// if multicast is enabled remember to bind to INADDR_ANY
mc.imr_multiaddr.s_addr = inet_addr("225.0.0.1");
if (socket_name[0] == 0) {
mc.imr_interface.s_addr = INADDR_ANY;
}
else {
mc.imr_interface.s_addr = inet_addr(socket_name);
#ifdef UWSGI_MULTICAST
if (uwsgi.multicast_group) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
// if multicast is enabled remember to bind to INADDR_ANY
mc.imr_multiaddr.s_addr = inet_addr(uwsgi.multicast_group);
if (socket_name[0] == 0) {
mc.imr_interface.s_addr = INADDR_ANY;
}
else {
mc.imr_interface.s_addr = inet_addr(socket_name);
}
}
#endif
fprintf(stderr, "binding on UDP port: %d\n", ntohs(uws_addr.sin_port));
@@ -162,10 +176,14 @@ int bind_to_udp(char *socket_name) {
return -1;
}
fprintf(stderr, "joining uWSGI multicast group: %s:%d\n", "225.0.0.1", ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
perror("setsockopt()");
#ifdef UWSGI_MULTICAST
if (uwsgi.multicast_group) {
fprintf(stderr, "joining uWSGI multicast group: %s:%d\n", uwsgi.multicast_group, ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
perror("setsockopt()");
}
}
#endif
return serverfd;
@@ -240,12 +258,16 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (!uwsgi.no_defer_accept) {
#ifdef TCP_DEFER_ACCEPT
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
perror("setsockopt()");
}
else {
fprintf(stderr, "TCP_DEFER_ACCEPT enabled.\n");
#elif defined(__apple__) || defined(__freebsd__)
struct accept_filter_arg afa;
strcpy(afa.af_name, "dataready");
afa.af_arg[0] = 0;
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
perror("setsockopt()");
}
#endif
+25 -30
View File
@@ -4,10 +4,8 @@
#include <dirent.h>
extern char *spool_dir;
int spool_request(char *filename, int rn, char *buffer, int size) {
int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buffer, int size) {
char hostname[256 + 1];
struct timeval tv;
@@ -23,7 +21,7 @@ int spool_request(char *filename, int rn, char *buffer, int size) {
hostname[256] = 0;
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
return 0;
}
@@ -74,10 +72,10 @@ int spool_request(char *filename, int rn, char *buffer, int size) {
return 0;
}
void spooler(PyObject * uwsgi_module) {
void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
DIR *sdir;
struct dirent *dp;
PyObject *uwsgi_module_dict, *spooler_callable, *spool_result, *spool_tuple, *spool_env;
PyObject *spooler_callable, *spool_result, *spool_tuple, *spool_env;
int spool_fd;
uint16_t uwstrlen;
int rlen = 0;
@@ -88,12 +86,8 @@ void spooler(PyObject * uwsgi_module) {
char *key;
char *val;
uwsgi_module_dict = PyModule_GetDict(uwsgi_module);
if (!uwsgi_module_dict) {
fprintf(stderr, "could not get uwsgi module __dict__\n");
exit(1);
}
// spool every 30 seconds by default
uwsgi->shared->spooler_frequency = 30 ;
spool_tuple = PyTuple_New(1);
@@ -113,8 +107,8 @@ void spooler(PyObject * uwsgi_module) {
PyErr_Print();
exit(1);
}
if (chdir(spool_dir)) {
if (chdir(uwsgi->spool_dir)) {
perror("chdir()");
exit(1);
}
@@ -124,7 +118,10 @@ void spooler(PyObject * uwsgi_module) {
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
for (;;) {
sdir = opendir(".");
sleep(uwsgi->shared->spooler_frequency);
sdir = opendir(uwsgi->spool_dir);
if (sdir) {
while ((dp = readdir(sdir)) != NULL) {
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
@@ -241,7 +238,7 @@ void spooler(PyObject * uwsgi_module) {
}
spool_result = PyEval_CallObject(spooler_callable, spool_tuple);
spool_result = python_call(spooler_callable, spool_tuple);
if (!spool_result) {
PyErr_Print();
fprintf(stderr, "error detected. spool request canceled.\n");
@@ -277,8 +274,6 @@ void spooler(PyObject * uwsgi_module) {
perror("opendir()");
}
/* TODO spooler frequency user-configurable */
sleep(5);
}
}
@@ -287,12 +282,12 @@ int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
int i;
char spool_filename[1024];
if (spool_dir == NULL) {
if (uwsgi->spool_dir == NULL) {
fprintf(stderr, "the spooler is inactive !!!...skip\n");
wsgi_req->modifier = 255;
wsgi_req->size = 0;
wsgi_req->modifier_arg = 0;
i = write(uwsgi->poll.fd, wsgi_req, 4);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
perror("write()");
}
@@ -300,12 +295,12 @@ int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
}
fprintf(stderr, "managing spool request...\n");
i = spool_request(spool_filename, uwsgi->workers[0].requests + 1, uwsgi->buffer, wsgi_req->size);
wsgi_req->modifier = 255;
wsgi_req->size = 0;
i = spool_request(uwsgi, spool_filename, uwsgi->workers[0].requests + 1, &wsgi_req->buffer, wsgi_req->uh.pktsize);
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
if (i > 0) {
wsgi_req->modifier_arg = 1;
if (write(uwsgi->poll.fd, wsgi_req, 4) != 4) {
wsgi_req->uh.modifier2 = 1;
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
fprintf(stderr, "disconnected client, remove spool file.\n");
/* client disconnect, remove spool file */
if (unlink(spool_filename)) {
@@ -318,8 +313,8 @@ int uwsgi_request_spooler(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
}
else {
/* announce a failed spool request */
wsgi_req->modifier_arg = 0;
i = write(uwsgi->poll.fd, wsgi_req, 4);
wsgi_req->uh.modifier2 = 0;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
perror("write()");
}
+143
View File
@@ -0,0 +1,143 @@
#ifdef UWSGI_STACKLESS
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request* find_request_by_tasklet(PyTaskletObject *tasklet) {
int i ;
for(i=0;i<uwsgi.async;i++) {
if (uwsgi.stackless_table[i]->tasklet == tasklet) {
return uwsgi.stackless_table[i]->wsgi_req;
}
}
return NULL;
}
PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
PyThreadState *ts = PyThreadState_GET();
struct wsgi_request *wsgi_req = find_request_by_tasklet(ts->st.current);
PyObject *zero;
int async_id = wsgi_req->async_id;
//fprintf(stderr,"i am the tasklet worker\n");
for(;;) {
// wait for request
zero = PyChannel_Receive(uwsgi.workers_channel);
wsgi_req_setup(wsgi_req, async_id);
if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
continue;
}
uwsgi_close_request(&uwsgi, wsgi_req);
}
}
PyMethodDef uwsgi_stackless_worker[] = { {"uwsgi_stackless_worker", py_uwsgi_stackless_worker, METH_VARARGS, ""} };
void stackless_init(struct uwsgi_server *uwsgi) {
int i;
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
PyObject *tasklet_worker = PyCFunction_New(uwsgi_stackless_worker, NULL);
uwsgi->workers_channel = PyChannel_New(NULL);
uwsgi->stackless_table = malloc( sizeof(struct stackless_req*) * uwsgi->async);
if (!uwsgi->stackless_table) {
perror("malloc()");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->stackless_table[i] = malloc(sizeof(struct stackless_req));
if (!uwsgi->stackless_table[i]) {
perror("malloc()");
exit(1);
}
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
fprintf(stderr,"initializing %d tasklet...", uwsgi->async);
// creating uwsgi->async tasklets
for(i=0;i<uwsgi->async;i++) {
wsgi_req->tasklet = PyTasklet_New(NULL, tasklet_worker);
uwsgi->stackless_table[i]->tasklet = wsgi_req->tasklet;
uwsgi->stackless_table[i]->wsgi_req = wsgi_req;
// useless for now, it will be used for I/O or other messaging
uwsgi->stackless_table[i]->channel = NULL;
wsgi_req->async_id = i ;
PyTasklet_Setup(wsgi_req->tasklet, PyTuple_New(0), NULL);
//PyTasklet_Run(wsgi_req->tasklet);
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
fprintf(stderr,"done\n");
}
void stackless_loop(struct uwsgi_server *uwsgi) {
int i;
PyTaskletObject *int_tasklet;
// tasklets main loop
for(;;) {
//uwsgi->async_running = -1 ;
//if (PyStackless_GetRunCount() > 0) {
uwsgi->async_running = 0 ;
//}
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, 0);
if (uwsgi->async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
//pass the connection to the first available tasklet
fprintf(stderr,"sending new connection...\n");
PyChannel_Send(uwsgi->workers_channel, Py_True);
}
}
/*
if (PyStackless_GetRunCount() > 0) {
PyStackless_Schedule(Py_None, 0);
}
*/
PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
fprintf(stderr,"done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
fprintf(stderr,"re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
fprintf(stderr,"recycle\n");
*/
}
}
#endif
-4
View File
@@ -1,4 +0,0 @@
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)
+12
View File
@@ -0,0 +1,12 @@
use strict;
use warnings;
my $app = sub {
my $env = shift;
return [
'200',
[ 'Content-Type' => 'text/plain' ],
[ "Hello World\r\n", $env->{'REQUEST_URI'} ],
];
};
+2 -2
View File
@@ -10,7 +10,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
#import django.core.handlers.wsgi
uwsgi.load_plugin(0, "plugins/example/example_plugin.so", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa")
#uwsgi.load_plugin(0, "plugins/example/example_plugin.so", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa")
from threading import Thread
@@ -154,7 +154,7 @@ def reload(env, start_response):
#print w
#print w['running_time']
if w is not None:
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['in_request']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
print w
yield '</table>'
View File
+6
View File
@@ -0,0 +1,6 @@
import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
for i in range(1,100000):
yield "<h1>%s at %s</h1>" % (i, str(time.time()))
+15
View File
@@ -0,0 +1,15 @@
import uwsgi
import time
def application(env, start_response):
counter = 0
start_response( '200 OK', [ ('Content-Type','text/html') ])
start_time = time.time()
for i in range(1,100000):
uwsgi.green_schedule()
# print every 100
if i % 100 == 0:
yield "<h1>%d</h1>\n" % i
counter = counter + i
yield "<h1>%d cycles after %d</h1>\n" % (counter, time.time() - start_time)
+14
View File
@@ -0,0 +1,14 @@
import time
import stackless
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
#print env
for i in range(1,100000):
#print i
yield "<h1>%s at %s</h1>\n" % (i, str(time.time()))
#schedule every 2
if i % 2 == 0:
stackless.schedule()
print "DONE AT %d" % i
+17
View File
@@ -0,0 +1,17 @@
import sys
import mimetypes
basedir = sys.argv[1]
mimetypes.init()
def application(environ, start_response):
filename = basedir + environ['PATH_INFO']
(content_type, encoding) = mimetypes.guess_type(filename)
if not content_type:
content_type = 'text/plain'
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+43
View File
@@ -0,0 +1,43 @@
import socket
import select
import errno
def send_request(env, client):
client.setblocking(1)
client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")
while 1:
yield env['x-wsgiorg.fdevent.readable'](client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield buf
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
#env['x-wsgiorg.fdevent.readable'] = lambda fd,t: ""
#env['x-wsgiorg.fdevent.writable'] = lambda fd,t: ""
#yield ""
c = s.connect_ex(('www.google.it', 80))
if c == errno.EINPROGRESS:
yield env['x-wsgiorg.fdevent.writable'](s.fileno(), 10)
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
yield r
else:
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
+41
View File
@@ -0,0 +1,41 @@
import uwsgi
import socket
import errno
def send_request(env, client):
client.setblocking(1)
client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")
uwsgi.green_schedule()
while 1:
uwsgi.green_wait_fdread(client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield buf
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
c = s.connect_ex(('74.125.77.104', 80))
if c == errno.EINPROGRESS:
uwsgi.green_wait_fdwrite(s.fileno(), 10)
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
yield r
else:
uwsgi.green_schedule()
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
+19
View File
@@ -0,0 +1,19 @@
import uwsgi
from mako.template import Template
import time
def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
mytemplate = Template("<h1>I am Mako at ${thetime}</h1>")
uwsgi.green_schedule()
yield mytemplate.render(thetime = time.time() )
for i in range(1, 100):
mytemplate = Template("Iteration ${thei} at ${thetime}<br/>")
uwsgi.green_schedule()
yield mytemplate.render(thei = i, thetime = time.time() )
+9
View File
@@ -0,0 +1,9 @@
import uwsgi
sleepvalue = 5 ;
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
yield uwsgi.async_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %d seconds</h1>" % sleepvalue
+14
View File
@@ -0,0 +1,14 @@
import uwsgi
import time
def application(env, start_response):
sleepvalue = 5 ;
if env.has_key('QUERY_STRING'):
if env['QUERY_STRING'] != '':
sleepvalue = int(env['QUERY_STRING'])
start_response('200 Ok', [('Content-type', 'text/html')])
start_at = time.time()
uwsgi.green_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %s seconds</h1>" % str(time.time() - start_at)
+20
View File
@@ -0,0 +1,20 @@
import sys
content_type = 'image/png'
filename = 'logo_uWSGI.png'
try:
filename = sys.argv[1]
except:
pass
try:
content_type = sys.argv[2]
except:
pass
def application(environ, start_response):
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+454
View File
@@ -0,0 +1,454 @@
#ifdef UWSGI_UGREEN
/* uGreen -> uWSGI green threads */
#include "uwsgi.h"
#define UGREEN_DEFAULT_STACKSIZE 256*1024
extern struct uwsgi_server uwsgi;
void u_green_write_all(struct uwsgi_server *uwsgi, char *data, size_t len) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
ssize_t rlen ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
perror("write()");
// mark core as plagued
wsgi_req->async_plagued = 1 ;
}
else {
wsgi_req->response_size += rlen ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
void u_green_unpause_all(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
static int u_green_blocking(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
return 0 ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return -1 ;
}
inline static void u_green_schedule_to_main(struct uwsgi_server *uwsgi, int async_id) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
swapcontext(uwsgi->ugreen_contexts[async_id], &uwsgi->ugreenmain);
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
inline static void u_green_schedule_to_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
uwsgi->wsgi_req = wsgi_req;
wsgi_req->async_switches++;
swapcontext(&uwsgi->ugreenmain, uwsgi->ugreen_contexts[wsgi_req->async_id] );
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
static void u_green_wait_for_fd(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int fd, int etype, int timeout) {
if (fd < 0) return;
if (async_add(uwsgi->async_queue, fd, etype)) return ;
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = etype;
wsgi_req->async_timeout = time(NULL) + timeout ;
u_green_schedule_to_main(uwsgi, wsgi_req->async_id);
async_del(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type);
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_timeout = 0 ;
}
PyObject *py_uwsgi_green_pause(PyObject * self, PyObject * args) {
int timeout = 0 ;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i", &timeout)) {
return NULL;
}
wsgi_req->async_status = UWSGI_PAUSED;
if (timeout) {
wsgi_req->async_timeout = time(NULL) + timeout ;
}
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
// something bad happened during pause ?
if (wsgi_req->async_plagued) {
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_write_all(PyObject * self, PyObject * args) {
char *data;
if (!PyArg_ParseTuple(args, "s", &data)) {
return NULL;
}
u_green_write_all(&uwsgi, data, strlen(data));
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_green_unpause_all(PyObject * self, PyObject * args) {
if (uwsgi.async > 1) {
u_green_unpause_all(&uwsgi);
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_green_schedule(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_wait_fdread(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_IN, timeout);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_wait_fdwrite(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_OUT, timeout);
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_green_sleep(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int timeout;
if (!PyArg_ParseTuple(args, "i", &timeout)) {
return NULL;
}
wsgi_req->async_timeout = time(NULL) + timeout ;
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
wsgi_req->async_timeout = 0 ;
Py_INCREF(Py_True);
return Py_True;
}
PyMethodDef uwsgi_green_methods[] = {
{"green_schedule", py_uwsgi_green_schedule, METH_VARARGS, ""},
{"green_wait_fdread", py_uwsgi_green_wait_fdread, METH_VARARGS, ""},
{"green_wait_fdwrite", py_uwsgi_green_wait_fdwrite, METH_VARARGS, ""},
{"green_sleep", py_uwsgi_green_sleep, METH_VARARGS, ""},
{"green_pause", py_uwsgi_green_pause, METH_VARARGS, ""},
{"green_unpause_all", py_uwsgi_green_unpause_all, METH_VARARGS, ""},
{"green_write_all", py_uwsgi_green_write_all, METH_VARARGS, ""},
{ NULL, NULL }
};
static struct wsgi_request *find_first_accepting_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_ACCEPTING) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
static void u_green_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int async_id) {
for(;;) {
wsgi_req_setup(wsgi_req, async_id);
wsgi_req->async_status = UWSGI_ACCEPTING;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_accept(uwsgi->serverfd, wsgi_req)) {
continue;
}
wsgi_req->async_status = UWSGI_OK;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_recv(wsgi_req)) {
continue;
}
while(wsgi_req->async_status == UWSGI_AGAIN) {
u_green_schedule_to_main(uwsgi, async_id);
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
}
u_green_schedule_to_main(uwsgi, async_id);
uwsgi_close_request(uwsgi, wsgi_req);
}
}
void u_green_init(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i;
size_t u_stack_size = UGREEN_DEFAULT_STACKSIZE ;
PyMethodDef *uwsgi_function;
if (uwsgi->ugreen_stackpages > 0) {
u_stack_size = uwsgi->ugreen_stackpages * uwsgi->page_size ;
}
fprintf(stderr,"initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi->async, (unsigned long) u_stack_size, (unsigned long) u_stack_size/1024);
uwsgi->ugreen_contexts = malloc( sizeof(ucontext_t*) * uwsgi->async);
if (!uwsgi->ugreen_contexts) {
perror("malloc()\n");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->ugreen_contexts[i] = malloc( sizeof(ucontext_t) );
if (!uwsgi->ugreen_contexts[i]) {
perror("malloc()");
exit(1);
}
getcontext(uwsgi->ugreen_contexts[i]);
uwsgi->ugreen_contexts[i]->uc_stack.ss_sp = mmap(NULL, u_stack_size + (uwsgi->page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi->page_size;
if (!uwsgi->ugreen_contexts[i]->uc_stack.ss_sp) {
perror("mmap()");
exit(1);
}
// set guard pages for stack
if (mprotect(uwsgi->ugreen_contexts[i]->uc_stack.ss_sp - uwsgi->page_size, uwsgi->page_size, PROT_NONE)) {
perror("mprotect()");
exit(1);
}
if (mprotect(uwsgi->ugreen_contexts[i]->uc_stack.ss_sp + u_stack_size, uwsgi->page_size, PROT_NONE)) {
perror("mprotect()");
exit(1);
}
uwsgi->ugreen_contexts[i]->uc_stack.ss_size = u_stack_size ;
uwsgi->ugreen_contexts[i]->uc_link = NULL;
makecontext(uwsgi->ugreen_contexts[i], (void (*) (void)) &u_green_request, 3, uwsgi, wsgi_req, i);
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
for (uwsgi_function = uwsgi_green_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi->embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
}
void u_green_expire_timeouts(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_status = UWSGI_AGAIN ;
wsgi_req->async_timeout = 0 ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
static int u_green_get_timeout(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
if (!uwsgi->async_running) return 0;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return 0;
}
void u_green_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i, current = 0, timeout ;
while(uwsgi->workers[uwsgi->mywid].manage_next_request) {
uwsgi->async_running = u_green_blocking(uwsgi) ;
timeout = u_green_get_timeout(uwsgi);
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, timeout);
if (uwsgi->async_nevents < 0) {
continue;
}
u_green_expire_timeouts(uwsgi);
if (uwsgi->async_nevents > 0) {
wsgi_req = find_first_accepting_wsgi_req(uwsgi);
if (!wsgi_req) goto cycle;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
wsgi_req = find_wsgi_req_by_fd(uwsgi, uwsgi->async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
async_del(uwsgi->async_queue, uwsgi->async_events[i].ASYNC_FD, uwsgi->async_events[i].ASYNC_EV);
}
}
}
cycle:
wsgi_req = find_wsgi_req_by_id(uwsgi, current) ;
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
current++;
if (current >= uwsgi->async) current = 0;
}
if (uwsgi->workers[uwsgi->mywid].manage_next_request == 0) {
reload_me();
}
else {
goodbye_cruel_world();
}
// never here
}
#endif
Executable
+45
View File
@@ -0,0 +1,45 @@
#!./uwsgi
import uwsgi
from bottle import route, default_app, request, response, redirect
@route('/')
def chat():
return """<iframe src="/recv"></iframe>
<iframe src="/sender"></iframe>"""
@route('/sender')
def sender():
return """<form method="GET" action="/send">
<textarea name="message"></textarea><br/>
<input type="submit" value="send" />
</form>"""
@route('/recv')
def recv():
response.header['Transfer-Encoding'] = 'chunked'
# this will flush headers
yield ""
running = True
while running:
# this will put the core in pause (for max 10 seconds) and remove it from the sched queue, so the /send can write to its socket
if not uwsgi.green_pause(10):
running = False
# this will maintain the connection opened if no data arrives
yield "<span/>"
@route('/send')
def send():
# this will write to all the core in PAUSED state
uwsgi.green_write_all(request.GET['message'] + "<br/>")
# this will unpause all the paused cores, so they will be re-inserted in the sched queue
uwsgi.green_unpause_all()
redirect('/sender')
application = default_app()
+295 -4
View File
@@ -29,6 +29,12 @@ void daemonize(char *logfile) {
pid_t pid;
int fd, fdin;
#ifdef UWSGI_UDP
char *udp_port;
struct sockaddr_in udp_addr;
#endif
pid = fork();
if (pid < 0) {
@@ -70,11 +76,43 @@ void daemonize(char *logfile) {
exit(1);
}
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
perror("open()");
exit(1);
#ifdef UWSGI_UDP
udp_port = strchr(logfile, ':');
if (udp_port) {
udp_port[0] = 0 ;
if ( !udp_port[1] || !logfile[0] ) {
fprintf(stderr,"invalid udp address\n");
exit(1);
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket()");
exit(1);
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(logfile);
if (connect(fd, (const struct sockaddr *) &udp_addr, sizeof(struct sockaddr_in)) < 0) {
perror("connect()");
exit(1);
}
}
else {
#endif
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
perror("open()");
exit(1);
}
#ifdef UWSGI_UDP
}
#endif
/* stdin */
if (dup2(fdin, 0) < 0) {
@@ -132,3 +170,256 @@ char *uwsgi_get_cwd() {
return cwd;
}
void internal_server_error(int fd, char *message) {
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
#endif
uwsgi.wsgi_req->headers_size = write(fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63);
#ifndef UNBIT
}
else {
uwsgi.wsgi_req->headers_size = write(fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62);
}
uwsgi.wsgi_req->header_cnt = 2;
#endif
uwsgi.wsgi_req->response_size = write(fd, "<h1>uWSGI Error</h1>", 20);
uwsgi.wsgi_req->response_size += write(fd, message, strlen(message));
}
void uwsgi_as_root() {
if (!getuid()) {
fprintf(stderr, "uWSGI running as root, you can use --uid/--gid/--chroot options\n");
if (uwsgi.chroot) {
fprintf(stderr, "chroot() to %s\n", uwsgi.chroot);
if (chroot(uwsgi.chroot)) {
perror("chroot()");
exit(1);
}
#ifdef __linux__
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
fprintf(stderr, "*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
}
#endif
}
if (uwsgi.gid) {
fprintf(stderr, "setgid() to %d\n", uwsgi.gid);
if (setgid(uwsgi.gid)) {
perror("setgid()");
exit(1);
}
}
if (uwsgi.uid) {
fprintf(stderr, "setuid() to %d\n", uwsgi.uid);
if (setuid(uwsgi.uid)) {
perror("setuid()");
exit(1);
}
}
if (!getuid()) {
fprintf(stderr, " *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
}
}
else {
if (uwsgi.chroot) {
fprintf(stderr, "cannot chroot() as non-root user\n");
exit(1);
}
if (uwsgi.gid) {
fprintf(stderr, "cannot setgid() as non-root user\n");
exit(1);
}
if (uwsgi.uid) {
fprintf(stderr, "cannot setuid() as non-root user\n");
exit(1);
}
}
}
void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int waitpid_status ;
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);
// get memory usage
if (uwsgi->shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1)
get_memusage();
// close the connection with the webserver
if (!wsgi_req->fd_closed) {
close(wsgi_req->poll.fd);
}
uwsgi->workers[0].requests++;
uwsgi->workers[uwsgi->mywid].requests++;
// after_request hook
(*uwsgi->shared->after_hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
// leave harakiri mode
if (uwsgi->workers[uwsgi->mywid].harakiri > 0) {
set_harakiri(0);
}
// defunct process reaper
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1) {
waitpid(-1, &waitpid_status, WNOHANG);
}
// reset request
memset(wsgi_req, 0, sizeof(struct wsgi_request));
if (uwsgi->shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi->workers[uwsgi->mywid].requests >= uwsgi->shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
goodbye_cruel_world();
}
}
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
wsgi_req->poll.events = POLLIN;
wsgi_req->app_id = uwsgi.default_app;
wsgi_req->async_id = async_id;
#ifdef UWSGI_SENDFILE
wsgi_req->sendfile_fd = -1;
#endif
#ifdef UWSGI_ASYNC
wsgi_req->async_waiting_fd = -1;
#endif
wsgi_req->hvec = &uwsgi.async_hvec[wsgi_req->async_id];
}
int wsgi_req_recv(struct wsgi_request *wsgi_req) {
UWSGI_SET_IN_REQUEST;
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING]) gettimeofday(&wsgi_req->start_of_request, NULL);
if (!uwsgi_parse_response(&wsgi_req->poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, &wsgi_req->buffer)) {
return -1;
}
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
wsgi_req->async_status = (*uwsgi.shared->hooks[wsgi_req->uh.modifier1]) (&uwsgi, wsgi_req);
return 0;
}
int wsgi_req_accept(int fd, struct wsgi_request *wsgi_req) {
wsgi_req->poll.fd = accept(fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) &wsgi_req->c_len);
if (wsgi_req->poll.fd < 0) {
perror("accept()");
return -1;
}
return 0;
}
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi->stackless && uwsgi->async >1) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
return wsgi_req;
}
void sanitize_args(struct uwsgi_server *uwsgi) {
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler) {
fprintf(stderr,"*** Profiler enabled, do not use it in production environment !!! ***\n");
uwsgi->async = 1;
}
#endif
#ifdef UWSGI_UGREEN
#ifdef UWSGI_THREADING
if (uwsgi->ugreen) {
if (uwsgi->has_threads) {
fprintf(stderr,"--- python threads will be disabled in uGreen mode ---\n");
uwsgi->has_threads = 0;
}
}
#endif
#endif
}
void env_to_arg(char *src, char *dst) {
int i;
for(i=0;i<strlen(src);i++) {
dst[i] = tolower(src[i]);
if (dst[i] == '_') {
dst[i] = '-';
}
}
dst[strlen(src)] = 0;
}
void parse_sys_envs(char **envs, struct option *long_options) {
struct option *lopt, *aopt;
char **uenvs = envs;
char *earg, *eq_pos ;
while(*uenvs) {
if (!strncmp(*uenvs, "UWSGI_", 6)) {
earg = malloc(strlen(*uenvs+6)+1);
if (!earg) {
perror("malloc()");
exit(1);
}
env_to_arg(*uenvs+6, earg);
eq_pos = strchr(earg, '=');
if (!eq_pos) {
break;
}
eq_pos[0] = 0 ;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(earg, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
}
else {
if (eq_pos[1] != 0) {
manage_opt(aopt->val, eq_pos+1);
}
else {
manage_opt(aopt->val, NULL);
}
}
}
lopt++;
}
}
uenvs++;
}
}
+632 -687
View File
File diff suppressed because it is too large Load Diff
+270 -42
View File
@@ -16,6 +16,10 @@
#include <netinet/sctp.h>
#endif
#ifdef UWSGI_UGREEN
#include <ucontext.h>
#endif
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/file.h>
@@ -60,15 +64,26 @@
#define MAX_PYARGV 10
#include <sys/ioctl.h>
#ifdef __linux__
#include <sys/sendfile.h>
#include <sys/epoll.h>
#elif defined(__sun__)
#include <sys/devpoll.h>
#else
#include <sys/event.h>
#endif
#undef _XOPEN_SOURCE
#include <Python.h>
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t int
#define Py_ssize_t ssize_t
#endif
#if PY_MAJOR_VERSION > 2
@@ -110,6 +125,15 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LONG_ARGS_VERSION 17018
#define LONG_ARGS_SNMP 17019
#define LONG_ARGS_SNMP_COMMUNITY 17020
#define LONG_ARGS_ASYNC 17021
#define LONG_ARGS_UGREEN_PAGES 17022
#define LONG_ARGS_FILE_CONFIG 17023
#define LONG_ARGS_MULTICAST 17024
#define UWSGI_OK 0
#define UWSGI_AGAIN 1
#define UWSGI_ACCEPTING 2
#define UWSGI_PAUSED 3
#define UWSGI_CLEAR_STATUS uwsgi.workers[uwsgi.mywid].status = 0
@@ -196,67 +220,125 @@ struct uwsgi_app {
PyThreadState *interpreter;
PyObject *pymain_dict;
PyObject *wsgi_callable;
PyObject *wsgi_environ;
#ifdef UWSGI_ASYNC
PyObject **wsgi_args;
PyObject **wsgi_environ;
#else
PyObject *wsgi_args;
PyObject *wsgi_environ;
#endif
PyObject *wsgi_harakiri;
PyObject *wsgi_sendfile;
PyObject *wsgi_cprofile_run;
#ifdef UWSGI_ASYNC
PyObject *wsgi_eventfd_read;
PyObject *wsgi_eventfd_write;
#endif
int requests;
};
struct __attribute__ ((packed)) wsgi_request {
uint8_t modifier;
uint16_t size;
uint8_t modifier_arg;
struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
};
struct wsgi_request {
struct uwsgi_header uh;
// temporary attr
int app_id;
struct pollfd poll;
// this is big enough to contain sockaddr_in
struct sockaddr_un c_addr;
int c_len;
// iovec
struct iovec *hvec;
struct timeval start_of_request;
struct timeval end_of_request;
char *uri;
unsigned short uri_len;
uint16_t uri_len;
char *remote_addr;
unsigned short remote_addr_len;
uint16_t remote_addr_len;
char *remote_user;
unsigned short remote_user_len;
uint16_t remote_user_len;
char *query_string;
unsigned short query_string_len;
uint16_t query_string_len;
char *protocol;
unsigned short protocol_len;
uint16_t protocol_len;
char *method;
unsigned short method_len;
uint16_t method_len;
char *scheme;
unsigned short scheme_len;
uint16_t scheme_len;
char *https;
unsigned short https_len;
uint16_t https_len;
char *script_name;
uint16_t script_name_len;
char *wsgi_script;
uint16_t wsgi_script_len;
char *wsgi_module;
uint16_t wsgi_module_len;
char *wsgi_callable;
uint16_t wsgi_callable_len;
#ifdef UNBIT
unsigned long long unbit_flags;
#endif
char *wsgi_script;
unsigned short wsgi_script_len;
char *wsgi_module;
unsigned short wsgi_module_len;
char *wsgi_callable;
unsigned short wsgi_callable_len;
char *script_name;
unsigned short script_name_len;
int fd_closed;
int sendfile_fd;
size_t sendfile_fd_chunk;
size_t sendfile_fd_size;
off_t sendfile_fd_pos;
unsigned short var_cnt;
unsigned short header_cnt;
uint16_t var_cnt;
uint16_t header_cnt;
int status;
int response_size;
size_t response_size;
int headers_size;
int async_status;
int async_id;
int async_status ;
int async_waiting_fd;
int async_waiting_fd_type;
int async_waiting_fd_monitored;
int async_switches;
time_t async_timeout ;
int async_timeout_expired ;
void *async_app;
void *async_result;
void *async_placeholder;
void *async_args;
void *async_environ;
void *async_post;
void *async_sendfile;
int async_plagued;
#ifdef UWSGI_STACKLESS
PyTaskletObject* tasklet;
#endif
// buffer MUST BE THE LAST VAR !!!
char buffer;
};
struct uwsgi_server {
@@ -267,6 +349,11 @@ struct uwsgi_server {
int wsgi_cnt;
int default_app;
int enable_profiler;
// base for all the requests (even on async mode)
struct wsgi_request *wsgi_requests ;
struct wsgi_request *wsgi_req ;
PyThreadState *_save;
#ifndef UNBIT
char *chroot;
@@ -274,7 +361,6 @@ struct uwsgi_server {
uid_t uid;
#endif
char *buffer;
int serverfd;
#ifdef UWSGI_PROXY
@@ -282,6 +368,8 @@ struct uwsgi_server {
char *proxy_socket_name;
#endif
struct iovec *async_hvec;
struct rlimit rl;
char *binary_path;
@@ -289,19 +377,33 @@ struct uwsgi_server {
int is_a_reload;
char *socket_name;
#ifdef UWSGI_UDP
char *udp_socket;
#endif
#ifdef UWSGI_MULTICAST
char *multicast_group;
#endif
#ifdef UWSGI_SPOOLER
char *spool_dir;
#endif
#ifdef UWSGI_ERLANG
char *erlang_node;
char *erlang_cookie;
#endif
#ifdef UWSGI_NAGIOS
int nagios;
#endif
#ifdef UWSGI_SNMP
int snmp;
char *snmp_community;
#endif
// iovec
struct iovec *hvec;
int to_heaven;
int to_hell;
@@ -322,6 +424,27 @@ struct uwsgi_server {
char *pidfile;
int numproc;
int async;
int async_running;
int async_queue ;
int async_nevents ;
int stackless;
#ifdef UWSGI_UGREEN
int ugreen;
int ugreen_stackpages;
ucontext_t ugreenmain;
ucontext_t **ugreen_contexts;
#endif
#ifdef __linux__
struct epoll_event *async_events;
#elif defined(__sun__)
struct pollfd *async_events;
#else
struct kevent *async_events;
#endif
int max_vars;
int vec_size;
@@ -346,6 +469,8 @@ struct uwsgi_server {
#ifdef UWSGI_XML
char *xml_config;
#endif
char *file_config;
char *python_path[64];
int python_path_cnt;
@@ -359,16 +484,22 @@ struct uwsgi_server {
int single_interpreter;
int py_optimize;
PyObject *py_sendfile;
PyObject *embedded_dict;
PyObject *embedded_args;
PyObject *fastfuncslist;
PyObject *wsgi_writeout;
#ifdef UWSGI_STACKLESS
PyObject *wsgi_stackless;
PyChannelObject *workers_channel;
struct stackless_req **stackless_table;
#endif
PyObject *workers_tuple;
PyThreadState *main_thread;
struct pollfd poll;
struct uwsgi_shared *shared;
@@ -419,6 +550,7 @@ struct uwsgi_shared {
#ifdef UWSGI_SPOOLER
pid_t spooler_pid;
int spooler_frequency;
#endif
#ifdef UWSGI_PROXY
@@ -463,12 +595,6 @@ struct uwsgi_worker {
};
struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize;
uint8_t modifier2;
};
char *uwsgi_get_cwd(void);
void warn_pipe(void);
@@ -503,7 +629,7 @@ void init_uwsgi_embedded_module(void);
void uwsgi_xml_config(struct wsgi_request *, struct option *);
#endif
void uwsgi_wsgi_config(void);
void uwsgi_wsgi_config(char *);
void uwsgi_paste_config(void);
void uwsgi_wsgi_file_config(void);
@@ -521,8 +647,8 @@ void snmp_init(void);
#endif
#ifdef UWSGI_SPOOLER
int spool_request(char *, int, char *, int);
void spooler(PyObject *);
int spool_request(struct uwsgi_server *, char *, int, char *, int);
void spooler(struct uwsgi_server *, PyObject *);
pid_t spooler_start(int, PyObject *);
#endif
@@ -563,7 +689,7 @@ int uwsgi_request_ping(struct uwsgi_server *, struct wsgi_request *);
#include <ei.h>
int init_erlang(char *, char *);
void erlang_loop(void);
void erlang_loop(struct wsgi_request *);
PyObject *eterm_to_py(ETERM *);
ETERM *py_to_eterm(PyObject *);
@@ -584,3 +710,105 @@ struct http_status_codes {
char *message;
int message_size;
};
#ifdef UWSGI_ASYNC
struct wsgi_request *async_loop(struct uwsgi_server *);
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *, int);
struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
int async_add(int, int , int) ;
int async_mod(int, int , int) ;
int async_wait(int, void *, int, int, int);
int async_del(int, int , int) ;
int async_queue_init(int);
int async_get_timeout(struct uwsgi_server *);
void async_set_timeout(struct wsgi_request *, time_t);
void async_expire_timeouts(struct uwsgi_server *);
void async_write_all(struct uwsgi_server *, char *, size_t);
void async_unpause_all(struct uwsgi_server *);
#ifdef __linux__
#define ASYNC_FD data.fd
#define ASYNC_EV events
#define ASYNC_IN EPOLLIN
#define ASYNC_OUT EPOLLOUT
#define ASYNC_IS_IN ASYNC_EV & ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV & ASYNC_OUT
#elif defined(__sun__)
#define ASYNC_FD fd
#define ASYNC_EV revents
#define ASYNC_IN POLLIN
#define ASYNC_OUT POLLOUT
#define ASYNC_IS_IN ASYNC_EV & ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV & ASYNC_OUT
#else
#define ASYNC_FD ident
#define ASYNC_EV filter
#define ASYNC_IN EVFILT_READ
#define ASYNC_OUT EVFILT_WRITE
#define ASYNC_IS_IN ASYNC_EV == ASYNC_IN
#define ASYNC_IS_OUT ASYNC_EV == ASYNC_OUT
#endif
PyObject *py_eventfd_read(PyObject *, PyObject *) ;
PyObject *py_eventfd_write(PyObject *, PyObject *) ;
#endif
#ifdef UWSGI_STACKLESS
PyObject *py_uwsgi_stackless(PyObject *, PyObject *) ;
#endif
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
ssize_t uwsgi_sendfile(struct uwsgi_server *, struct wsgi_request *);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *) ;
PyObject *py_uwsgi_spit(PyObject *, PyObject *) ;
void uwsgi_as_root(void);
#ifdef UWSGI_NAGIOS
void nagios(struct uwsgi_server *);
#endif
#ifdef UWSGI_STACKLESS
struct stackless_req {
PyTaskletObject *tasklet;
struct wsgi_request *wsgi_req;
PyChannelObject *channel;
};
struct wsgi_request *find_request_by_tasklet(PyTaskletObject *);
void stackless_init(struct uwsgi_server *);
void stackless_loop(struct uwsgi_server *);
#endif
void uwsgi_close_request(struct uwsgi_server *, struct wsgi_request *) ;
void wsgi_req_setup(struct wsgi_request *, int);
int wsgi_req_recv(struct wsgi_request *);
int wsgi_req_accept(int, struct wsgi_request *);
#ifdef UWSGI_UGREEN
void u_green_init(struct uwsgi_server *);
void u_green_loop(struct uwsgi_server *);
#endif
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
void sanitize_args(struct uwsgi_server *);
void env_to_arg(char *, char *);
void parse_sys_envs(char **, struct option *);
+32 -43
View File
@@ -5,20 +5,20 @@ int uwsgi_request_ping(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
char len;
fprintf(stderr, "PING\n");
wsgi_req->modifier_arg = 1;
wsgi_req->size = 0;
wsgi_req->uh.modifier2 = 1;
wsgi_req->uh.pktsize = 0;
len = strlen(uwsgi->shared->warning_message);
if (len > 0) {
// endianess check is not needed as the warning message can be max 80 chars
wsgi_req->size = len;
wsgi_req->uh.pktsize = len;
}
if (write(uwsgi->poll.fd, wsgi_req, 4) != 4) {
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
perror("write()");
}
if (len > 0) {
if (write(uwsgi->poll.fd, uwsgi->shared->warning_message, len)
if (write(wsgi_req->poll.fd, uwsgi->shared->warning_message, len)
!= len) {
perror("write()");
}
@@ -32,52 +32,41 @@ int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re
uint32_t opt_value = 0;
int i;
if (wsgi_req->size >= 4) {
memcpy(&opt_value, uwsgi->buffer, 4);
if (wsgi_req->uh.pktsize >= 4) {
memcpy(&opt_value, &wsgi_req->buffer, 4);
// TODO: check endianess
}
fprintf(stderr, "setting internal option %d to %d\n", wsgi_req->modifier_arg, opt_value);
uwsgi->shared->options[wsgi_req->modifier_arg] = opt_value;
wsgi_req->modifier = 255;
wsgi_req->size = 0;
wsgi_req->modifier_arg = 1;
i = write(uwsgi->poll.fd, wsgi_req, 4);
fprintf(stderr, "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi->shared->options[wsgi_req->uh.modifier2] = opt_value;
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
perror("write()");
}
return 0;
return UWSGI_OK;
}
/* uwsgi FASTFUNC|26 */
int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
PyObject *zero, *func_result, *fchunk, *func_chunks;
PyObject *ffunc;
zero = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->modifier_arg);
if (zero) {
fprintf(stderr, "managing fastfunc %d\n", wsgi_req->modifier_arg);
func_result = PyEval_CallObject(zero, NULL);
if (PyErr_Occurred()) {
PyErr_Print();
}
if (func_result) {
func_chunks = PyObject_GetIter(func_result);
if (func_chunks) {
while ((fchunk = PyIter_Next(func_chunks))) {
if (PyString_Check(fchunk)) {
wsgi_req->response_size += write(uwsgi->poll.fd, PyString_AsString(fchunk), PyString_Size(fchunk));
}
Py_DECREF(fchunk);
}
Py_DECREF(func_chunks);
}
Py_DECREF(func_result);
}
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return manage_python_response(uwsgi, wsgi_req);
}
#endif
ffunc = PyList_GetItem(uwsgi->fastfuncslist, wsgi_req->uh.modifier2);
if (ffunc) {
fprintf(stderr, "managing fastfunc %d\n", wsgi_req->uh.modifier2);
return uwsgi_python_call(uwsgi, wsgi_req, ffunc, NULL);
}
PyErr_Clear();
return 0;
return UWSGI_OK;
}
/* uwsgi MARSHAL|33 */
@@ -87,11 +76,11 @@ int uwsgi_request_marshal(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
PyObject *umm = PyDict_GetItemString(uwsgi->embedded_dict,
"message_manager_marshal");
if (umm) {
PyObject *ummo = PyMarshal_ReadObjectFromString(uwsgi->buffer,
wsgi_req->size);
PyObject *ummo = PyMarshal_ReadObjectFromString(&wsgi_req->buffer,
wsgi_req->uh.pktsize);
if (ummo) {
if (!PyTuple_SetItem(uwsgi->embedded_args, 0, ummo)) {
if (!PyTuple_SetItem(uwsgi->embedded_args, 1, PyInt_FromLong(wsgi_req->modifier_arg))) {
if (!PyTuple_SetItem(uwsgi->embedded_args, 1, PyInt_FromLong(wsgi_req->uh.modifier2))) {
func_result = PyEval_CallObject(umm, uwsgi->embedded_args);
if (PyErr_Occurred()) {
PyErr_Print();
@@ -103,10 +92,10 @@ int uwsgi_request_marshal(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_
}
else {
if (PyString_Size(marshalled) <= 0xFFFF) {
wsgi_req->size = (uint16_t)
wsgi_req->uh.pktsize = (uint16_t)
PyString_Size(marshalled);
if (write(uwsgi->poll.fd, wsgi_req, 4) == 4) {
if (write(uwsgi->poll.fd, PyString_AsString(marshalled), wsgi_req->size) != wsgi_req->size) {
if (write(wsgi_req->poll.fd, wsgi_req, 4) == 4) {
if (write(wsgi_req->poll.fd, PyString_AsString(marshalled), wsgi_req->uh.pktsize) != wsgi_req->uh.pktsize) {
perror("write()");
}
}
+46 -2
View File
@@ -19,6 +19,28 @@ extern struct uwsgi_server uwsgi;
#define UWSGI_LOGBASE "[- uWSGI -"
#ifdef UWSGI_ASYNC
PyObject *py_uwsgi_async_sleep(PyObject * self, PyObject * args) {
float timeout ;
time_t sec_timeout ;
if (!PyArg_ParseTuple(args, "f:async_sleep", &timeout)) {
return NULL;
}
sec_timeout = (time_t) timeout ;
if (sec_timeout > 0) {
async_set_timeout(uwsgi.wsgi_req, sec_timeout);
}
return PyString_FromString("") ;
}
#endif
PyObject *py_uwsgi_warning(PyObject * self, PyObject * args) {
char *message;
int len;
@@ -254,6 +276,18 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
}
#ifdef UWSGI_SPOOLER
PyObject *py_uwsgi_spooler_freq(PyObject * self, PyObject * args) {
if (!PyArg_ParseTuple(args, "i", &uwsgi.shared->spooler_frequency)) {
return NULL;
}
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
PyObject *spool_dict, *spool_vars;
PyObject *zero, *key, *val;
@@ -335,7 +369,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
}
}
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, spool_buffer, cur_buf - spool_buffer);
i = spool_request(&uwsgi, spool_filename, uwsgi.workers[0].requests + 1, spool_buffer, cur_buf - spool_buffer);
if (i > 0) {
return Py_True;
}
@@ -581,6 +615,7 @@ PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
return Py_None;
}
#ifdef UWSGI_MULTICAST
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
char *host, *message ;
@@ -601,6 +636,7 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
return Py_True;
}
#endif
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
@@ -795,7 +831,11 @@ PyObject *py_uwsgi_worker_id(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
fprintf(stderr, "detaching uWSGI from current connection...\n");
close(uwsgi.poll.fd);
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1 ;
Py_INCREF(Py_True);
return Py_True;
@@ -804,6 +844,7 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
#ifdef UWSGI_SPOOLER
static PyMethodDef uwsgi_spooler_methods[] = {
{"send_to_spooler", py_uwsgi_send_spool, METH_VARARGS, ""},
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
{NULL, NULL},
};
#endif
@@ -830,6 +871,9 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"set_warning_message", py_uwsgi_warning, METH_VARARGS, ""},
#ifdef UWSGI_MULTICAST
{"send_multicast_message", py_uwsgi_multicast, METH_VARARGS, ""},
#endif
#ifdef UWSGI_ASYNC
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
#endif
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
{NULL, NULL},
+113 -24
View File
@@ -14,10 +14,25 @@ PROFILER=True
NAGIOS=True
PROXY=True
MINTERPRETERS=True
ASYNC=True
UGREEN=True
STACKLESS=False
PLUGINS = []
UNBIT=False
UWSGI_BIN_NAME = 'uwsgi'
GCC='gcc'
# specific compilation flags
# libxml2 or expat
XML_IMPLEMENTATION = 'libxml2'
# if you want to use alternative python lib, specifiy its path here
#PYLIB_PATH = '/home/roberto/uwsgi/STACKLESS/slp/lib'
PYLIB_PATH = ''
ERLANG_CFLAGS = ''
ERLANG_LDFLAGS = '-lerl_interface -lei'
# for source distribution installed in /usr/local
#ERLANG_CFLAGS = '-I /usr/local/lib/erlang/lib/erl_interface-3.6.5/include/'
#ERLANG_LDFLAGS = '-L/usr/local/lib/erlang/lib/erl_interface-3.6.5/lib -lerl_interface -lei'
@@ -29,11 +44,25 @@ uwsgi_os = os.uname()[0]
import sys
import subprocess
gcc_list = ['utils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'uwsgi_handlers', 'uwsgi']
from distutils import sysconfig
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'uwsgi']
# large file support
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64']
ldflags = ['-lpthread', '-rdynamic']
try:
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + sysconfig.get_config_var('CFLAGS').split()
except:
print("You need python headers to build uWSGI.")
sys.exit(1)
cflags = cflags + ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
ldflags = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
def depends_on(what, dep):
for d in dep:
if not globals()[d]:
print("%s needs %s support." % (what, d))
sys.exit(1)
def spcall(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
@@ -79,23 +108,41 @@ def build_uwsgi(bin_name):
bin_name = './' + bin_name
print("*** uWSGI is ready, launch it with %s ***" % bin_name)
def unbit_setup():
global XML, SNMP, SCTP, ERLANG, SPOOLER
global EMBEDDED, UDP, MULTICAST, THREADING
global SENDFILE, PROFILER, NAGIOS, PROXY
global UWSGI_BIN_NAME
XML=False
SNMP=False
SCTP=False
ERLANG=False
UDP=False
MULTICAST=False
NAGIOS=False
PROXY=False
EMBEDDED=True
SPOOLER=True
THREADING=True
SENDFILE=True
PROFILER=True
UNBIT=True
UWSGI_BIN_NAME='/usr/share/unbit/uwsgi26'
def parse_vars():
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
pyconf = spcall("python%s-config --cflags" % uver)
if pyconf is None:
print("python development headers unavailable !!!!")
sys.exit(1)
cflags.insert(0,pyconf)
ldflags.append('-lpython' + uver)
pyconf = spcall("python%s-config --libs" % uver)
if pyconf is None:
print("python development headers unavailable !!!!")
sys.exit(1)
ldflags.insert(0,pyconf)
if str(PYLIB_PATH) != '':
ldflags.insert(0,'-L' + PYLIB_PATH)
kvm_list = ['SunOS', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
@@ -112,20 +159,42 @@ def parse_vars():
if UDP:
cflags.append("-DUWSGI_UDP")
if ASYNC:
cflags.append("-DUWSGI_ASYNC")
gcc_list.append('async')
if MULTICAST:
depends_on("MULTICAST", ['UDP'])
cflags.append("-DUWSGI_MULTICAST")
if STACKLESS:
if not cflags.__contains__('-DSTACKLESS_FRHACK=1'):
print("you need Stackless Python to use Tasklet")
sys.exit(1)
cflags.append("-DUWSGI_STACKLESS")
gcc_list.append('stackless')
if MINTERPRETERS:
cflags.append("-DUWSGI_MINTERPRETERS")
if NAGIOS:
cflags.append("-DUWSGI_NAGIOS")
gcc_list.append('nagios')
if PROXY:
depends_on("PROXY", ['ASYNC'])
cflags.append("-DUWSGI_PROXY")
gcc_list.append('proxy')
if UGREEN:
if uwsgi_os == 'Darwin':
cflags.append("-D_XOPEN_SOURCE")
depends_on("UGREEN", ['ASYNC'])
cflags.append("-DUWSGI_UGREEN")
gcc_list.append('ugreen')
if SNMP:
depends_on("SNMP", ['UDP'])
cflags.append("-DUWSGI_SNMP")
gcc_list.append('snmp')
@@ -137,24 +206,36 @@ def parse_vars():
if SENDFILE:
cflags.append("-DUWSGI_SENDFILE")
gcc_list.append('sendfile')
if XML:
xmlconf = spcall('xml2-config --libs')
if xmlconf is None:
print("libxml2 headers unavailable. XML support will be disabled")
else:
ldflags.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
if XML_IMPLEMENTATION == 'libxml2':
xmlconf = spcall('xml2-config --libs')
if xmlconf is None:
print("libxml2 headers unavailable. XML support will be disabled")
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
sys.exit(1)
else:
cflags.append(xmlconf)
cflags.append("-DUWSGI_XML")
gcc_list.append('xmlconf')
ldflags.append(xmlconf)
xmlconf = spcall("xml2-config --cflags")
if xmlconf is None:
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
sys.exit(1)
else:
cflags.append(xmlconf)
cflags.append("-DUWSGI_XML -DUWSGI_XML_LIBXML2")
gcc_list.append('xmlconf')
elif XML_IMPLEMENTATION == 'expat':
cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
ldflags.append('-lexpat')
gcc_list.append('xmlconf')
if ERLANG:
depends_on("ERLANG", ['EMBEDDED'])
cflags.append("-DUWSGI_ERLANG")
ldflags.append("-lerl_interface -lei")
ldflags.append(ERLANG_LDFLAGS)
if str(ERLANG_CFLAGS) != '':
cflags.append(ERLANG_CFLAGS)
gcc_list.append('erlang')
if SCTP:
@@ -162,9 +243,13 @@ def parse_vars():
cflags.append("-DUWSGI_SCTP")
if SPOOLER:
depends_on("SPOOLER", ['EMBEDDED'])
cflags.append("-DUWSGI_SPOOLER")
gcc_list.append('spooler')
if UNBIT:
cflags.append("-DUWSGI_UNBIT")
def build_plugin(path):
path = path.rstrip('/')
@@ -209,6 +294,10 @@ if __name__ == "__main__":
elif cmd == '--build':
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--unbit':
unbit_setup()
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--plugin':
parse_vars()
build_plugin(sys.argv[2])
+181 -353
View File
@@ -1,159 +1,114 @@
#include "uwsgi.h"
static int uwsgi_sendfile(struct uwsgi_server *, int, int);
extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
PyObject *data;
char *content;
int len;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
data = PyTuple_GetItem(args, 0);
if (PyString_Check(data)) {
content = PyString_AsString(data);
len = PyString_Size(data);
#ifdef UWSGI_THREADING
if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
Py_BEGIN_ALLOW_THREADS wsgi_req->response_size = write(wsgi_req->poll.fd, content, len);
Py_END_ALLOW_THREADS}
else {
#endif
wsgi_req->response_size = write(wsgi_req->poll.fd, content, len);
#ifdef UWSGI_THREADING
}
#endif
}
Py_INCREF(Py_None);
return Py_None;
}
#ifdef UWSGI_ASYNC
PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_IN ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = ASYNC_OUT ;
wsgi_req->async_waiting_fd_monitored = 0 ;
}
return PyString_FromString("") ;
}
#endif
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *ptrbuf;
char *bufferend;
uint16_t strsize = 0;
FILE *wsgi_file;
int i;
struct uwsgi_app *wi;
PyObject *zero, *wsgi_socket;
PyObject *pydictkey, *pydictvalue;
char *path_info;
struct uwsgi_app *wi ;
PyObject *wsgi_result, *wsgi_chunks, *wchunk;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0 ;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
return manage_python_response(uwsgi, wsgi_req);
}
#endif
/* Standard WSGI request */
if (!wsgi_req->size) {
if (!wsgi_req->uh.pktsize) {
fprintf(stderr, "Invalid WSGI request. skip.\n");
return -1;
}
ptrbuf = uwsgi->buffer;
bufferend = ptrbuf + wsgi_req->size;
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
fprintf(stderr,"Invalid WSGI request. skip.\n");
return -1;
}
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) {
#ifdef UNBIT
if (single_app_mode == 0 && !strncmp("SCRIPT_NAME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
#else
if (!strncmp("SCRIPT_NAME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
#endif
// set the request app_id
// LOCKED SECTION
if (strsize > 0) {
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
PyEval_RestoreThread(uwsgi->_save);
uwsgi->workers[uwsgi->mywid].i_have_gil = 1;
}
zero = PyString_FromStringAndSize(ptrbuf, strsize);
if (PyDict_Contains(uwsgi->py_apps, zero)) {
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
}
else {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
}
Py_DECREF(zero);
if (uwsgi->has_threads && uwsgi->shared->options[UWSGI_OPTION_THREADS] == 1) {
uwsgi->_save = PyEval_SaveThread();
uwsgi->workers[uwsgi->mywid].i_have_gil = 0;
}
}
// UNLOCK
}
else if (!strncmp("SERVER_PROTOCOL", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
wsgi_req->protocol_len = strsize;
}
else if (!strncmp("REQUEST_URI", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->uri = ptrbuf;
wsgi_req->uri_len = strsize;
}
else if (!strncmp("QUERY_STRING", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->query_string = ptrbuf;
wsgi_req->query_string_len = strsize;
}
else if (!strncmp("REQUEST_METHOD", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!strncmp("REMOTE_ADDR", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!strncmp("REMOTE_USER", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_user = ptrbuf;
wsgi_req->remote_user_len = strsize;
}
else if (!strncmp("UWSGI_SCHEME", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->scheme = ptrbuf;
wsgi_req->scheme_len = strsize;
}
else if (!strncmp("HTTPS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
#ifdef UNBIT
else if (!strncmp("UNBIT_FLAGS", uwsgi->hvec[wsgi_req->var_cnt].iov_base, uwsgi->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
}
#endif
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;
}
}
#ifndef UWSGI_THREADING
#ifdef UWSGI_THREADING
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
PyEval_RestoreThread(uwsgi->_save);
uwsgi->workers[uwsgi->mywid].i_have_gil = 1;
@@ -161,93 +116,91 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
#endif
wsgi_file = fdopen(uwsgi->poll.fd, "r");
#ifdef UWSGI_XML
if (wsgi_req->app_id == -1 && uwsgi->xml_config == NULL) {
#else
if (wsgi_req->app_id == -1 && uwsgi->wsgi_config == NULL) {
#endif
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!strncmp("SCRIPT_NAME", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
wsgi_req->script_name = uwsgi->hvec[i + 1].iov_base;
wsgi_req->script_name_len = uwsgi->hvec[i + 1].iov_len;
if (wsgi_req->script_name_len > 0) {
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
if (PyDict_Contains(uwsgi->py_apps, zero)) {
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
}
else {
/* unavailable app for this SCRIPT_NAME */
wsgi_req->app_id = -1;
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
Py_DECREF(zero);
goto clear2;
}
}
if (!strncmp("UWSGI_SCRIPT", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
wsgi_req->wsgi_script = uwsgi->hvec[i + 1].iov_base;
wsgi_req->wsgi_script_len = uwsgi->hvec[i + 1].iov_len;
}
if (!strncmp("UWSGI_MODULE", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
wsgi_req->wsgi_module = uwsgi->hvec[i + 1].iov_base;
wsgi_req->wsgi_module_len = uwsgi->hvec[i + 1].iov_len;
}
if (!strncmp("UWSGI_CALLABLE", uwsgi->hvec[i].iov_base, uwsgi->hvec[i].iov_len)) {
wsgi_req->wsgi_callable = uwsgi->hvec[i + 1].iov_base;
wsgi_req->wsgi_callable_len = uwsgi->hvec[i + 1].iov_len;
}
}
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
internal_server_error(uwsgi->poll.fd, "wsgi application not found");
goto clean;
}
}
}
}
Py_DECREF(zero);
}
if (wsgi_req->app_id == -1) {
internal_server_error(uwsgi->poll.fd, "wsgi application not found");
goto clean;
}
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
goto clear2;
}
wi = &uwsgi->wsgi_apps[wsgi_req->app_id];
if (uwsgi->single_interpreter == 0) {
if (!wi->interpreter) {
internal_server_error(uwsgi->poll.fd, "wsgi application's %d interpreter not found");
goto clean;
internal_server_error(wsgi_req->poll.fd, "wsgi application's %d interpreter not found");
goto clear2;
}
// set the interpreter
PyThreadState_Swap(wi->interpreter);
}
wi->requests++;
if (wsgi_req->protocol_len < 5) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(uwsgi->poll.fd, "invalid HTTP protocol !!!");
goto clean;
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
fprintf(stderr, "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
internal_server_error(uwsgi->poll.fd, "invalid HTTP protocol !!!");
goto clean;
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
goto clear;
}
#ifdef UWSGI_ASYNC
wsgi_req->async_environ = wi->wsgi_environ[wsgi_req->async_id];
wsgi_req->async_args = wi->wsgi_args[wsgi_req->async_id];
#else
wsgi_req->async_environ = wi->wsgi_environ;
wsgi_req->async_args = wi->wsgi_args;
#endif
Py_INCREF((PyObject *)wsgi_req->async_environ);
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);
pydictvalue = PyString_FromStringAndSize(uwsgi->hvec[i + 1].iov_base, uwsgi->hvec[i + 1].iov_len);
PyDict_SetItem(wi->wsgi_environ, pydictkey, pydictvalue);
//fprintf(stderr,"%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
Py_DECREF(pydictkey);
Py_DECREF(pydictvalue);
}
if (wsgi_req->modifier == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
pydictkey = PyDict_GetItemString(wi->wsgi_environ, "SCRIPT_NAME");
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
pydictvalue = PyDict_GetItemString(wi->wsgi_environ, "PATH_INFO");
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
if (pydictvalue) {
if (PyString_Check(pydictvalue)) {
path_info = PyString_AsString(pydictvalue);
PyDict_SetItemString(wi->wsgi_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
}
}
}
@@ -255,34 +208,46 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
}
// set wsgi vars
wsgi_socket = PyFile_FromFile(wsgi_file, "wsgi_input", "r", NULL);
PyDict_SetItemString(wi->wsgi_environ, "wsgi.input", wsgi_socket);
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_socket);
Py_DECREF(wsgi_socket);
#ifdef UWSGI_SENDFILE
PyDict_SetItemString(wi->wsgi_environ, "wsgi.file_wrapper", wi->wsgi_sendfile);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->wsgi_sendfile);
#endif
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.readable", wi->wsgi_eventfd_read);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.writable", wi->wsgi_eventfd_write);
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
#endif
zero = PyTuple_New(2);
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
PyDict_SetItemString(wi->wsgi_environ, "wsgi.version", zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
Py_DECREF(zero);
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
PyDict_SetItemString(wi->wsgi_environ, "wsgi.errors", zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
Py_DECREF(zero);
PyDict_SetItemString(wi->wsgi_environ, "wsgi.run_once", Py_False);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multithread", Py_False);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_False);
if (uwsgi->numproc == 1) {
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multiprocess", Py_False);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_False);
}
else {
PyDict_SetItemString(wi->wsgi_environ, "wsgi.multiprocess", Py_True);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
}
if (wsgi_req->scheme_len > 0) {
@@ -299,131 +264,57 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
else {
zero = PyString_FromString("http");
}
PyDict_SetItemString(wi->wsgi_environ, "wsgi.url_scheme", zero);
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
Py_DECREF(zero);
#ifdef UNBIT
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
if (uri_to_hex() <= 0) {
tmp_filename[0] = 0;
}
}
#endif
// call
#ifdef UWSGI_PROFILER
if (uwsgi->enable_profiler == 1) {
wsgi_result = PyEval_CallObject(wi->wsgi_cprofile_run, wi->wsgi_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
if (wsgi_result) {
Py_DECREF(wsgi_result);
wsgi_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", wsgi_req->app_id), wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args);
if (wsgi_req->async_result) {
wsgi_req->async_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
Py_INCREF((PyObject*)wsgi_req->async_result);
Py_INCREF((PyObject*)wsgi_req->async_result);
}
}
else {
#endif
wsgi_result = PyEval_CallObject(wi->wsgi_callable, wi->wsgi_args);
if (PyErr_Occurred()) {
PyErr_Print();
}
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_callable, wsgi_req->async_args);
#ifdef UWSGI_PROFILER
}
#endif
if (wsgi_req->async_result) {
if (wsgi_result) {
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1) {
wsgi_req->response_size = uwsgi_sendfile(uwsgi, wsgi_req->sendfile_fd, uwsgi->poll.fd);
}
else {
#endif
wsgi_chunks = PyObject_GetIter(wsgi_result);
if (wsgi_chunks) {
while ((wchunk = PyIter_Next(wsgi_chunks))) {
if (PyString_Check(wchunk)) {
if ((i = write(uwsgi->poll.fd, PyString_AsString(wchunk), PyString_Size(wchunk))) < 0) {
perror("write()");
}
wsgi_req->response_size += i;
#ifdef UNBIT
if (save_to_disk >= 0) {
if (write(save_to_disk, PyString_AsString(wchunk), PyString_Size(wchunk)) < 0) {
perror("write()");
close(save_to_disk);
save_to_disk = -1;
unlinkat(tmp_dir_fd, tmp_filename, 0);
}
}
#endif
}
else {
fprintf(stderr, "invalid output returned by the wsgi callable !!!\n");
}
Py_DECREF(wchunk);
}
if (PyErr_Occurred()) {
PyErr_Print();
}
#ifdef UNBIT
else if (save_to_disk >= 0) {
close(save_to_disk);
save_to_disk = -1;
fprintf(stderr, "[uWSGI cacher] output of request %llu (%.*s) on pid %d written to cache file %s\n", uwsgi->workers[0].requests + 1, wsgi_req->uri_len, wsgi_req->uri, uwsgi->mypid, tmp_filename);
}
#endif
Py_DECREF(wsgi_chunks);
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#ifdef UWSGI_PROFILER
}
if (uwsgi->enable_profiler == 0) {
#endif
Py_DECREF(wsgi_result);
#ifdef UWSGI_PROFILER
}
#endif
}
PyDict_Clear(wi->wsgi_environ);
wi->requests++;
PyErr_Clear();
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(0);
}
clear:
if (uwsgi->single_interpreter == 0) {
// restoring main interpreter
PyThreadState_Swap(uwsgi->main_thread);
}
clean:
fclose(wsgi_file);
clear2:
#ifdef UWSGI_THREADING
if (uwsgi->has_threads && uwsgi->shared->options[UWSGI_OPTION_THREADS] == 1) {
uwsgi->_save = PyEval_SaveThread();
uwsgi->workers[uwsgi->mywid].i_have_gil = 0;
}
#endif
uwsgi->workers[uwsgi->mywid].requests++;
return 0;
return UWSGI_OK;
}
@@ -432,66 +323,3 @@ void uwsgi_after_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *w
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
#ifdef UWSGI_SENDFILE
static int uwsgi_sendfile(struct uwsgi_server *uwsgi, int fd, int sockfd) {
off_t rlen;
#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, &rlen, 0)) {
perror("sendfile()");
}
#elif __APPLE__
if (sendfile(fd, sockfd, 0, &rlen, NULL, 0)) {
perror("sendfile()");
}
#else
ssize_t i = 0;
char *no_sendfile_buf[4096];
ssize_t 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
off_t sf_ot = 0;
rlen = sendfile(sockfd, fd, &sf_ot, rlen);
#endif
}
Py_DECREF(uwsgi->py_sendfile);
return rlen;
}
#endif
+166
View File
@@ -0,0 +1,166 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static char *nl = "\r\n";
static char *h_sep = ": ";
static const char *http_protocol = "HTTP/1.1";
PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *headers, *head;
PyObject *h_key, *h_value;
int i, j;
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
#ifndef UNBIT
int base = 0;
#else
int base = 4;
#endif
// use writev()
head = PyTuple_GetItem(args, 0);
if (!head) {
goto clear;
}
if (!PyString_Check(head)) {
fprintf(stderr, "http status must be a string !\n");
goto clear;
}
#ifndef UNBIT
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
base = 4;
#endif
if (wsgi_req->protocol_len == 0) {
wsgi_req->hvec[0].iov_base = (char *) http_protocol;
wsgi_req->protocol_len = 8;
}
else {
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
}
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
#ifdef PYTHREE
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[2].iov_len = strlen(wsgi_req->hvec[2].iov_base);
#else
wsgi_req->hvec[2].iov_base = PyString_AsString(head);
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
#ifndef UNBIT
}
else {
// drop http status on cgi mode
base = 3;
wsgi_req->hvec[0].iov_base = "Status: ";
wsgi_req->hvec[0].iov_len = 8;
#ifdef PYTHREE
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[1].iov_len = strlen(wsgi_req->hvec[1].iov_base);
#else
wsgi_req->hvec[1].iov_base = PyString_AsString(head);
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
}
#endif
#ifdef UNBIT
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
if (tmp_dir_fd >= 0 && tmp_filename[0] != 0 && wsgi_req->status == 200 && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
save_to_disk = openat(tmp_dir_fd, tmp_filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
}
}
#endif
headers = PyTuple_GetItem(args, 1);
if (!headers) {
goto clear;
}
if (!PyList_Check(headers)) {
fprintf(stderr, "http headers must be in a python list\n");
goto clear;
}
wsgi_req->header_cnt = PyList_Size(headers);
if (wsgi_req->header_cnt > uwsgi.max_vars) {
wsgi_req->header_cnt = uwsgi.max_vars;
}
for (i = 0; i < wsgi_req->header_cnt; i++) {
j = (i * 4) + base;
head = PyList_GetItem(headers, i);
if (!head) {
goto clear;
}
if (!PyTuple_Check(head)) {
fprintf(stderr, "http header must be defined in a tuple !\n");
goto clear;
}
h_key = PyTuple_GetItem(head, 0);
if (!h_key) {
goto clear;
}
h_value = PyTuple_GetItem(head, 1);
if (!h_value) {
goto clear;
}
#ifdef PYTHREE
wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
wsgi_req->hvec[j].iov_len = strlen(wsgi_req->hvec[j].iov_base);
#else
wsgi_req->hvec[j].iov_base = PyString_AsString(h_key);
wsgi_req->hvec[j].iov_len = PyString_Size(h_key);
#endif
wsgi_req->hvec[j + 1].iov_base = h_sep;
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
#ifdef PYTHREE
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
wsgi_req->hvec[j + 2].iov_len = strlen(wsgi_req->hvec[j + 2].iov_base);
#else
wsgi_req->hvec[j + 2].iov_base = PyString_AsString(h_value);
wsgi_req->hvec[j + 2].iov_len = PyString_Size(h_value);
#endif
wsgi_req->hvec[j + 3].iov_base = nl;
wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
//fprintf(stderr, "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
}
// \r\n
j = (i * 4) + base;
wsgi_req->hvec[j].iov_base = nl;
wsgi_req->hvec[j].iov_len = NL_SIZE;
wsgi_req->headers_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, j + 1);
if (wsgi_req->headers_size < 0) {
perror("writev()");
}
Py_INCREF(uwsgi.wsgi_writeout);
return uwsgi.wsgi_writeout;
clear:
Py_INCREF(Py_None);
return Py_None;
}
+179 -4
View File
@@ -2,10 +2,13 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_XML_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
extern struct uwsgi_server uwsgi;
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) {
xmlDoc *doc = NULL;
@@ -116,12 +119,184 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
}
/* We cannot free xml resources as the string pointer must be valid for all the server lifecycle */
//xmlFreeDoc (doc);
//xmlCleanupParser ();
/* We cannot free xml resources on the first round as the string pointer must be valid for all the server lifecycle */
if (!long_options) {
xmlFreeDoc (doc);
xmlCleanupParser ();
}
}
#endif
#ifdef UWSGI_XML_EXPAT
#include <expat.h>
int current_xmlnode ;
int current_xmlnode_has_arg ;
char *current_xmlnode_text ;
int current_xmlnode_text_len ;
void uwsgi_endElement(void *userData, const char *name) {
if (current_xmlnode && !current_xmlnode_has_arg) {
manage_opt(current_xmlnode, NULL);
}
else if (current_xmlnode_has_arg) {
if (!current_xmlnode_text_len) {
fprintf(stderr,"option %s requires an argument\n", name);
exit(1);
}
// HACK: use the first char of closing tag for nulling string
current_xmlnode_text[current_xmlnode_text_len] = 0;
manage_opt(current_xmlnode, current_xmlnode_text);
}
current_xmlnode = 0 ;
current_xmlnode_has_arg = 0 ;
current_xmlnode_text = NULL ;
current_xmlnode_text_len = 0 ;
}
void uwsgi_endApp(void *userData, const char *name) {}
void uwsgi_textHandler(void *userData, const char *s, int len) {
if (current_xmlnode && current_xmlnode_has_arg) {
current_xmlnode_text = (char *) s;
current_xmlnode_text_len = len;
}
}
void uwsgi_textApp(void *userData, const char *s, int len) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) userData ;
if (current_xmlnode) {
wsgi_req->wsgi_script = (char *) s;
wsgi_req->wsgi_script_len = len;
init_uwsgi_app(NULL, NULL);
current_xmlnode = 0;
}
};
void uwsgi_startApp(void *userData, const char *name, const char **attrs) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) userData ;
if (!strcmp(name, "app")) {
current_xmlnode = 0 ;
fprintf(stderr,"%s = %s\n", attrs[0], attrs[1]);
if (strcmp(attrs[0], "mountpoint")) {
fprintf(stderr,"invalid attribute for app tag. must be 'mountpoint'\n");
exit(1);
}
if (attrs[1]) {
wsgi_req->script_name = (char *) attrs[1];
wsgi_req->script_name_len = strlen(attrs[1]);
}
else {
wsgi_req->script_name = "/";
wsgi_req->script_name_len = 1;
}
}
else if (!strcmp(name, "script")) {
if (!wsgi_req->script_name_len) {
fprintf(stderr,"you have not specified an app mountpoint.\n");
exit(1);
}
current_xmlnode = 1 ;
}
}
void uwsgi_startElement(void *userData, const char *name, const char **attrs) {
struct option *long_options = (struct option *) userData;
struct option *lopt, *aopt;
lopt = long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(name, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
break;
}
else {
current_xmlnode = aopt->val;
current_xmlnode_has_arg = aopt->has_arg ;
break;
}
}
lopt++;
}
}
void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options) {
int xmlfd ;
size_t rlen ;
struct stat stat_buf;
char *xmlbuf ;
XML_Parser parser = XML_ParserCreate(NULL);
xmlfd = open(uwsgi.xml_config, O_RDONLY);
if (xmlfd < 0) {
perror("open()");
exit(1);
}
if (fstat(xmlfd, &stat_buf)) {
perror("fstat()");
exit(1);
}
xmlbuf = malloc(stat_buf.st_size);
if (!xmlbuf) {
perror("malloc()");
exit(1);
}
rlen = read(xmlfd, xmlbuf, stat_buf.st_size);
if (rlen != stat_buf.st_size) {
perror("read()");
exit(1);
}
close(xmlfd);
if (long_options) {
XML_SetUserData(parser, long_options);
XML_SetElementHandler(parser, uwsgi_startElement, uwsgi_endElement);
XML_SetCharacterDataHandler(parser, uwsgi_textHandler);
}
else {
XML_SetUserData(parser, wsgi_req);
XML_SetElementHandler(parser, uwsgi_startApp, uwsgi_endApp);
XML_SetCharacterDataHandler(parser, uwsgi_textApp);
}
if (!XML_Parse(parser, xmlbuf, stat_buf.st_size, 1)) {
fprintf(stderr, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int) XML_GetCurrentLineNumber(parser));
exit(1);
}
if (!long_options) {
XML_ParserFree(parser);
free(xmlbuf);
}
}
#endif
#else
#warning "*** XML configuration support is disabled ***"
#endif