Compare commits

...
41 Commits
Author SHA1 Message Date
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
42 changed files with 1824 additions and 1081 deletions
+5
View File
@@ -12,3 +12,8 @@ ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
+46 -1
View File
@@ -1,6 +1,51 @@
*** march 2011 ***
* 0.9.7-rc2 [20010309]
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
+325 -157
View File
@@ -2,198 +2,366 @@
extern struct uwsgi_server uwsgi;
int async_get_timeout() {
struct wsgi_request* wsgi_req ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
// do not wait if there are cores running
if (!uwsgi.async_running) return 0;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
// do not wait if there are timeout expired
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return -1;
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
void async_expire_timeouts() {
void runqueue_remove(struct uwsgi_async_request *u_request) {
struct wsgi_request* wsgi_req ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[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 ;
if (wsgi_req->async_waiting_fd != -1) {
event_queue_del_fd(uwsgi.async_queue, wsgi_req->async_waiting_fd);
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = -1;
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_waiting_fd_monitored = 0;
}
}
}
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request* wsgi_req;
int i ;
struct wsgi_request *wsgi_req;
// optimization
if (uwsgi.async_current_max > 1) {
if (uwsgi.wsgi_requests[uwsgi.async_current_max-1]->async_status == UWSGI_OK) {
//uwsgi_log("decreasing current max cores\n");
uwsgi.async_current_max--;
}
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i] ;
if (wsgi_req->async_status == UWSGI_OK) {
// optimization
if (i > uwsgi.async_current_max-1) uwsgi.async_current_max = i+1;
wsgi_req->async_id = i;
return wsgi_req ;
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct wsgi_request* wsgi_req = NULL ;
int core_id = uwsgi.async_waiting_fd_table[fd];
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (core_id == -1) return NULL;
if (fd < 0) return ;
wsgi_req = uwsgi.wsgi_requests[core_id];
//if (wsgi_req->async_waiting_fd_type == etype) return wsgi_req ;
return wsgi_req;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return NULL ;
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
}
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
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 ;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
void async_write_all(char *data, size_t len) {
struct wsgi_request *wsgi_req;
int i;
ssize_t rlen ;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
}
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
}
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// new request coming in
if (interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
continue;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
continue;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_simple_recv(uwsgi.wsgi_req)) {
continue;
}
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
}
else {
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
}
}
void async_unpause_all() {
struct wsgi_request *wsgi_req ;
int i;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop() {
struct wsgi_request *wsgi_req ;
int i ;
int ret;
uwsgi.async_running = -1 ;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->sigwait) {
uwsgi_log("waiting for signal\n");
continue;
}
else if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
ret = -1;
if (wsgi_req->async_waiting_fd_type == ASYNC_IN) {
ret = event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
else if (wsgi_req->async_waiting_fd_type == ASYNC_OUT) {
ret = event_queue_add_fd_write(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
if (ret < 0) {
// 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;
}
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = wsgi_req->async_id;
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
uwsgi.wsgi_req = wsgi_req ;
uwsgi_log("!!! getting new part\n");
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);;
wsgi_req->switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
}
}
}
return NULL;
+1 -1
View File
@@ -21,7 +21,7 @@ xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
locking = auto
event = auto
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+37 -16
View File
@@ -6,6 +6,9 @@ extern struct uwsgi_server uwsgi;
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
@@ -18,7 +21,7 @@ int event_queue_init() {
return port;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
@@ -28,6 +31,17 @@ int event_queue_del_fd(int eq, int fd) {
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
@@ -76,12 +90,11 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget;
int i;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout > 0) {
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
@@ -99,13 +112,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
pe = (port_event_t *) events;
for(i=0;i<nget;i++) {
if (pe[i].portev_source == PORT_SOURCE_FD) {
if (port_associate(eq, pe[i].portev_source, pe[i].portev_object, pe[i].portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
}
return nget;
}
@@ -144,7 +150,6 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
uwsgi_log("port event interesting_fd: %d\n", *interesting_fd);
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -160,6 +165,9 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
@@ -207,12 +215,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
@@ -298,6 +307,10 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
@@ -329,11 +342,11 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
@@ -516,7 +529,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
return -1;
}
@@ -831,3 +844,11 @@ struct uwsgi_timer *event_queue_ack_timer(int id) {
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+15
View File
@@ -6,6 +6,14 @@ extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
@@ -296,10 +304,17 @@ void uwsgi_ldap_config() {
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
+1 -1
View File
@@ -146,7 +146,7 @@ void uwsgi_lock_init(void *lock) {
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
exit(1);
}
-103
View File
@@ -87,106 +87,3 @@ void *simple_loop(void *arg1) {
//never here
return NULL;
}
#ifdef UWSGI_ASYNC
void complex_loop() {
int current_async_timeout = 0;
int i, j;
int interesting_fd;
struct wsgi_request *wsgi_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
current_async_timeout = async_get_timeout();
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, current_async_timeout, uwsgi.async_events, 64);
async_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
interesting_fd = event_queue_interesting_fd(uwsgi.async_events, i);
if ( interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
// async system is full !!!
goto cycle;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
continue;
}
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_recv(uwsgi.wsgi_req)) {
continue;
}
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
goto reqclear;
}
}
else if ( interesting_fd == uwsgi.sockets_poll[uwsgi.sockets_cnt].fd) {
// wake up cores waiting for signal
char byte;
if (read(uwsgi.sockets_poll[uwsgi.sockets_cnt].fd, &byte, 1) == 1) {
}
else {
uwsgi_error("read()");
}
for(j=0;j<uwsgi.async_current_max;j++) {
wsgi_req = uwsgi.wsgi_requests[j] ;
if (wsgi_req->sigwait) {
wsgi_req->signal_received = byte;
wsgi_req->sigwait = 0;
}
}
}
else {
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
uwsgi.wsgi_req->async_waiting_fd = -1;
uwsgi.wsgi_req->async_waiting_fd_monitored = 0;
uwsgi.wsgi_req->async_timeout = 0;
}
event_queue_del_fd(uwsgi.async_queue, interesting_fd);
}
}
cycle:
uwsgi.wsgi_req = async_loop();
if (uwsgi.wsgi_req == NULL)
continue;
uwsgi.wsgi_req->async_status = UWSGI_OK;
reqclear:
uwsgi_close_request(uwsgi.wsgi_req);
}
}
#endif
+18 -23
View File
@@ -337,6 +337,12 @@ void master_loop(char **argv, char **environ) {
}
}
if (uwsgi.queue_store && uwsgi.queue_filesize) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
@@ -950,6 +956,12 @@ void master_loop(char **argv, char **environ) {
}
}
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((master_cycles % uwsgi.queue_store_sync) == 0)) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
#endif
@@ -1040,7 +1052,9 @@ void master_loop(char **argv, char **environ) {
}
uwsgi_log( "DAMN ! process %d died :( trying respawn ...\n", diedpid);
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
uwsgi_log( "DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int)diedpid);
}
gettimeofday(&last_respawn, NULL);
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
uwsgi_log( "worker respawning too fast !!! i have to sleep a bit...\n");
@@ -1075,28 +1089,9 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("fork()");
}
else {
uwsgi_log( "Respawned uWSGI worker (new pid: %d)\n", pid);
//close(uwsgi.workers[uwsgi.mywid].pipe[1]);
//event_queue_add_fd_read(uwsgi.master_queue, uwsgi.workers[uwsgi.mywid].pipe[0]);
#ifdef UWSGI_SPOOLER
if (uwsgi.mywid <= 0 && diedpid != uwsgi.shared->spooler_pid) {
#else
if (uwsgi.mywid <= 0) {
#endif
#ifdef UWSGI_PROXY
// TODO if no gateway span the error !!!
if (diedpid != uwsgi.shared->proxy_pid) {
#endif
uwsgi_log( "warning the died pid was not in the workers list. Probably you hit a BUG of uWSGI\n");
#ifdef UWSGI_PROXY
}
#endif
}
}
}
uwsgi_log( "Respawned uWSGI worker %d (new pid: %d)\n", uwsgi.mywid, (int) pid);
}
}
}
}
+18 -4
View File
@@ -1,13 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
vacuum = true
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
mount = /app1=werkzeug.testapp:test_app
mount = /app2=config:/Users/roberta/uwsgi/my.ini
mount = /app3=pinaxsite/deploy/pinax.wsgi
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+1 -2
View File
@@ -345,8 +345,7 @@ void fastrouter_loop() {
break;
}
event_queue_del_fd(fr_queue, fr_session->instance_fd);
event_queue_add_fd_read(fr_queue, fr_session->instance_fd);
event_queue_fd_write_to_read(fr_queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
+86
View File
@@ -0,0 +1,86 @@
#include "../python/uwsgi_python.h"
#include <greenlet/greenlet.h>
extern struct uwsgi_server uwsgi;
struct ugreenlet {
int enabled;
PyObject *callable;
PyGreenlet *main;
PyGreenlet **gl;
} ugl;
struct option greenlet_options[] = {
{"greenlet", no_argument, &ugl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
inline static void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
uwsgi.wsgi_req->suspended = 1;
}
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
PyGreenlet_Switch(ugl.main, NULL, NULL);
uwsgi.wsgi_req = wsgi_req;
}
int greenlet_init() {
return 0;
}
void greenlet_init_apps(void) {
if (!ugl.enabled) {
return;
}
PyGreenlet_Import();
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
ugl.main = PyGreenlet_GetCurrent();
ugl.callable = PyCFunction_New(uwsgi_greenlet_request_method, NULL);
uwsgi_log("enabled greenlet engine\n");
uwsgi.schedule_to_main = greenlet_schedule_to_main;
uwsgi.schedule_to_req = greenlet_schedule_to_req;
return;
}
struct uwsgi_plugin greenlet_plugin = {
.name = "greenlet",
.init = greenlet_init,
.init_apps = greenlet_init_apps,
.options = greenlet_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='greenlet'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['greenlet']
+43
View File
@@ -501,6 +501,9 @@ void http_loop() {
if (interesting_fd == uhttp.server) {
new_connection = accept(uhttp.server, (struct sockaddr *) &uhttp_addr, &uhttp_addr_len);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp.server);
#endif
if (new_connection < 0) {
continue;
}
@@ -531,6 +534,9 @@ void http_loop() {
}
else if (interesting_fd == uhttp_subserver) {
len = recv(uhttp_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_subserver);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
@@ -555,12 +561,16 @@ void http_loop() {
case HTTP_STATUS_RECV:
len = recv(uhttp_session->fd, uhttp_session->buffer + uhttp_session->h_pos, UMAX16-uhttp_session->h_pos, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
#endif
if (len <= 0) {
uwsgi_error("recv()");
close_session(uhttp_table, uhttp_session);
break;
}
uhttp_session->h_pos += len;
for(j=0;j<len;j++) {
@@ -726,11 +736,32 @@ void http_loop() {
break;
}
#ifdef __sun__
if (uhttp_session->iov_len > IOV_MAX) {
int remains = uhttp_session->iov_len;
int iov_len;
while(remains) {
if (remains > IOV_MAX) {
iov_len = IOV_MAX;
}
else {
iov_len = remains;
}
if (writev(uhttp_session->instance_fd, uhttp_session->iov + (uhttp_session->iov_len-remains), iov_len) <= 0) {
uwsgi_error("writev()");
close_session(uhttp_table, uhttp_session);
break;
}
remains -= iov_len;
}
}
#else
if (writev(uhttp_session->instance_fd, uhttp_session->iov, uhttp_session->iov_len) <= 0) {
uwsgi_error("writev()");
close_session(uhttp_table, uhttp_session);
break;
}
#endif
event_queue_fd_write_to_read(uhttp_queue, uhttp_session->instance_fd);
uhttp_session->status = HTTP_STATUS_RESPONSE;
@@ -743,6 +774,9 @@ void http_loop() {
// data from instance
if (interesting_fd == uhttp_session->instance_fd) {
len = recv(uhttp_session->instance_fd, bbuf, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->instance_fd);
#endif
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close_session(uhttp_table, uhttp_session);
@@ -768,6 +802,9 @@ void http_loop() {
//uwsgi_log("receiving body...\n");
len = recv(uhttp_session->fd, bbuf, UMAX16, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
#endif
if (len <= 0) {
if (len < 0) uwsgi_error("recv()");
close(uhttp_session->fd);
@@ -842,6 +879,11 @@ int http_init() {
return 0;
}
struct uwsgi_help_item http_help[] = {
{ "http-to <addr>", "forward http requests to uwsgi instance bound at <addr>"},
{ 0, 0 }
};
int http_opt(int i, char *optarg) {
@@ -894,6 +936,7 @@ struct uwsgi_plugin http_plugin = {
.options = http_options,
.manage_opt = http_opt,
.help = http_help,
.init = http_init,
};
+1
View File
@@ -1,3 +1,4 @@
#undef __USE_GNU
#include "../../uwsgi.h"
#include <EXTERN.h>
+1 -1
View File
@@ -102,7 +102,7 @@ void uwsgi_psgi_app() {
if (uperl.psgi) {
uperl.fd = open(uperl.psgi, O_RDONLY);
if (uperl.fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(uperl.psgi);
exit(1);
}
+8
View File
@@ -149,6 +149,14 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->interpreter = up.main_thread;
}
if (wsgi_req->touch_reload_len) {
struct stat trst;
char *touch_reload = uwsgi_strncopy(wsgi_req->touch_reload, wsgi_req->touch_reload_len);
if (!stat(touch_reload, &trst)) {
wi->touch_reload = touch_reload;
wi->touch_reload_mtime = trst.st_mtime;
}
}
wi->callable = up.loaders[loader](arg1);
+89 -33
View File
@@ -35,6 +35,29 @@ struct option uwsgi_python_options[] = {
{0, 0, 0, 0},
};
struct uwsgi_help_item uwsgi_python_help[] = {
{"module <module>" ,"name of python config module"},
{"optimize <n>", "set python optimization level to <n>"},
{"home <path>", "set python home/virtualenv"},
{"pyhome <path>", "set python home/virtualenv"},
{"virtualenv <path>", "set python home/virtualenv"},
{"venv <path>", "set python home/virtualenv"},
{"callable <callable>", "set the callable (default 'application')"},
{"paste <config:/egg:>", "load applications using paste.deploy.loadapp()"},
{"pythonpath <dir>", "add <dir> to PYTHONPATH"},
{"python-path <dir>", "add <dir> to PYTHONPATH"},
{"pp <dir>", "add <dir> to PYTHONPATH"},
{"pyargv <args>", "assign args to python sys.argv"},
{"wsgi-file <file>", "load the <file> wsgi file"},
{"file <file>", "use python file instead of python module for configuration"},
{"eval <code>", "evaluate code for app configuration"},
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
{ 0, 0},
};
/* this routine will be called after each fork to reinitialize the various locks */
void uwsgi_python_pthread_prepare(void) {
pthread_mutex_lock(&up.lock_pyloaders);
@@ -107,6 +130,9 @@ int uwsgi_python_init() {
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
// add the hacky modifier1 30
uwsgi.p[30]->request = uwsgi.p[0]->request;
return 1;
}
@@ -159,36 +185,52 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
char *real_filename = filename;
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
}
if (strncmp(filename, "http://", 7)) {
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
}
if (S_ISDIR(pystat.st_mode)) {
is_a_package = 1;
fclose(pyfile);
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_error("fopen()");
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
}
}
py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
}
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
}
fclose(pyfile);
if (S_ISDIR(pystat.st_mode)) {
is_a_package = 1;
fclose(pyfile);
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
if (!pyfile) {
uwsgi_error_open(real_filename);
exit(1);
}
}
py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
}
fclose(pyfile);
}
else {
int pycontent_size = 0;
char *pycontent = uwsgi_open_and_read(filename, &pycontent_size, 1, NULL);
if (pycontent) {
py_file_node = PyParser_SimpleParseString(pycontent, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse url %s\n", real_filename);
exit(1);
}
}
}
py_compiled_node = (PyObject *) PyNode_Compile(py_file_node, real_filename);
@@ -690,6 +732,11 @@ int uwsgi_python_mount_app(char *mountpoint, char *app) {
void uwsgi_python_init_apps() {
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
}
init_pyargv();
#ifdef UWSGI_MINTERPRETERS
init_uwsgi_embedded_module();
@@ -821,9 +868,14 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
uwsgi_log("suspending python\n");
up.current_recursion_depth = tstate->recursion_depth;
up.current_frame = tstate->frame;
if (wsgi_req) {
up.current_recursion_depth[wsgi_req->async_id] = tstate->recursion_depth;
up.current_frame[wsgi_req->async_id] = tstate->frame;
}
else {
up.current_main_recursion_depth = tstate->recursion_depth;
up.current_main_frame = tstate->frame;
}
}
@@ -938,9 +990,14 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyThreadState *tstate = PyThreadState_GET();
uwsgi_log("resuming python\n");
tstate->recursion_depth = up.current_recursion_depth;
tstate->frame = up.current_frame;
if (wsgi_req) {
tstate->recursion_depth = up.current_recursion_depth[wsgi_req->async_id];
tstate->frame = up.current_frame[wsgi_req->async_id];
}
else {
tstate->recursion_depth = up.current_main_recursion_depth;
tstate->frame = up.current_main_frame;
}
}
@@ -972,8 +1029,7 @@ struct uwsgi_plugin python_plugin = {
.rpc = uwsgi_python_rpc,
.spooler = uwsgi_python_spooler,
/*
.help = uwsgi_python_help,
*/
.help = uwsgi_python_help,
};
-1
View File
@@ -5,7 +5,6 @@ extern struct uwsgi_python up;
int manage_python_response(struct wsgi_request *wsgi_req) {
// use standard WSGI response parse
wsgi_req->switches++;
return uwsgi_response_subhandler_wsgi(wsgi_req);
}
+61 -7
View File
@@ -813,16 +813,16 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_async_sleep(PyObject * self, PyObject * args) {
float timeout;
time_t sec_timeout;
int sec_timeout;
if (!PyArg_ParseTuple(args, "f:async_sleep", &timeout)) {
return NULL;
}
sec_timeout = (time_t) timeout;
sec_timeout = (int) timeout;
if (sec_timeout > 0) {
async_set_timeout(uwsgi.wsgi_req, sec_timeout);
async_add_timeout(uwsgi.wsgi_req, sec_timeout);
}
return PyString_FromString("");
@@ -2087,7 +2087,7 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
goto clear;
}
@@ -2242,7 +2242,7 @@ PyObject *py_uwsgi_suspend(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi.schedule_to_main(wsgi_req);
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
Py_INCREF(Py_True);
return Py_True;
@@ -2528,7 +2528,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
}
if (uwsgi.queue_size) {
uwsgi_log("locking queue\n");
uwsgi_wlock(uwsgi.queue_lock);
if (uwsgi_queue_push(message, msglen)) {
Py_INCREF(Py_True);
@@ -2539,7 +2538,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
res = Py_None;
}
uwsgi_rwunlock(uwsgi.queue_lock);
uwsgi_log("unlocked queue\n");
return res;
}
@@ -2611,6 +2609,56 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
long num = 0;
uint64_t size = 0;
char *message;
PyObject *res, *zero;
uint64_t base;
if (!PyArg_ParseTuple(args, "l:queue_last", &num)) {
return NULL;
}
if (uwsgi.queue_size) {
res = PyList_New(0);
uwsgi_rlock(uwsgi.queue_lock);
if (uwsgi.shared->queue_pos > 0) {
base = uwsgi.shared->queue_pos-1;
}
else {
base = uwsgi.queue_size-1;
}
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
while(num) {
message = uwsgi_queue_get(base, &size);
if (message && size) {
zero = PyString_FromStringAndSize(message, size);
PyList_Append(res, zero);
Py_DECREF(zero);
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
if (base > 0) {
base--;
}
else {
base = uwsgi.queue_size-1;
}
num--;
}
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
char *key;
@@ -2641,6 +2689,11 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
#endif
uwsgi_rlock(uwsgi.cache_lock);
value = uwsgi_cache_get(key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.cache_lock);
Py_INCREF(Py_None);
return Py_None;
}
res = PyString_FromStringAndSize(value, valsize);
#ifdef UWSGI_DEBUG
gettimeofday(&tv2, NULL);
@@ -2671,6 +2724,7 @@ static PyMethodDef uwsgi_cache_methods[] = {
static PyMethodDef uwsgi_queue_methods[] = {
{"queue_get", py_uwsgi_queue_get, METH_VARARGS, ""},
{"queue_last", py_uwsgi_queue_last, METH_VARARGS, ""},
{"queue_push", py_uwsgi_queue_push, METH_VARARGS, ""},
{"queue_pull", py_uwsgi_queue_pull, METH_VARARGS, ""},
{"queue_slot", py_uwsgi_queue_slot, METH_VARARGS, ""},
+6 -22
View File
@@ -1,6 +1,7 @@
#include "../../uwsgi.h"
#include <Python.h>
#include <frameobject.h>
#define MAX_PYTHONPATH 64
#define MAX_PYMODULE_ALIAS 64
@@ -13,10 +14,6 @@
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
#endif
@@ -110,8 +107,11 @@ struct uwsgi_python {
int ignore_script_name;
int catch_exceptions;
int current_recursion_depth;
struct _frame* current_frame;
int *current_recursion_depth;
struct _frame **current_frame;
int current_main_recursion_depth;
struct _frame *current_main_frame;
void (*swap_ts)(struct wsgi_request *, struct uwsgi_app *);
void (*reset_ts)(struct wsgi_request *, struct uwsgi_app *);
@@ -157,10 +157,6 @@ PyObject *py_eventfd_read(PyObject *, PyObject *);
PyObject *py_eventfd_write(PyObject *, PyObject *);
#ifdef UWSGI_STACKLESS
PyObject *py_uwsgi_stackless(PyObject *, PyObject *);
#endif
int manage_python_response(struct wsgi_request *);
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
@@ -174,18 +170,6 @@ ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
PyObject *py_uwsgi_write(PyObject *, PyObject *);
PyObject *py_uwsgi_spit(PyObject *, PyObject *);
#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(void);
void stackless_loop(void);
#endif
void init_pyargv(void);
#ifdef UWSGI_WEB3
+6 -4
View File
@@ -20,10 +20,12 @@ else:
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
LIBS.append('-lpython' + uver)
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
+39 -39
View File
@@ -17,9 +17,8 @@ PyObject *uwsgi_Input_iter(PyObject * self) {
PyObject *uwsgi_Input_next(PyObject * self) {
PyErr_SetNone(PyExc_StopIteration);
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input __iter__() is not implemented");
return NULL;
}
static void uwsgi_Input_free(uwsgi_Input *self) {
@@ -29,7 +28,7 @@ static void uwsgi_Input_free(uwsgi_Input *self) {
static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
long len = 0;
size_t remains, chunk_size;
size_t remains;
ssize_t rlen;
char *tmp_buf;
int fd;
@@ -75,27 +74,22 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
return res;
}
chunk_size = remains;
tmp_buf = uwsgi_malloc(remains);
while(remains) {
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
return PyErr_Format(PyExc_ValueError, "error waiting for wsgi.input data");
}
rlen = read(fd, tmp_buf + self->pos, remains);
if (rlen < 0) {
free(tmp_buf);
return PyErr_Format(PyExc_ValueError, "error reading wsgi.input data");
}
if (!rlen) break;
self->pos += rlen;
remains -= rlen;
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
}
res = PyString_FromStringAndSize(tmp_buf, chunk_size);
rlen = read(fd, tmp_buf, remains);
if (rlen < 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
self->pos += rlen;
res = PyString_FromStringAndSize(tmp_buf, rlen);
free(tmp_buf);
return res;
@@ -103,17 +97,19 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
static PyObject *uwsgi_Input_readline(uwsgi_Input *self, PyObject *args) {
return NULL;
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input readline() is not implemented");
}
static PyObject *uwsgi_Input_readlines(uwsgi_Input *self, PyObject *args) {
return NULL;
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input readlines() is not implemented");
}
static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef uwsgi_Input_methods[] = {
@@ -196,12 +192,7 @@ PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd;
wsgi_req->async_waiting_fd_type = ASYNC_IN;
wsgi_req->async_waiting_fd_monitored = 0;
if (timeout > 0) {
wsgi_req->async_timeout = time(NULL) + timeout;
}
async_add_fd_read(wsgi_req, fd, timeout);
}
return PyString_FromString("");
@@ -218,12 +209,7 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd;
wsgi_req->async_waiting_fd_type = ASYNC_OUT;
wsgi_req->async_waiting_fd_monitored = 0;
if (timeout > 0) {
wsgi_req->async_timeout = time(NULL) + timeout;
}
async_add_fd_write(wsgi_req, fd, timeout);
}
return PyString_FromString("");
@@ -249,13 +235,21 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
if (wsgi_req->async_timed_out) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0;
wsgi_req->async_timed_out = 0;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
if (wsgi_req->async_ready_fd) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.ready_fd", PyInt_FromLong(wsgi_req->async_last_ready_fd));
wsgi_req->async_ready_fd = 0;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.ready_fd", Py_None);
}
return manage_python_response(wsgi_req);
}
#endif
@@ -268,7 +262,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSGI request. skip.\n");
return -1;
}
@@ -435,6 +428,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
goto clear;
}
}
else {
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
}
}
else {
// read to disk if post_cl > post_buffering
@@ -478,11 +474,15 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
while (wi->response_subhandler(wsgi_req) != UWSGI_OK) {
wsgi_req->switches++;
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
else {
#endif
wsgi_req->switches++;
#ifdef UWSGI_ASYNC
}
#endif
}
+2 -2
View File
@@ -68,7 +68,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[2].iov_len;
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->status = uwsgi_str3_num(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[3].iov_len;
@@ -87,7 +87,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[1].iov_len;
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
wsgi_req->status = uwsgi_str3_num(wsgi_req->hvec[1].iov_base);
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[2].iov_len;
-12
View File
@@ -225,18 +225,6 @@ clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
-3
View File
@@ -94,14 +94,12 @@ VALUE protected_fiber_loop() {
if (!wsgi_req) goto cycle;
uwsgi_log("request passed to fiber core %d\n", wsgi_req->async_id);
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
wsgi_req = find_wsgi_req_by_fd((int)uwsgi.async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
@@ -116,7 +114,6 @@ cycle:
//uwsgi_log("resuming fiber %d %p\n", current, fiber_list[current]);
uwsgi.wsgi_req = uwsgi.wsgi_requests[current];
uwsgi.wsgi_req->switches++;
if (uwsgi.wsgi_req->async_status != UWSGI_ACCEPTING) {
uwsgi_log("passing control to fiber %d\n", current);
rb_fiber_resume(fiber_list[current], 0, NULL);
+84
View File
@@ -0,0 +1,84 @@
#include "../python/uwsgi_python.h"
#include <stackless_api.h>
extern struct uwsgi_server uwsgi;
struct ustackless {
int enabled;
PyObject *callable;
PyTaskletObject **sl;
} usl;
struct option stackless_options[] = {
{"stackless", no_argument, &usl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_stackless_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(usl.sl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_stackless_request_method[] = {{"uwsgi_stackless_request", py_uwsgi_stackless_request, METH_VARARGS, ""}};
inline static void stackless_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
usl.sl[id] = PyTasklet_New(NULL, usl.callable);
PyObject *args = PyTuple_New(0);
PyTasklet_Setup(usl.sl[id], args, NULL);
Py_DECREF(args);
uwsgi.wsgi_req->suspended = 1;
}
PyTasklet_Run(usl.sl[id]);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void stackless_schedule_to_main(struct wsgi_request *wsgi_req) {
PyStackless_Schedule(Py_None, 1);
uwsgi.wsgi_req = wsgi_req;
}
int stackless_init() {
return 0;
}
void stackless_init_apps(void) {
if (!usl.enabled) {
return;
}
usl.sl = uwsgi_malloc( sizeof(PyTaskletObject *) * uwsgi.async );
usl.callable = PyCFunction_New(uwsgi_stackless_request_method, NULL);
uwsgi_log("enabled stackless engine\n");
uwsgi.schedule_to_main = stackless_schedule_to_main;
uwsgi.schedule_to_req = stackless_schedule_to_req;
return;
}
struct uwsgi_plugin stackless_plugin = {
.name = "stackless",
.init = stackless_init,
.init_apps = stackless_init_apps,
.options = stackless_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='stackless'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['stackless']
+41 -274
View File
@@ -12,7 +12,7 @@ struct uwsgi_ugreen {
int ugreen;
int stackpages;
ucontext_t main;
ucontext_t **contexts;
ucontext_t *contexts;
size_t u_stack_size;
} ug;
@@ -27,165 +27,60 @@ struct option ugreen_options[] = {
{ 0, 0, 0, 0 }
};
void u_green_loop(void);
void u_green_write_all(char *data, size_t len) {
struct wsgi_request *wsgi_req;
int i;
ssize_t rlen;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
// mark core as plagued
wsgi_req->async_plagued = 1;
}
else {
wsgi_req->response_size += rlen;
}
}
}
void u_green_request() {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
}
void u_green_unpause_all() {
inline static void u_green_schedule_to_req() {
struct wsgi_request *wsgi_req;
int i;
int id = uwsgi.wsgi_req->async_id;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
if (!uwsgi.wsgi_req->suspended) {
ug.contexts[id].uc_link = &ug.main;
makecontext(&ug.contexts[id], u_green_request, 0);
uwsgi.wsgi_req->suspended = 1;
}
}
if (uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->suspend(NULL);
}
swapcontext(&ug.main, &ug.contexts[id] );
static int u_green_blocking() {
struct wsgi_request* wsgi_req;
int i;
if (uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->resume) {
uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->resume(NULL);
}
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[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;
}
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
return -1;
}
inline static void u_green_schedule_to_main(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
uwsgi_log("uGreen EXITING TO MAIN\n");
swapcontext(ug.contexts[wsgi_req->async_id], &ug.main);
swapcontext(&ug.contexts[wsgi_req->async_id], &ug.main);
uwsgi_log("uGreen RETURNED FROM MAIN\n");
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
}
}
inline static void u_green_schedule_to_req(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
uwsgi.wsgi_req = wsgi_req;
uwsgi_log("SWAPCONTEXT to %p\n", ug.contexts[wsgi_req->async_id]);
//wsgi_req->async_switches++;
swapcontext(&ug.main, ug.contexts[wsgi_req->async_id] );
uwsgi_log("RESUMED\n");
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
}
}
void u_green_wait_for_fd(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(wsgi_req);
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;
}
static void u_green_request(struct wsgi_request *wsgi_req, int async_id) {
uwsgi_log("request handler args %p %d\n", wsgi_req, async_id);
for(;;) {
uwsgi_log("accept()\n");
wsgi_req_setup(wsgi_req, async_id);
wsgi_req->async_status = UWSGI_ACCEPTING;
u_green_schedule_to_main(wsgi_req);
if (wsgi_req_accept(wsgi_req)) {
continue;
}
uwsgi_log("REQUEST ACCEPTED\n");
wsgi_req->async_status = UWSGI_OK;
// check here
//u_green_schedule_to_main(wsgi_req);
if (wsgi_req_recv(wsgi_req)) {
continue;
}
while(wsgi_req->async_status == UWSGI_AGAIN) {
u_green_schedule_to_main(wsgi_req);
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
}
u_green_schedule_to_main(wsgi_req);
uwsgi_close_request(wsgi_req);
}
}
int u_green_init() {
struct wsgi_request *wsgi_req;
static int i;
volatile int i;
if (!ug.ugreen) {
return 0;
}
ug.u_stack_size = UGREEN_DEFAULT_STACKSIZE;
@@ -196,168 +91,38 @@ int u_green_init() {
uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi.async, (unsigned long) ug.u_stack_size, (unsigned long) ug.u_stack_size/1024);
ug.contexts = malloc( sizeof(ucontext_t*) * uwsgi.async);
if (!ug.contexts) {
uwsgi_error("malloc()\n");
exit(1);
}
ug.contexts = uwsgi_malloc( sizeof(ucontext_t) * uwsgi.async);
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
ug.contexts[i] = malloc( sizeof(ucontext_t) );
if (!ug.contexts[i]) {
uwsgi_error("malloc()");
exit(1);
}
getcontext(ug.contexts[i]);
ug.contexts[i]->uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
getcontext(&ug.contexts[i]);
if (!ug.contexts[i]->uc_stack.ss_sp) {
ug.contexts[i].uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
if (!ug.contexts[i].uc_stack.ss_sp) {
uwsgi_error("mmap()");
exit(1);
}
// set guard pages for stack
if (mprotect(ug.contexts[i]->uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) {
if (mprotect(ug.contexts[i].uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
if (mprotect(ug.contexts[i]->uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) {
if (mprotect(ug.contexts[i].uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
ug.contexts[i]->uc_stack.ss_size = ug.u_stack_size;
ug.contexts[i].uc_stack.ss_size = ug.u_stack_size;
ug.contexts[i]->uc_link = NULL;
makecontext(ug.contexts[i], (void(*)(void)) u_green_request, 2, wsgi_req, i);
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
uwsgi_log("wsgi_req %d %d %p\n", wsgi_req->async_id, wsgi_req->async_status, ug.contexts[i]);
}
uwsgi_register_loop("ugreen", u_green_loop);
return 0;
}
void u_green_expire_timeouts() {
struct wsgi_request* wsgi_req;
int i;
time_t deadline = time(NULL);
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
}
}
}
static int u_green_get_timeout() {
struct wsgi_request* wsgi_req;
int i;
time_t curtime, tdelta = 0;
int ret = 0;
if (!uwsgi.async_running) return 0;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout;
}
}
}
curtime = time(NULL);
ret = tdelta - curtime;
if (ret > 0) {
return ret;
}
return 0;
}
void u_green_loop() {
struct wsgi_request *wsgi_req;
int i, current = 0, timeout;
for(i=0;i<uwsgi.async;i++){
wsgi_req = uwsgi.wsgi_requests[i];
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
}
uwsgi.schedule_to_main = u_green_schedule_to_main;
uwsgi.schedule_to_req = u_green_schedule_to_req;
uwsgi_log("FFAR: %p\n", find_first_accepting_wsgi_req());
while(uwsgi.workers[uwsgi.mywid].manage_next_request) {
//uwsgi_log("i am uGreen...\n");
uwsgi.async_running = u_green_blocking();
timeout = u_green_get_timeout();
uwsgi.async_nevents = async_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running, timeout);
u_green_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
uwsgi_log("received I/O event on fd %d\n", uwsgi.async_events[i].ASYNC_FD);
if ( (int) uwsgi.async_events[i].ASYNC_FD == uwsgi.sockets[0].fd) {
wsgi_req = find_first_accepting_wsgi_req();
uwsgi_log("found wsgireq at %p\n", wsgi_req);
if (!wsgi_req) goto cycle;
uwsgi_log("found %d\n", wsgi_req->async_id);
u_green_schedule_to_req(wsgi_req);
uwsgi_log("ooops\n");
}
else {
uwsgi_log("fd ready\n");
wsgi_req = find_wsgi_req_by_fd(uwsgi.async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
u_green_schedule_to_req(wsgi_req);
}
else {
async_del(uwsgi.async_queue, uwsgi.async_events[i].ASYNC_FD, uwsgi.async_events[i].ASYNC_EV);
}
}
}
cycle:
wsgi_req = uwsgi.wsgi_requests[current];
uwsgi_log("schedule %d %d ?\n", current, wsgi_req->async_status);
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
uwsgi_log("schedule !\n");
u_green_schedule_to_req(wsgi_req);
}
current++;
if (current >= uwsgi.async) current = 0;
}
return 0;
}
@@ -376,4 +141,6 @@ struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
.init = u_green_init,
.options = ugreen_options,
.manage_opt = uwsgi_ugreen_manage_opt,
};
+177 -9
View File
@@ -16,6 +16,112 @@ static size_t get_content_length(char *buf, uint16_t size) {
return val;
}
void set_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
struct tm *hdtm = gmtime(&t);
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
week[hdtm->tm_wday], hdtm->tm_mday,
months[hdtm->tm_mon], hdtm->tm_year+1900,
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
}
// only RFC 1123 is supported
time_t parse_http_date(char *date, uint16_t len) {
struct tm hdtm;
if (len != 29 && date[3] != ',') return 0;
hdtm.tm_mday = uwsgi_str2_num(date+5);
switch(date[8]) {
case 'J':
if (date[9] == 'a') {
hdtm.tm_mon = 0;
break;
}
if (date[9] == 'u') {
if (date[10] == 'n') {
hdtm.tm_mon = 5;
break;
}
if (date[10] == 'l') {
hdtm.tm_mon = 6;
break;
}
return 0;
}
return 0;
case 'F':
hdtm.tm_mon = 1;
break;
case 'M':
if (date[9] != 'a') return 0;
if (date[10] == 'r') {
hdtm.tm_mon = 2;
break;
}
if (date[10] == 'y') {
hdtm.tm_mon = 4;
break;
}
return 0;
case 'A':
if (date[10] == 'r') {
hdtm.tm_mon = 3;
break;
}
if (date[10] == 'g') {
hdtm.tm_mon = 7;
break;
}
return 0;
case 'S':
hdtm.tm_mon = 8;
break;
case 'O':
hdtm.tm_mon = 9;
break;
case 'N':
hdtm.tm_mon = 10;
case 'D':
hdtm.tm_mon = 11;
break;
default:
return 0;
}
hdtm.tm_year = uwsgi_str4_num(date+12)-1900;
hdtm.tm_hour = uwsgi_str2_num(date+17);
hdtm.tm_min = uwsgi_str2_num(date+20);
hdtm.tm_sec = uwsgi_str2_num(date+23);
return timegm(&hdtm);
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
@@ -346,21 +452,27 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
return 0;
}
// older OSX versions make mess with CMSG_FIRSTHDR
#ifdef __APPLE__
if (!msg.msg_controllen) return 1;
#endif
cmsg = CMSG_FIRSTHDR (&msg);
while(cmsg != NULL) {
if (cmsg->cmsg_len != CMSG_LEN (sizeof (int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) continue;
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type && SCM_RIGHTS) {
// upgrade connection to the new socket
#ifdef UWSGI_DEBUG
uwsgi_log("upgrading fd %d to ", upoll->fd);
uwsgi_log("upgrading fd %d to ", upoll->fd);
#endif
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
#ifdef UWSGI_DEBUG
uwsgi_log("%d\n", upoll->fd);
uwsgi_log("%d\n", upoll->fd);
#endif
}
cmsg = CMSG_NXTHDR (&msg, cmsg);
}
@@ -516,6 +628,18 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->file = ptrbuf;
wsgi_req->file_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
wsgi_req->touch_reload_len = strsize;
}
else if (uwsgi.cache_max_items > 0 && !uwsgi_strncmp("UWSGI_CACHE_GET", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->cache_get = ptrbuf;
wsgi_req->cache_get_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_SETENV", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
char *env_value = memchr(ptrbuf, '=', strsize);
if (env_value) {
@@ -545,6 +669,10 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
else if (!uwsgi_strncmp("HTTP_IF_MODIFIED_SINCE", 22, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->if_modified_since = ptrbuf;
wsgi_req->if_modified_since_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
}
@@ -570,19 +698,44 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
ptrbuf += strsize;
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
// check if data are available in the local cache
if (wsgi_req->cache_get_len > 0) {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size);
if (cache_value && cache_value_size > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, cache_value, cache_value_size);
wsgi_req->status = -1;
return -1;
}
}
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 &&
wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size);
if (cache_value && cache_value_size > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, cache_value, cache_value_size);
wsgi_req->status = -1;
return -1;
}
}
if (uwsgi.manage_script_name) {
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
@@ -626,6 +779,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
}
// check i fa file name uwsgi.check_static+env['PATH_INFO'] exists
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
struct stat st;
char *filename = uwsgi_concat2n(uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len);
@@ -633,13 +787,27 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
uwsgi_log("checking for %s\n", filename);
#endif
if (!stat(filename, &st)) {
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 304 Not Modified\r\n\r\n", 21);
return -1;
}
}
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("file %s found\n", filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->sendfile_fd = open(filename, O_RDONLY);
wsgi_req->response_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->response_size += write(wsgi_req->poll.fd, " 200 OK\r\n\r\n", 11);
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 200 OK\r\n", 9);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
wsgi_req->header_cnt = 1;
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
wsgi_req->status = 200;
free(filename);
+21
View File
@@ -19,6 +19,25 @@ char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
}
void uwsgi_queue_fix() {
uint64_t i;
char *value;
uint64_t size;
for(i=0;i< uwsgi.queue_size;i++) {
// valid record ?
value = uwsgi_queue_get(i, &size);
if (value && size) {
uwsgi.shared->queue_pos++;
}
else {
return;
}
}
}
char *uwsgi_queue_pop(uint64_t *size) {
struct uwsgi_queue_item *uqi;
@@ -70,6 +89,8 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
uqi = (struct uwsgi_queue_item *) ptr;
+21 -8
View File
@@ -8,25 +8,38 @@ from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
def patch_bin_path(cmd, conf):
bin_name = conf.get('bin_name')
try:
if not os.path.exists(cmd.install_scripts):
os.makedirs(cmd.install_scripts)
if not os.path.isabs(bin_name):
print('Patching "bin_name" to properly install_scripts dir')
conf.set('bin_name', os.path.join(cmd.install_scripts, conf.get('bin_name')))
except:
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
class uWSGIBuilder(build_ext):
def run(self):
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution for 0.9.6
# hack, hack and still hack. We need to find a solution...
if self.record:
record_file = open(self.record,'w')
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIDistribution(Distribution):
@@ -38,7 +51,7 @@ class uWSGIDistribution(Distribution):
setup(name='uWSGI',
version='0.9.7-dev',
version='0.9.7.1',
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
+3 -3
View File
@@ -53,7 +53,7 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
}
@@ -135,7 +135,7 @@ void spooler() {
nullfd = open("/dev/null", O_RDONLY);
if (nullfd < 0) {
uwsgi_error("open()");
uwsgi_error_open("/dev/null");
exit(1);
}
@@ -164,7 +164,7 @@ void spooler() {
spool_fd = open(dp->d_name, O_RDONLY);
if (spool_fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(dp->d_name);
continue;
}
-137
View File
@@ -1,137 +0,0 @@
#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;
//uwsgi_log("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) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->stackless_table[i] = malloc(sizeof(struct stackless_req));
if (!uwsgi->stackless_table[i]) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
uwsgi_log("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);
}
uwsgi_log("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
uwsgi_log("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 );
/*
uwsgi_log("done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
uwsgi_log("re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
uwsgi_log("recycle\n");
*/
}
}
#endif
+25 -29
View File
@@ -1,47 +1,43 @@
import socket
import select
import errno
import uwsgi
def send_request(env, client):
client.setblocking(1)
uwsgi.send(client, b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
# test for suspend/resume
uwsgi.suspend()
uwsgi.send(client, b"Host: www.google.it\r\n\r\n")
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 uwsgi.wait_fd_read(client, 2)
if env['x-wsgiorg.fdevent.timeout']:
return
buf = uwsgi.recv(client, 4096)
if buf:
yield buf
else:
break
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
c = uwsgi.async_connect('74.125.232.115:80')
#env['x-wsgiorg.fdevent.readable'] = lambda fd,t: ""
#env['x-wsgiorg.fdevent.writable'] = lambda fd,t: ""
# wait for connection
yield uwsgi.wait_fd_write(c, 2)
if env['x-wsgiorg.fdevent.timeout']:
uwsgi.close(c)
raise StopIteration
#yield ""
print "opening socket"
c = s.connect_ex(('www.google.it', 80))
if c == errno.EINPROGRESS:
print "yielding"
yield env['x-wsgiorg.fdevent.writable'](s.fileno(), 10)
print "waiting for fd write"
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
if uwsgi.is_connected(c):
for r in send_request(env, c):
yield r
else:
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
uwsgi.close(c)
+1
View File
@@ -1,4 +1,5 @@
import sys
import uwsgi
content_type = 'image/png'
filename = 'logo_uWSGI.png'
+86 -25
View File
@@ -70,6 +70,12 @@ void daemonize(char *logfile) {
pid_t pid;
int fdin;
// do not daemonize under emperor
if (uwsgi.has_emperor) {
logto(logfile);
return;
}
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
@@ -104,7 +110,7 @@ void daemonize(char *logfile) {
fdin = open("/dev/null", O_RDWR);
if (fdin < 0) {
uwsgi_error("open()");
uwsgi_error_open("/dev/null");
exit(1);
}
@@ -155,7 +161,7 @@ void logto(char *logfile) {
#endif
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(logfile);
exit(1);
}
#ifdef UWSGI_UDP
@@ -269,7 +275,7 @@ void uwsgi_as_root() {
cgroup_taskfile = uwsgi_concat2(uwsgi.cgroup, "/tasks");
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error("fopen");
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%d\n", (int) getpid()) < 0) {
@@ -295,7 +301,7 @@ void uwsgi_as_root() {
cgroup_taskfile = uwsgi_concat3(uwsgi.cgroup, "/", uwsgi.cgroup_opt[i]);
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error("fopen");
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
@@ -338,6 +344,13 @@ void uwsgi_as_root() {
exit(1);
}
}
if (uwsgi.logfile_chown) {
if (fchown(2, uwsgi.uid, uwsgi.gid)) {
uwsgi_error("fchown()");
exit(1);
}
}
if (uwsgi.gid) {
if (!uwsgi.master_as_root) uwsgi_log("setgid() to %d\n", uwsgi.gid);
if (setgid(uwsgi.gid)) {
@@ -376,6 +389,7 @@ void uwsgi_as_root() {
void uwsgi_close_request(struct wsgi_request *wsgi_req) {
int waitpid_status;
int tmp_id;
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);
@@ -408,7 +422,9 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
}
// reset request
tmp_id = wsgi_req->async_id;
memset(wsgi_req, 0, sizeof(struct wsgi_request));
wsgi_req->async_id = tmp_id;
if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
goodbye_cruel_world();
@@ -426,9 +442,6 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
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];
wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id];
@@ -443,6 +456,25 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
}
int wsgi_req_simple_recv(struct wsgi_request *wsgi_req) {
UWSGI_SET_IN_REQUEST;
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]);
}
return 0;
}
int wsgi_req_recv(struct wsgi_request *wsgi_req) {
UWSGI_SET_IN_REQUEST;
@@ -547,21 +579,6 @@ polling:
return -1;
}
#ifdef UWSGI_STACKLESS
inline struct wsgi_request *current_wsgi_req() {
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
if (uwsgi.stackless && uwsgi.async >1) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
return wsgi_req;
}
#endif
void sanitize_args() {
if (uwsgi.async > 1) {
@@ -937,6 +954,7 @@ char *uwsgi_strncopy(char *s, int len) {
int uwsgi_get_app_id(char *script_name, int script_name_len, int modifier1) {
int i;
struct stat st;
for(i=0;i<uwsgi.apps_cnt;i++) {
//uwsgi_log("searching for %.*s in %.*s %p\n", script_name_len, script_name, uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint, uwsgi.apps[i].callable);
@@ -944,6 +962,15 @@ int uwsgi_get_app_id(char *script_name, int script_name_len, int modifier1) {
continue;
}
if (!uwsgi_strncmp(uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len, script_name, script_name_len)) {
if (uwsgi.apps[i].touch_reload) {
if (!stat(uwsgi.apps[i].touch_reload, &st)) {
if (st.st_mtime != uwsgi.apps[i].touch_reload_mtime) {
// serve the new request and reload
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
return -1;
}
}
}
if (modifier1 == -1) return i;
if (modifier1 == uwsgi.apps[i].modifier1) return i;
}
@@ -1058,7 +1085,7 @@ int uwsgi_read_whole_body(struct wsgi_request *wsgi_req, char *buf, size_t len)
// here we use O_EXCL to avoid eventual application bug in uuid generation/using
upload_progress_fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP);
if (upload_progress_fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(upload_progress_filename);
free(upload_progress_filename);
}
}
@@ -1345,7 +1372,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
if (add_zero) {
*size = *size + 1;
buffer = realloc(buffer, *size);
buffer[*size] = 0;
buffer[*size-1] = 0;
}
}
@@ -1353,7 +1380,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
else {
fd = open(url, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(url);
exit(1);
}
@@ -1662,3 +1689,37 @@ int uwsgi_list_has_str(char *list, char *str) {
free(list2);
return 0;
}
int uwsgi_str2_num(char *str) {
int num = 0;
num = 10 * (str[0] - 48);
num += str[1] - 48;
return num;
}
int uwsgi_str3_num(char *str) {
int num = 0;
num = 100 * (str[0] - 48);
num += 10 * (str[1] - 48);
num += str[2] - 48;
return num;
}
int uwsgi_str4_num(char *str) {
int num = 0;
num = 1000 * (str[0] - 48);
num += 100 * (str[1] - 48);
num += 10 * (str[2] - 48);
num += str[3] - 48;
return num;
}
+430 -128
View File
@@ -52,6 +52,8 @@ static struct option long_base_options[] = {
{"cgi-mode", no_argument, 0, 'c'},
{"abstract-socket", no_argument, 0, 'a'},
{"chmod-socket", optional_argument, 0, 'C'},
{"map-socket", required_argument, 0, LONG_ARGS_MAP_SOCKET},
{"chmod", optional_argument, 0, 'C'},
#ifdef UWSGI_THREADING
{"enable-threads", no_argument, 0, 'T'},
#endif
@@ -70,12 +72,15 @@ static struct option long_base_options[] = {
{"cache-store-sync", required_argument, 0, LONG_ARGS_CACHE_STORE_SYNC},
{"queue", required_argument, 0, LONG_ARGS_QUEUE},
{"queue-blocksize", required_argument, 0, LONG_ARGS_QUEUE_BLOCKSIZE},
{"queue-store", required_argument, 0, LONG_ARGS_QUEUE_STORE},
{"queue-store-sync", required_argument, 0, LONG_ARGS_QUEUE_STORE_SYNC},
#ifdef UWSGI_SPOOLER
{"spooler", required_argument, 0, 'Q'},
#endif
{"disable-logging", no_argument, 0, 'L'},
{"pidfile", required_argument, 0, LONG_ARGS_PIDFILE},
{"pidfile2", required_argument, 0, LONG_ARGS_PIDFILE2},
{"chroot", required_argument, 0, LONG_ARGS_CHROOT},
{"gid", required_argument, 0, LONG_ARGS_GID},
{"uid", required_argument, 0, LONG_ARGS_UID},
@@ -125,6 +130,7 @@ static struct option long_base_options[] = {
{"async", required_argument, 0, LONG_ARGS_ASYNC},
#endif
{"logto", required_argument, 0, LONG_ARGS_LOGTO},
{"logfile-chown", no_argument, &uwsgi.logfile_chown, 1},
{"log-syslog", optional_argument, 0, LONG_ARGS_LOG_SYSLOG},
{"log-master", no_argument, 0, LONG_ARGS_LOG_MASTER},
{"logdate", optional_argument, 0, LONG_ARGS_LOG_DATE},
@@ -147,6 +153,7 @@ static struct option long_base_options[] = {
{"routing", no_argument, &uwsgi.routing, 1},
#endif
{"check-static", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"check-cache", no_argument, &uwsgi.check_cache, 1},
{"close-on-exec", no_argument, &uwsgi.close_on_exec, 1},
{"mode", required_argument, 0, LONG_ARGS_MODE},
{"env", required_argument, 0, LONG_ARGS_ENV},
@@ -188,7 +195,7 @@ void warn_pipe()
{
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi.async < 2 && wsgi_req->uri_len > 0) {
if (uwsgi.threads < 2 && wsgi_req->uri_len > 0) {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
} else {
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
@@ -411,6 +418,13 @@ static void vacuum(void)
uwsgi_log("VACUUM: pidfile removed.\n");
}
}
if (uwsgi.pidfile2) {
if (unlink(uwsgi.pidfile2)) {
uwsgi_error("unlink()");
} else {
uwsgi_log("VACUUM: pidfile2 removed.\n");
}
}
if (uwsgi.chdir) {
if (chdir(uwsgi.chdir)) {
uwsgi_error("chdir()");
@@ -823,9 +837,10 @@ int main(int argc, char *argv[], char *envp[])
if (uwsgi.dump_options) {
struct option *lopt = uwsgi.long_options;
while(lopt->name) {
uwsgi_log("--%s\n", lopt->name);
fprintf(stdout, "%s\n", lopt->name);
lopt++;
}
exit(0);
}
if (uwsgi.show_config) {
@@ -898,7 +913,7 @@ options_parsed:
}
#ifdef UWSGI_DEBUG
uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, plese disable DEBUG in uwsgiconfig.py and recompile it ***\n***\n");
uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, please disable debug in your build profile and recompile it ***\n***\n");
#endif
uwsgi_log("compiled with version: %s on %s\n", __VERSION__, UWSGI_BUILD_DATE);
@@ -913,7 +928,7 @@ options_parsed:
uwsgi_log("writing pidfile to %s\n", uwsgi.pidfile);
pidfile = fopen(uwsgi.pidfile, "w");
if (!pidfile) {
uwsgi_error("fopen");
uwsgi_error_open(uwsgi.pidfile);
exit(1);
}
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
@@ -941,7 +956,9 @@ options_parsed:
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
int clone_flags = SIGCHLD|CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
//clone_flags |= CLONE_NEWNET;
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack+PTHREAD_STACK_MIN, clone_flags, (void *)argv);
if (pid == -1) {
uwsgi_error("clone()");
@@ -1089,6 +1106,19 @@ int uwsgi_start(void *v_argv) {
}
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_log("writing pidfile2 to %s\n", uwsgi.pidfile2);
FILE *pidfile2 = fopen(uwsgi.pidfile2, "w");
if (!pidfile2) {
uwsgi_error_open(uwsgi.pidfile2);
exit(1);
}
if (fprintf(pidfile2, "%d\n", (int) getpid()) < 0) {
uwsgi_log("could not write pidfile2.\n");
}
fclose(pidfile2);
}
if (!uwsgi.no_initial_output) {
if (!uwsgi.master_process) {
uwsgi_log(" *** WARNING: you are running uWSGI without its master process manager ***\n");
@@ -1170,9 +1200,10 @@ int uwsgi_start(void *v_argv) {
uwsgi_register_loop("simple", simple_loop);
uwsgi_register_loop("async", complex_loop);
uwsgi_register_loop("async", async_loop);
// TODO rewrite to use uwsgi.max_fd
if (uwsgi.async > 1) {
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
if ((unsigned long) uwsgi.rl.rlim_cur < (unsigned long) uwsgi.async) {
@@ -1209,8 +1240,8 @@ int uwsgi_start(void *v_argv) {
uwsgi.async_buf = uwsgi_malloc(sizeof(char *) * uwsgi.cores);
if (uwsgi.async > 1) {
uwsgi_log("%d\n", uwsgi.max_fd);
uwsgi.async_waiting_fd_table = malloc( sizeof(int) * uwsgi.max_fd);
uwsgi_log("async fd table size: %d\n", uwsgi.max_fd);
uwsgi.async_waiting_fd_table = malloc( sizeof(struct wsgi_request *) * uwsgi.max_fd);
if (!uwsgi.async_waiting_fd_table) {
uwsgi_error("malloc()");
exit(1);
@@ -1306,15 +1337,50 @@ int uwsgi_start(void *v_argv) {
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
uwsgi.shared->queue_pos = 0;
uwsgi.shared->queue_pull_pos = 0;
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size;
int queue_fd;
struct stat qst;
if (stat(uwsgi.queue_store, &qst)) {
uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
if (queue_fd >= 0) {
// fill the queue store
if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t)qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
exit(1);
}
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
}
if (queue_fd < 0) {
uwsgi_error_open(uwsgi.queue_store);
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
uwsgi_queue_fix();
}
else {
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.shared->queue_pos = 0;
uwsgi.shared->queue_pull_pos = 0;
uwsgi.queue_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.queue_lock);
@@ -1369,7 +1435,7 @@ int uwsgi_start(void *v_argv) {
}
}
else {
if (cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
if ((size_t)cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
@@ -1378,7 +1444,7 @@ int uwsgi_start(void *v_argv) {
}
if (cache_fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
@@ -1577,7 +1643,7 @@ int uwsgi_start(void *v_argv) {
} else {
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != 0) {
@@ -1637,7 +1703,8 @@ int uwsgi_start(void *v_argv) {
#ifdef UWSGI_THREADING
if (uwsgi.sockets_cnt) {
if (uwsgi.has_threads) {
uwsgi.current_wsgi_req = threaded_current_wsgi_req;
if (uwsgi.threads > 1)
uwsgi.current_wsgi_req = threaded_current_wsgi_req;
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->enable_threads)
uwsgi.p[i]->enable_threads();
@@ -1674,20 +1741,6 @@ int uwsgi_start(void *v_argv) {
}
#endif
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
#ifdef __linux__
uwsgi.async_events = uwsgi_malloc(sizeof(struct epoll_event) * uwsgi.async);
#elif defined(__sun__)
uwsgi.async_events = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.async);
#else
uwsgi.async_events = uwsgi_malloc(sizeof(struct kevent) * uwsgi.async);
#endif
}
#endif
#ifndef UNBIT
uwsgi_log("your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue);
@@ -1703,6 +1756,22 @@ int uwsgi_start(void *v_argv) {
}
memset(uwsgi.workers, 0, sizeof(struct uwsgi_worker) * uwsgi.numproc + 1);
for(i=0;i<MAX_SOCKETS;i++) {
if (!uwsgi.map_socket[i]) continue;
char *p = strtok(uwsgi.map_socket[i], ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
uwsgi.workers[w].sockets_mask[i] = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", i, uwsgi.sockets[i].name, w);
p = strtok(NULL, ",");
}
}
uwsgi.mypid = getpid();
masterpid = uwsgi.mypid;
@@ -1781,6 +1850,12 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->init_apps) {
uwsgi.gp[i]->init_apps();
}
}
/*parse xml for <app> tags */
#ifdef UWSGI_XML
if (uwsgi.xml_round2 && uwsgi.xml_config != NULL) {
@@ -1901,6 +1976,31 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
//from now on the process is a real worker
}
for(i=0;i<uwsgi.sockets_cnt;i++) {
if (uwsgi.workers[uwsgi.mywid].sockets_mask[i]) {
// disable the socket for this worker
#ifdef UWSGI_DEBUG
uwsgi_log("switching off socket %d (%d) on worker %d\n", i, uwsgi.sockets[i].fd, uwsgi.mywid);
#endif
int fd = uwsgi.sockets[i].fd;
close(fd);
fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi.sockets[i].fd) {
if (dup2(fd, uwsgi.sockets[i].fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi.sockets_poll[i].fd = -1;
uwsgi.sockets_poll[i].events = 0;
}
}
if (uwsgi.cpu_affinity) {
#ifdef __linux__
cpu_set_t cpuset;
@@ -1969,6 +2069,16 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.sockets[i].fd);
}
}
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request*) * uwsgi.async);
for(i=0;i<uwsgi.async;i++) {
uwsgi.async_queue_unused[i] = uwsgi.wsgi_requests[i];
}
uwsgi.async_queue_unused_ptr = uwsgi.async-1;
#endif
@@ -2006,6 +2116,7 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
//re - initialize wsgi_req(can be full of init_uwsgi_app data)
for (i = 0; i < uwsgi.cores; i++) {
memset(uwsgi.wsgi_requests[i], 0, sizeof(struct wsgi_request));
uwsgi.wsgi_requests[i]->async_id = i;
}
@@ -2037,6 +2148,7 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
uwsgi.sockets_poll[uwsgi.sockets_cnt].fd = uwsgi.shared->worker_signal_pipe[1];
uwsgi.sockets_poll[uwsgi.sockets_cnt].events = POLLIN;
#ifdef UWSGI_ASYNC
// add uwsgi signal fd to async queue
if (uwsgi.async > 1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.sockets_poll[uwsgi.sockets_cnt].fd);
}
@@ -2081,7 +2193,7 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
long y = 0;
simple_loop((void *) y);
} else {
complex_loop();
async_loop(NULL);
}
}
@@ -2138,7 +2250,7 @@ end:
uwsgi_load_plugin(-1, p, NULL, 0);
p = strtok(NULL, ",");
}
build_options();
build_options();
return 1;
case LONG_ARGS_CHDIR:
uwsgi.chdir = optarg;
@@ -2214,6 +2326,9 @@ end:
case LONG_ARGS_PIDFILE:
uwsgi.pidfile = optarg;
return 1;
case LONG_ARGS_PIDFILE2:
uwsgi.pidfile2 = optarg;
return 1;
#ifdef UWSGI_UDP
case LONG_ARGS_UDP:
uwsgi.udp_socket = optarg;
@@ -2296,6 +2411,9 @@ end:
case LONG_ARGS_LINUX_NS:
uwsgi.ns = optarg;
return 1;
case LONG_ARGS_LINUX_NS_NET:
uwsgi.ns_net = optarg;
return 1;
#endif
case LONG_ARGS_LIMIT_AS:
uwsgi.rl.rlim_cur = (atoi(optarg)) * 1024 * 1024;
@@ -2329,6 +2447,21 @@ end:
uwsgi.ini = optarg;
return 1;
#endif
case LONG_ARGS_MAP_SOCKET:
p = strchr(optarg, ':');
if (!p) {
uwsgi_log("invalid map-socket syntax, must be socketnum:workerN[,workerN...]\n");
exit(1);
}
p[0] = 0;
int sn = atoi(optarg);
if (sn < 0 || sn >= MAX_SOCKETS) {
uwsgi_log("invalid socket number in map-socket\n");
exit(1);
}
uwsgi.map_socket[sn] = p+1;
p[0] = ':';
return 1;
case LONG_ARGS_CHECK_INTERVAL:
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = atoi(optarg);
return 1;
@@ -2345,6 +2478,13 @@ end:
case LONG_ARGS_CACHE_BLOCKSIZE:
uwsgi.cache_blocksize = atoi(optarg);
return 1;
case LONG_ARGS_QUEUE_STORE:
uwsgi.queue_store = optarg;
uwsgi.master_process = 1;
return 1;
case LONG_ARGS_QUEUE_STORE_SYNC:
uwsgi.queue_store_sync = atoi(optarg);
return 1;
case LONG_ARGS_QUEUE:
uwsgi.queue_size = atoi(optarg);
return 1;
@@ -2425,6 +2565,7 @@ end:
return 1;
case 'p':
if (!strcmp(optarg, "auto")) {
#ifndef __sun__
struct rlimit rl;
if (getrlimit(RLIMIT_NPROC, &rl)) {
uwsgi_error("getrlimit()");
@@ -2451,6 +2592,9 @@ end:
uwsgi.master_process = 1;
}
}
#else
uwsgi.numproc = 4;
#endif
}
else {
uwsgi.numproc = atoi(optarg);
@@ -2518,104 +2662,11 @@ end:
uwsgi.single_interpreter = 1;
return 1;
case 'h':
uwsgi_help();
/*
fprintf(stdout, "Usage: %s [options...]\n\
\t-s|--socket <name>\t\tpath (or name) of UNIX/TCP socket to bind to\n\
\t-l|--listen <num>\t\tset socket listen queue to <n> (default 64, maximum is system dependent)\n\
\t-z|--socket-timeout <sec>\tset socket timeout to <sec> seconds (default 4 seconds)\n\
\t-b|--buffer-size <n>\t\tset buffer size to <n> bytes\n\
\t-L|--disable-logging\t\tdisable request logging (only errors or server messages will be logged)\n\
\t-x|--xmlconfig <path>\t\tpath of xml config file\n\
\t-w|--module <module>\t\tname of python config module\n\
\t-t|--harakiri <sec>\t\tset harakiri timeout to <sec> seconds\n\
\t-p|--processes <n>\t\tspawn <n> uwsgi worker processes\n\
\t-O|--optimize <n>\t\tset python optimization level to <n>\n\
\t-v|--max-vars <n>\t\tset maximum number of vars/headers to <n>\n\
\t-A|--sharedarea <n>\t\tcreate a shared memory area of <n> pages\n\
\t-c|--cgi-mode\t\t\tset cgi mode\n\
\t-C|--chmod-socket[=NNN]\t\tchmod socket to 666 or NNN\n\
\t-m|--memory-report\t\tenable memory usage report\n\
\t-i|--single-interpreter\t\tsingle interpreter mode\n\
\t-a|--abstract-socket\t\tset socket in the abstract namespace (Linux only)\n\
\t-T|--enable-threads\t\tenable threads support\n\
\t-M|--master\t\t\tenable master process manager\n\
\t-H|--home <path>\t\tset python home/virtualenv\n\
\t-h|--help\t\t\tthis help\n\
\t-r|--reaper\t\t\tprocess reaper (call waitpid(-1,...) after each request)\n\
\t-R|--max-requests\t\tmaximum number of requests for each worker\n\
\t-j|--test\t\t\ttest if uWSGI can import a module\n\
\t-Q|--spooler <dir>\t\trun the spooler on directory <dir>\n\
\t--callable <callable>\t\tset the callable (default 'application')\n\
\t--pidfile <file>\t\twrite the masterpid to <file>\n\
\t--chroot <dir>\t\t\tchroot to directory <dir> (only root)\n\
\t--gid <id/groupname>\t\tsetgid to <id/groupname> (only root)\n\
\t--uid <id/username>\t\tsetuid to <id/username> (only root)\n\
\t--chdir <dir>\t\t\tchdir to <dir> before app loading\n\
\t--chdir2 <dir>\t\t\tchdir to <dir> after module loading\n\
\t--no-server\t\t\tinitialize the uWSGI server then exit. Useful for testing and using uwsgi embedded module\n\
\t--no-defer-accept\t\tdisable the no-standard way to defer the accept() call (TCP_DEFER_ACCEPT, SO_ACCEPTFILTER...)\n\
\t--paste <config:/egg:>\t\tload applications using paste.deploy.loadapp()\n\
\t--check-interval <sec>\t\tset the check interval (in seconds) of the master process\n\
\t--pythonpath <dir>\t\tadd <dir> to PYTHONPATH\n\
\t--python-path <dir>\t\tadd <dir> to PYTHONPATH\n\
\t--pp <dir>\t\t\tadd <dir> to PYTHONPATH\n\
\t--pyargv <args>\t\t\tassign args to python sys.argv\n\
\t--limit-as <MB>\t\t\tlimit the address space of processes to MB megabytes\n\
\t--limit-post <bytes>\t\tlimit HTTP content_length size to <bytes>\n\
\t--post-buffering <bytes>\tbuffer HTTP POST request higher than <bytes> to disk\n\
\t--post-buffering-bufsize <b>\tset the buffer size to <b> bytes for post-buffering\n\
\t--prio <N>\t\t\tset process priority/nice to N\n\
\t--no-orphans\t\t\tautomatically kill workers on master's dead\n\
\t--udp <ip:port>\t\t\tbind master process to udp socket on ip:port\n\
\t--multicast <group>\t\tset multicast group\n\
\t--snmp\t\t\t\tenable SNMP support in the UDP server\n\
\t--snmp-community <value>\tset SNMP community code to <value>\n\
\t--erlang <name@ip>\t\tenable the Erlang server with node name <node@ip>\n\
\t--erlang-cookie <cookie>\tset the erlang cookie to <cookie>\n\
\t--nagios\t\t\tdo a nagios check\n\
\t--binary-path <bin-path>\tset the path for the next reload of uWSGI (needed for chroot environments)\n\
\t--proxy <socket>\t\trun the uwsgi proxy on socket <socket>\n\
\t--proxy-node <socket>\t\tadd the node <socket> to the proxy\n\
\t--proxy-max-connections <n>\tset the max number of concurrent connections mnaged by the proxy\n\
\t--wsgi-file <file>\t\tload the <file> wsgi file\n\
\t--file <file>\t\t\tuse python file instead of python module for configuration\n\
\t--eval <code>\t\t\tevaluate code for app configuration\n\
\t--async <n>\t\t\tenable async mode with n core\n\
\t--logto <logfile|addr>\t\tlog to file/udp\n\
\t--logdate\t\t\tadd timestamp to loglines\n\
\t--log-zero\t\t\tlog requests with 0 response size\n\
\t--log-slow <t>\t\t\tlog requests slower than <t> milliseconds\n\
\t--log-4xx\t\t\tlog requests with status code 4xx\n\
\t--log-5xx\t\t\tlog requests with status code 5xx\n\
\t--log-big <n>\t\t\tlog requests bigger than <n> bytes\n\
\t--log-sendfile\t\t\tlog sendfile() requests\n\
\t--ignore-script-name\t\tdisable uWSGI management of SCRIPT_NAME\n\
\t--no-default-app\t\tdo not fallback unknown SCRIPT_NAME requests\n\
\t--ini <inifile>\t\t\tpath of ini config file\n\
\t--ini-paste <inifile>\t\tpath of ini config file that contains paste configuration\n\
\t--ldap <url>\t\t\turl of LDAP uWSGIConfig resource\n\
\t--ldap-schema\t\t\tdump uWSGIConfig LDAP schema\n\
\t--ldap-schema-ldif\t\tdump uWSGIConfig LDAP schema in LDIF format\n\
\t--grunt\t\t\t\tenable grunt workers\n\
\t--ugreen\t\t\tenable uGreen support\n\
\t--ugreen-stacksize <n>\t\tset uGreen stacksize to <n>\n\
\t--stackless\t\t\tenable usage of tasklet (only on Stackless Python)\n\
\t--no-site\t\t\tdo not import site.py on startup\n\
\t--vhost\t\t\t\tenable virtual hosting\n\
\t--mount MOUNTPOINT=app\t\tadda new app under MOUNTPOINT\n\
\t--routing\t\t\tenable uWSGI advanced routing\n\
\t--http <addr>\t\t\tstart embedded HTTP server on <addr>\n\
\t--http-only\t\t\tstart only the embedded HTTP server\n\
\t--http-var KEY[=VALUE]\t\tadd var KEY to uwsgi requests made by the embedded HTTP server\n\
\t--catch-exceptions\t\tprint exceptions in the browser\n\
\t--mode\t\t\t\tset configuration mode\n\
\t--env KEY=VALUE\t\t\tset environment variable\n\
\t--vacuum\t\t\tclear the environment on exit (remove UNIX sockets and pidfiles)\n\
\t--ping <addr>\t\t\tping a uWSGI server (returns 1 on failure 0 on success)\n\
\t--ping-timeout <n>\t\tset ping timeout to <n>\n\
\t--cgroup <group>\t\trun the server in <group> cgroup (Linux only)\n\
\t--cgroup-opt KEY=VAL\t\tset cgroup option (Linux only)\n\
\t--version\t\t\tprint server version\n\
\t-d|--daemonize <logfile|addr>\tdaemonize and log into <logfile> or udp <addr>\n", uwsgi.binary_path);
*/
return 0;
}
@@ -3068,3 +3119,254 @@ char *uwsgi_cluster_best_node() {
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
struct uwsgi_help_item main_help[] = {
{"socket <name>", "path (or name) of UNIX/TCP socket to bind to"},
{"listen <num>", "set socket listen queue to <n> (default 100, maximum is system dependent)"},
{"socket-timeout <sec>", "set socket timeout to <sec> seconds (default 4 seconds)"},
{"buffer-size <n>", "set buffer size to <n> bytes"},
{"disable-logging", "disable request logging (only errors or server messages will be logged)"},
{"xmlconfig <path>", "path of xml config file"},
{"harakiri <sec>", "set harakiri timeout to <sec> seconds"},
{"harakiri-verbose", "report additional info during harakiri"},
{"processes <n>", "spawn <n> uwsgi worker processes"},
{"workers <n>", "spawn <n> uwsgi worker processes"},
{"max-vars <n>", "set maximum number of vars/headers to <n>"},
{"sharedarea <n>", "create a shared memory area of <n> pages"},
{"cgi-mode", "set cgi mode"},
{"chmod-socket[=NNN]", "chmod socket to 666 or NNN"},
{"chmod[=NNN]", "chmod socket to 666 or NNN"},
{"memory-report", "enable memory usage report"},
{"single-interpreter", "single interpreter mode"},
{"abstract-socket", "set socket in the abstract namespace (Linux only)"},
{"enable-threads", "enable threads support"},
{"master", "enable master process manager"},
{"help", "this help"},
{"reaper", "process reaper (call waitpid(-1,...) after each request)"},
{"max-requests", "maximum number of requests for each worker"},
{"test", "test if uWSGI can import a module"},
{"spooler <dir>", "run the spooler on directory <dir>"},
{"pidfile <file>", "write the masterpid to <file>"},
{"chroot <dir>", "chroot to directory <dir> (only root)"},
{"gid <id/groupname>", "setgid to <id/groupname> (only root)"},
{"uid <id/username>", "setuid to <id/username> (only root)"},
{"chdir <dir>", "chdir to <dir> before app loading"},
{"chdir2 <dir>", "chdir to <dir> after module loading"},
{"no-server", "initialize the uWSGI server then exit. Useful for testing and using uwsgi embedded module"},
{"no-defer-accept", "disable the no-standard way to defer the accept() call (TCP_DEFER_ACCEPT, SO_ACCEPTFILTER...)"},
{"check-interval <sec>", "set the check interval (in seconds) of the master process"},
{"limit-as <MB>", "limit the address space of processes to MB megabytes"},
{"limit-post <bytes>", "limit HTTP content_length size to <bytes>"},
{"post-buffering <bytes>", "buffer HTTP POST request higher than <bytes> to disk"},
{"post-buffering-bufsize <b>", "set the buffer size to <b> bytes for post-buffering"},
{"prio <N>", "set process priority/nice to N"},
{"no-orphans", "automatically kill workers on master's dead"},
{"udp <ip:port>", "bind master process to udp socket on ip:port"},
{"multicast <group>", "set multicast group"},
{"snmp[=<addr>]", "enable SNMP support in the UDP server or bind it to <addr>"},
{"snmp-community <value>", "set SNMP community code to <value>"},
{"erlang <name|address>", "enable the Erlang server with node name <name@address>"},
{"erlang-cookie <cookie>", "set the erlang cookie to <cookie>"},
{"nagios", "do a nagios check"},
{"binary-path <bin-path>", "set the path for the next reload of uWSGI (needed for chroot environments)"},
{"proxy <socket>", "run the uwsgi proxy on socket <socket>"},
{"proxy-node <socket>", "add the node <socket> to the proxy"},
{"proxy-max-connections <n>", "set the max number of concurrent connections mnaged by the proxy"},
{"async <n>", "enable async mode with n core"},
{"threads <n>", "spawn <n> threads core"},
{"logto <logfile|addr>", "log to file/udp"},
{"logdate", "add timestamp to loglines"},
{"log-zero", "log requests with 0 response size"},
{"log-slow <t>", "log requests slower than <t> milliseconds"},
{"log-4xx", "log requests with status code 4xx"},
{"log-5xx", "log requests with status code 5xx"},
{"log-big <n>", "log requests bigger than <n> bytes"},
{"log-sendfile", "log sendfile() requests"},
{"ignore-script-name", "disable uWSGI management of SCRIPT_NAME"},
{"no-default-app", "do not fallback unknown SCRIPT_NAME requests"},
{"ini <inifile>", "path of ini config file"},
{"ldap <url>", "url of LDAP uWSGIConfig resource"},
{"ldap-schema", "dump uWSGIConfig LDAP schema"},
{"ldap-schema-ldif", "dump uWSGIConfig LDAP schema in LDIF format"},
{"grunt", "enable grunt workers"},
{"ugreen", "enable uGreen support"},
{"ugreen-stacksize <n>", "set uGreen stacksize to <n>"},
{"no-site", "do not import site.py on startup"},
{"vhost", "enable virtual hosting"},
{"vhost-host", "use the Host header as the key for virtual hosting"},
{"mount MOUNTPOINT=app", "add a new app under MOUNTPOINT"},
{"routing", "enable uWSGI advanced routing"},
{"http <addr>", "start embedded HTTP server on <addr>"},
{"http-only", "start only the embedded HTTP server"},
{"http-var KEY[=VALUE]", "add var KEY to uwsgi requests made by the embedded HTTP server"},
{"catch-exceptions", "print exceptions in the browser"},
{"mode", "set configuration mode"},
{"env KEY=VALUE", "set environment variable"},
{"vacuum", "clear the environment on exit (remove UNIX sockets and pidfiles)"},
{"ping <addr>", "ping a uWSGI server (returns 1 on failure 0 on success)"},
{"ping-timeout <n>", "set ping timeout to <n>"},
{"cgroup <group>", "run the server in <group> cgroup (Linux only)"},
{"cgroup-opt KEY=VAL", "set cgroup option (Linux only)"},
{"version", "print server version"},
{"attach-daemon <command>", "run <command> under the control of master process"},
{"daemonize <logfile|addr>", "daemonize and log into <logfile> or udp <addr>"},
{ 0, 0 },
};
void uwsgi_help(void) {
struct uwsgi_help_item *uhi, *all_help;
int max_size = 0;
struct option *lopt;
int found;
char *space;
char *tmp_option = NULL;
int i;
all_help = main_help;
build_options();
while( (uhi = all_help) ) {
if (uhi->key == 0)
break;
if ((int)strlen(uhi->key) > max_size) {
max_size = (int)strlen(uhi->key);
}
all_help++;
}
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->help) {
all_help = uwsgi.p[i]->help;
while( (uhi = all_help) ) {
if (uhi->key == 0) break;
if ((int)strlen(uhi->key) > max_size)
max_size = (int)strlen(uhi->key);
all_help++;
}
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->help) {
all_help = uwsgi.gp[i]->help ;
while( (uhi = all_help) ) {
if (uhi->key == 0) break;
if ((int)strlen(uhi->key) > max_size)
max_size = (int)strlen(uhi->key);
all_help++;
}
}
}
fprintf(stdout, "Usage: %s [options...]\n", uwsgi.binary_path);
lopt = uwsgi.long_options;
max_size+=4;
while(lopt->name) {
found = 0;
all_help = main_help;
while( (uhi = all_help) ) {
if (uhi->key == 0) break;
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
found = 1;
break;
}
free(tmp_option);
all_help++;
}
if (!found) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->help) {
all_help = uwsgi.p[i]->help;
while( (uhi = all_help) ) {
if (uhi->key == 0) break;
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
found = 1;
break;
}
free(tmp_option);
all_help++;
}
}
if (found) break;
}
}
if (!found) {
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->help) {
all_help = uwsgi.gp[i]->help;
while( (uhi = all_help) ) {
if (uhi->key == 0) break;
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
found = 1;
break;
}
free(tmp_option);
all_help++;
}
}
if (found) break;
}
}
if (found) {
if (!lopt->flag && ( (lopt->val >= 'a' && lopt->val <= 'z') || (lopt->val >= 'A' && lopt->val <= 'Z'))) {
fprintf(stdout, " -%c|--%-*s %s\n", lopt->val, max_size-3, uhi->key, uhi->value);
}
else {
fprintf(stdout, " --%-*s %s\n", max_size, uhi->key, uhi->value);
}
if (tmp_option) free(tmp_option);
}
else {
fprintf(stdout, " --%-*s *** UNDOCUMENTED OPTION ***\n", max_size, lopt->name);
}
lopt++;
}
exit(0);
}
+93 -34
View File
@@ -2,11 +2,12 @@
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
#define UWSGI_VERSION "0.9.7-dev"
#define UWSGI_VERSION "0.9.7.1"
#define UMAX16 65536
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
#define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()")
@@ -14,6 +15,7 @@
#define ushared uwsgi.shared
#define MAX_SOCKETS 8
#define MAX_APPS 64
#define MAX_GENERIC_PLUGINS 64
#define MAX_RPC 64
@@ -98,7 +100,9 @@
#ifdef __linux
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <sched.h>
#include <sys/prctl.h>
#include <linux/limits.h>
@@ -206,6 +210,13 @@ extern int pivot_root(const char * new_root, const char * put_old);
#define uwsgi_cache_update_start(x, y, z) uwsgi_cache_set(x, y, "", 0, CACHE_FLAG_UNGETTABLE)
struct uwsgi_help_item {
char *key;
char *value;
};
union uwsgi_sockaddr {
struct sockaddr sa;
struct sockaddr_in sa_in;
@@ -364,6 +375,10 @@ struct uwsgi_opt {
#define LONG_ARGS_CPU_AFFINITY 17083
#define LONG_ARGS_CACHE_STORE 17084
#define LONG_ARGS_CACHE_STORE_SYNC 17085
#define LONG_ARGS_QUEUE_STORE 17086
#define LONG_ARGS_QUEUE_STORE_SYNC 17087
#define LONG_ARGS_PIDFILE2 17088
#define LONG_ARGS_MAP_SOCKET 17089
#define UWSGI_OK 0
@@ -491,6 +506,8 @@ struct uwsgi_plugin {
uint16_t (*rpc)(void *, uint8_t, char **, char *);
struct uwsgi_help_item *help;
};
@@ -527,6 +544,9 @@ struct uwsgi_app {
int requests;
char *chdir;
char *touch_reload;
time_t touch_reload_mtime;
};
@@ -560,6 +580,13 @@ struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier2;
};
struct uwsgi_async_fd {
int fd;
int event;
struct uwsgi_async_fd* prev;
struct uwsgi_async_fd* next;
};
struct wsgi_request {
struct uwsgi_header uh;
@@ -622,6 +649,15 @@ struct wsgi_request {
char *chdir;
uint16_t chdir_len;
char *touch_reload;
uint16_t touch_reload_len;
char *cache_get;
uint16_t cache_get_len;
char *if_modified_since;
uint16_t if_modified_since_len;
int fd_closed;
int sendfile_fd;
@@ -639,14 +675,14 @@ struct wsgi_request {
int async_id;
int async_status;
int async_waiting_fd;
int async_waiting_fd_type;
int async_waiting_fd_monitored;
int switches;
time_t async_timeout;
int async_timeout_expired;
int async_timed_out;
int async_ready_fd;
int async_last_ready_fd;
struct uwsgi_rb_timer *async_timeout;
struct uwsgi_async_fd *waiting_fds;
void *async_app;
void *async_result;
@@ -658,6 +694,8 @@ struct wsgi_request {
int async_plagued;
int suspended;
int *ovector;
size_t post_cl;
char *post_buffering_buf;
@@ -764,6 +802,7 @@ struct uwsgi_server {
size_t check_static_len;
char *logfile;
int logfile_chown;
int vhost;
int vhost_host;
@@ -772,8 +811,16 @@ struct uwsgi_server {
char **async_buf;
char **async_post_buf;
int *async_waiting_fd_table;
int async_current_max;
struct wsgi_request **async_waiting_fd_table;
struct uwsgi_async_request *async_runqueue;
struct uwsgi_async_request *async_runqueue_last;
int async_runqueue_cnt;
struct rb_root *rb_async_timeouts;
int async_queue_unused_ptr;
struct wsgi_request **async_queue_unused;
#ifdef UWSGI_ROUTING
int **async_ovector;
@@ -826,6 +873,7 @@ struct uwsgi_server {
int page_size;
char *pidfile;
char *pidfile2;
int harakiri_verbose;
@@ -835,14 +883,6 @@ struct uwsgi_server {
int async_queue;
int async_nevents;
#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;
@@ -922,13 +962,16 @@ struct uwsgi_server {
char *cgroup_opt[64];
int cgroup_opt_cnt;
char *ns;
char *ns_net;
#endif
int sockets_cnt;
struct uwsgi_socket sockets[8];
struct uwsgi_socket sockets[MAX_SOCKETS];
// leave a slot for no-orphan mode
struct pollfd sockets_poll[9];
char *map_socket[MAX_SOCKETS];
time_t respawn_delta;
char *mounts[MAX_APPS];
@@ -948,6 +991,7 @@ struct uwsgi_server {
// usedby suspend/resume loops
void (*schedule_to_main) (struct wsgi_request *);
void (*schedule_to_req) (void);
int close_on_exec;
@@ -967,6 +1011,8 @@ struct uwsgi_server {
int cluster_nodes;
int cluster_fd;
struct sockaddr_in mc_cluster_addr;
int check_cache;
uint32_t cache_max_items;
uint64_t *cache_hashtable;
@@ -981,6 +1027,9 @@ struct uwsgi_server {
uint64_t queue_size;
uint64_t queue_blocksize;
void *queue;
char *queue_store;
size_t queue_filesize;
int queue_store_sync;
void *cache_lock;
void *queue_lock;
@@ -1185,6 +1234,8 @@ struct uwsgi_worker {
uint64_t exceptions;
char sockets_mask[MAX_SOCKETS];
};
char *uwsgi_get_cwd(void);
@@ -1268,14 +1319,15 @@ struct http_status_codes {
#ifdef UWSGI_ASYNC
#define ASYNC_IN 1
#define ASYNC_OUT 2
struct wsgi_request *async_loop(void);
void *async_loop(void *);
struct wsgi_request *find_first_available_wsgi_req(void);
struct wsgi_request *find_first_accepting_wsgi_req(void);
struct wsgi_request *find_wsgi_req_by_fd(int);
struct wsgi_request *find_wsgi_req_by_id(int);
void async_add_fd_write(struct wsgi_request *, int, int);
void async_add_fd_read(struct wsgi_request *, int, int);
#ifdef __clang__
struct wsgi_request *next_wsgi_req(struct wsgi_request *);
#else
@@ -1283,11 +1335,8 @@ inline struct wsgi_request *next_wsgi_req(struct wsgi_request *);
#endif
int async_get_timeout(void);
void async_set_timeout(struct wsgi_request*, time_t);
void async_add_timeout(struct wsgi_request*, int);
void async_expire_timeouts(void);
void async_write_all(char *, size_t);
void async_unpause_all(void);
#endif
@@ -1302,18 +1351,11 @@ void uwsgi_close_request(struct wsgi_request *);
void wsgi_req_setup(struct wsgi_request *, int);
int wsgi_req_recv(struct wsgi_request *);
int wsgi_req_simple_recv(struct wsgi_request *);
int wsgi_req_accept(struct wsgi_request *);
int wsgi_req_simple_accept(struct wsgi_request *, int);
#ifdef UWSGI_STACKLESS
#ifdef __clang__
struct wsgi_request *current_wsgi_req(void);
#else
inline struct wsgi_request *current_wsgi_req(void);
#endif
#else
#define current_wsgi_req() (*uwsgi.current_wsgi_req)()
#endif
void sanitize_args(void);
@@ -1375,7 +1417,6 @@ int find_worker_id(pid_t);
void *simple_loop(void *);
void complex_loop(void);
int count_options(struct option *);
@@ -1445,7 +1486,7 @@ int event_queue_init(void);
void *event_queue_alloc(int);
int event_queue_add_fd_read(int, int);
int event_queue_add_fd_write(int, int);
int event_queue_del_fd(int, int);
int event_queue_del_fd(int, int, int);
int event_queue_wait(int, int, int *);
int event_queue_wait_multi(int, int, void *, int);
int event_queue_interesting_fd(void *, int);
@@ -1627,3 +1668,21 @@ int uwsgi_list_has_num(char *, int);
int uwsgi_list_has_str(char *, char *);
void uwsgi_cache_fix(void);
struct uwsgi_async_request {
struct wsgi_request *wsgi_req;
struct uwsgi_async_request *prev;
struct uwsgi_async_request *next;
};
inline int event_queue_read(void);
inline int event_queue_write(void);
void uwsgi_help(void);
void uwsgi_queue_fix(void);
int uwsgi_str2_num(char *);
int uwsgi_str3_num(char *);
int uwsgi_str4_num(char *);
+12 -1
View File
@@ -71,6 +71,9 @@ def build_uwsgi(uc):
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
epc += "UDEP(%s);" % p
eplc += "ULEP(%s);" % p
epc += "\""
@@ -93,6 +96,10 @@ def build_uwsgi(uc):
print("*** uWSGI compiling embedded plugins ***")
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
path = 'plugins/%s' % p
path = path.rstrip('/')
@@ -227,6 +234,9 @@ class uConf(object):
self.libs.remove('-lpthread')
self.libs.append('-lroot')
if uwsgi_os == 'Darwin':
self.cflags.append('-mmacosx-version-min=10.5')
# set locking subsystem
locking_mode = self.get('locking','auto')
@@ -335,7 +345,8 @@ class uConf(object):
if self.get('udp'):
self.cflags.append("-DUWSGI_UDP")
if self.get('pcre'):
# re-enable after pcre fix
if self.get('pcreOFF'):
if self.get('pcre') == 'auto':
pcreconf = spcall('pcre-config --libs')
if pcreconf:
+1 -1
View File
@@ -358,7 +358,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
xmlfd = open(uwsgi.xml_config, O_RDONLY);
if (xmlfd < 0) {
uwsgi_error("open()");
uwsgi_error_open(uwsgi.xml_config);
exit(1);
}