Compare commits

...
28 Commits
Author SHA1 Message Date
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
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
32 changed files with 1542 additions and 1017 deletions
+2
View File
@@ -11,3 +11,5 @@ b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
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
+21
View File
@@ -1,5 +1,26 @@
*** march 2011 ***
* 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
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
+324 -157
View File
@@ -2,198 +2,365 @@
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();
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;
+2 -2
View File
@@ -13,7 +13,7 @@ sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
ldap = auto
pcre = auto
debug = false
unbit = false
@@ -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
+23 -1
View File
@@ -330,6 +330,27 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
@@ -476,7 +497,7 @@ void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, vallen);
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
}
}
@@ -528,6 +549,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
+1 -4
View File
@@ -222,10 +222,7 @@ void emperor_loop() {
if (!i_am_alone) {
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
else if (diedpid > 0) {
if (diedpid < 0 || diedpid > 0) {
i_am_alone = 1;
}
}
+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;
}
+193 -113
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;
@@ -37,71 +45,162 @@ int calc_ldap_name(char *name) {
return strlen(name) + counter;
}
void uwsgi_ldap_schema_dump_ldif() {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
lopt = uwsgi.long_options;
int i;
int counter = 30000;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry->has_arg = aopt->has_arg;
next:
lopt++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
if (aopt->flag) {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
uwsgi_log("uWSGI");
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
@@ -112,67 +211,47 @@ void uwsgi_ldap_schema_dump_ldif() {
}
void uwsgi_ldap_schema_dump() {
struct option *aopt, *lopt;
lopt = uwsgi.long_options;
int i;
int counter = 30000;
int items;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
if (aopt->flag) {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
}
else {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGI");
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
@@ -194,8 +273,6 @@ void uwsgi_ldap_config() {
int desired_version = LDAP_VERSION3;
int ret;
struct option *aopt, *lopt;
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
@@ -211,6 +288,8 @@ void uwsgi_ldap_config() {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
@@ -225,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) {
@@ -255,9 +341,11 @@ void uwsgi_ldap_config() {
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
@@ -271,7 +359,7 @@ void uwsgi_ldap_config() {
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_val;
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
@@ -281,29 +369,21 @@ void uwsgi_ldap_config() {
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
lopt = uwsgi.long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(uwsgi_attr, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
add_exported_option(0, (char*) uwsgi_attr);
}
else {
manage_opt(aopt->val, uwsgi_val);
}
}
lopt++;
}
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
free(bervalues);
free(uwsgi_attr);
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
+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
+51 -12
View File
@@ -146,8 +146,6 @@ void master_loop(char **argv, char **environ) {
uint8_t uwsgi_signal;
#ifdef UWSGI_UDP
struct pollfd uwsgi_poll[2];
int uwsgi_poll_size = 0;
struct sockaddr_in udp_client;
socklen_t udp_len;
char udp_client_addr[16];
@@ -165,6 +163,10 @@ void master_loop(char **argv, char **environ) {
#endif
#endif
#ifdef UWSGI_SNMP
int snmp_fd = -1;
#endif
int i=0,j;
int rlen;
@@ -206,21 +208,16 @@ void master_loop(char **argv, char **environ) {
#ifdef UWSGI_UDP
if (uwsgi.udp_socket) {
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
uwsgi_poll[uwsgi_poll_size].fd = udp_fd;
if (uwsgi_poll[uwsgi_poll_size].fd < 0) {
if (udp_fd < 0) {
uwsgi_log( "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n");
}
else {
uwsgi_log( "UDP server enabled.\n");
uwsgi_poll[uwsgi_poll_size].events = POLLIN;
uwsgi_poll_size++;
event_queue_add_fd_read(uwsgi.master_queue, udp_fd);
}
}
#ifdef UWSGI_MULTICAST
if (uwsgi.cluster) {
uwsgi_poll[uwsgi_poll_size].fd = uwsgi.cluster_fd;
uwsgi_poll[uwsgi_poll_size].events = POLLIN;
uwsgi_poll_size++;
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.cluster_fd);
@@ -288,12 +285,28 @@ void master_loop(char **argv, char **environ) {
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
}
}
uwsgi_log( "filling SNMP table...");
uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
uwsgi_log( "done\n");
for(i=0;i<uwsgi.numproc;i++) {
uwsgi.shared->snmp_gvalue[30+i].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[30+i].val = &uwsgi.workers[i+1].requests;
}
if (uwsgi.snmp_addr) {
snmp_fd = bind_to_udp(uwsgi.snmp_addr, 0, 0);
if (snmp_fd < 0) {
uwsgi_log( "unable to bind to udp socket. SNMP service will be disabled.\n");
}
else {
uwsgi_log( "SNMP server enabled on %s\n", uwsgi.snmp_addr);
event_queue_add_fd_read(uwsgi.master_queue, snmp_fd);
}
}
else {
uwsgi_log( "SNMP agent enabled.\n");
}
}
#endif
@@ -317,6 +330,13 @@ void master_loop(char **argv, char **environ) {
uwsgi_subscribe(uwsgi.subscriptions[i]);
}
// sync the cache store if needed
if (uwsgi.cache_store && uwsgi.cache_filesize) {
if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
@@ -606,6 +626,20 @@ void master_loop(char **argv, char **environ) {
}
}
}
#ifdef UWSGI_SNMP
if (uwsgi.snmp_addr && interesting_fd == snmp_fd) {
udp_len = sizeof(udp_client);
rlen = recvfrom(snmp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
}
else if (rlen > 0) {
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
}
continue;
}
#endif
#ifdef UWSGI_UDP
if (uwsgi.udp_socket && interesting_fd == udp_fd) {
@@ -709,7 +743,6 @@ void master_loop(char **argv, char **environ) {
uwsgi_lock(uwsgi.fmon_table_lock);
for(i=0;i<ushared->files_monitored_cnt;i++) {
if (ushared->files_monitored[i].registered) {
uwsgi_log("fmon check %d == %d\n", interesting_fd, ushared->files_monitored[i].fd) ;
if (interesting_fd == ushared->files_monitored[i].fd) {
struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd);
// now call the file_monitor handler
@@ -911,6 +944,12 @@ void master_loop(char **argv, char **environ) {
}
}
if (uwsgi.cache_store && uwsgi.cache_filesize && uwsgi.cache_store_sync && ((master_cycles % uwsgi.cache_store_sync) == 0)) {
if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
#endif
+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']
+37
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);
+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);
}
+7 -5
View File
@@ -478,11 +478,13 @@ int py_to_erl(PyObject *pobj, ei_x_buff *x) {
ei_x_encode_long(x, PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
ei_x_encode_list_header(x, PyList_Size(pobj));
for (i = 0; i < PyList_Size(pobj); i++) {
pobj2 = PyList_GetItem(pobj, i);
if (py_to_erl(pobj2, x) < 0) return -1;
}
if (PyList_Size(pobj) > 0) {
ei_x_encode_list_header(x, PyList_Size(pobj));
for (i = 0; i < PyList_Size(pobj); i++) {
pobj2 = PyList_GetItem(pobj, i);
if (py_to_erl(pobj2, x) < 0) return -1;
}
}
ei_x_encode_empty_list(x);
}
else if (PyTuple_Check(pobj)) {
+44 -10
View File
@@ -35,6 +35,26 @@ 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"},
{"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);
@@ -176,7 +196,7 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
if (!pyfile) {
uwsgi_error("fopen()");
uwsgi_error_open(real_filename);
exit(1);
}
}
@@ -690,6 +710,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 +846,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 +968,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 +1007,7 @@ struct uwsgi_plugin python_plugin = {
.rpc = uwsgi_python_rpc,
.spooler = uwsgi_python_spooler,
/*
.help = uwsgi_python_help,
*/
.help = uwsgi_python_help,
};
+10 -5
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;
@@ -2641,6 +2641,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);
+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
+33 -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
@@ -398,8 +392,8 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "ignore");
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, "ignore");
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
-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;
}
+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,
};
+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;
}
+5
View File
@@ -2,6 +2,11 @@
#include "uwsgi.h"
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
extern struct uwsgi_server uwsgi;
struct wsgi_request* find_request_by_tasklet(PyTaskletObject *tasklet) {
+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)
+78 -24
View File
@@ -104,7 +104,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 +155,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 +269,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 +295,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) {
@@ -376,6 +376,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 +409,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 +429,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 +443,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 +566,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) {
@@ -1058,7 +1062,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);
}
}
@@ -1353,7 +1357,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);
}
@@ -1612,3 +1616,53 @@ char *uwsgi_get_exported_opt(char *key) {
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct option *aopt;
struct option *lopt = uwsgi.long_options;
while ( (aopt = lopt) ) {
if (!aopt->name) break;
if (aopt->val == index) {
return (char *) aopt->name;
}
lopt++;
}
return NULL;
}
int uwsgi_list_has_num(char *list, int num) {
char *list2 = uwsgi_concat2(list, "");
char *p = strtok(list2, ",");
while (p != NULL) {
if (atoi(p) == num) {
free(list2);
return 1;
}
p = strtok(NULL, ",");
}
free(list2);
return 0;
}
int uwsgi_list_has_str(char *list, char *str) {
char *list2 = uwsgi_concat2(list+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
if (!strcasecmp(p, str)) {
free(list2);
return 1;
}
p = strtok(NULL, " ");
}
free(list2);
return 0;
}
+402 -139
View File
@@ -66,6 +66,8 @@ static struct option long_base_options[] = {
{"sharedarea", required_argument, 0, 'A'},
{"cache", required_argument, 0, LONG_ARGS_CACHE},
{"cache-blocksize", required_argument, 0, LONG_ARGS_CACHE_BLOCKSIZE},
{"cache-store", required_argument, 0, LONG_ARGS_CACHE_STORE},
{"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},
#ifdef UWSGI_SPOOLER
@@ -95,6 +97,7 @@ static struct option long_base_options[] = {
{"limit-post", required_argument, 0, LONG_ARGS_LIMIT_POST},
{"no-orphans", no_argument, &uwsgi.no_orphans, 1},
{"prio", required_argument, 0, LONG_ARGS_PRIO},
{"cpu-affinity", required_argument, 0, LONG_ARGS_CPU_AFFINITY},
{"post-buffering", required_argument, 0, LONG_ARGS_POST_BUFFERING},
{"post-buffering-bufsize", required_argument, 0, LONG_ARGS_POST_BUFFERING_SIZE},
{"upload-progress", required_argument, 0, LONG_ARGS_UPLOAD_PROGRESS},
@@ -112,7 +115,7 @@ static struct option long_base_options[] = {
{"cluster-log", required_argument, 0, LONG_ARGS_CLUSTER_LOG},
{"subscribe-to", required_argument, 0, LONG_ARGS_SUBSCRIBE_TO},
#ifdef UWSGI_SNMP
{"snmp", no_argument, 0, LONG_ARGS_SNMP},
{"snmp", optional_argument, 0, LONG_ARGS_SNMP},
{"snmp-community", required_argument, 0, LONG_ARGS_SNMP_COMMUNITY},
#endif
{"check-interval", required_argument, 0, LONG_ARGS_CHECK_INTERVAL},
@@ -153,11 +156,14 @@ static struct option long_base_options[] = {
{"cgroup-opt", required_argument, 0, LONG_ARGS_CGROUP_OPT},
{"namespace", required_argument, 0, LONG_ARGS_LINUX_NS},
{"ns", required_argument, 0, LONG_ARGS_LINUX_NS},
{"namespace-net", required_argument, 0, LONG_ARGS_LINUX_NS_NET},
{"ns-net", required_argument, 0, LONG_ARGS_LINUX_NS_NET},
#endif
{"loop", required_argument, 0, LONG_ARGS_LOOP},
{"worker-exec", required_argument, 0, LONG_ARGS_WORKER_EXEC},
{"attach-daemon", required_argument, 0, LONG_ARGS_ATTACH_DAEMON},
{"plugins", required_argument, 0, LONG_ARGS_PLUGINS},
{"allowed-modifiers", required_argument, 0, LONG_ARGS_ALLOWED_MODIFIERS},
{"remap-modifier", required_argument, 0, LONG_ARGS_REMAP_MODIFIER},
{"dump-options", no_argument, &uwsgi.dump_options, 1},
{"show-config", no_argument, &uwsgi.show_config, 1},
@@ -182,7 +188,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");
@@ -448,6 +454,7 @@ int main(int argc, char *argv[], char *envp[])
char *emperor_env;
char *magic_table[0xff];
char *optname;
signal(SIGHUP, SIG_IGN);
@@ -583,17 +590,26 @@ int main(int argc, char *argv[], char *envp[])
}
build_options();
uwsgi.option_index = -1;
while ((i = getopt_long(argc, argv, short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
if (i == 0) {
add_exported_option((char *)uwsgi.long_options[uwsgi.option_index].name, "1", 0);
if (uwsgi.option_index > -1) {
optname = (char *)uwsgi.long_options[uwsgi.option_index].name;
}
else {
add_exported_option((char *)uwsgi.long_options[uwsgi.option_index].name, optarg, 1);
optname = uwsgi_get_optname_by_index(i);
}
// is this a flagged option ?
if (i == 0) {
add_exported_option(optname, "1", 0);
}
else {
add_exported_option(optname, optarg, 1);
manage_opt(i, optarg);
}
uwsgi.option_index = -1;
}
if (optind < argc) {
char *lazy = argv[optind];
if (lazy[0] != '[') {
@@ -897,7 +913,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) {
@@ -924,7 +940,9 @@ options_parsed:
char stack[PTHREAD_STACK_MIN];
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
pid_t pid = clone(uwsgi_start, stack+PTHREAD_STACK_MIN, SIGCHLD|CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS, (void *)argv);
int clone_flags = SIGCHLD|CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
//clone_flags |= CLONE_NEWNET;
pid_t pid = clone(uwsgi_start, stack+PTHREAD_STACK_MIN, clone_flags, (void *)argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
@@ -1152,9 +1170,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) {
@@ -1191,8 +1210,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);
@@ -1329,26 +1348,65 @@ int uwsgi_start(void *v_argv) {
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_store) {
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
int cache_fd;
struct stat cst;
if (stat(uwsgi.cache_store, &cst)) {
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
if (cache_fd >= 0) {
// fill the caching store
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
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);
}
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
}
if (cache_fd < 0) {
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);
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
for(i=0;i< (int) uwsgi.cache_max_items;i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache) {
uwsgi_error("mmap()");
exit(1);
}
*/
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) ;
for(i=0;i< (int) uwsgi.cache_max_items;i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
// the first cache item is always zero
uwsgi.shared->cache_first_available_item = 1;
uwsgi.shared->cache_unused_stack_ptr = 0;
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
@@ -1520,7 +1578,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) {
@@ -1617,20 +1675,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);
@@ -1717,12 +1761,6 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
uwsgi_rawlog(" ***\n");
#ifdef UWSGI_SNMP
if (uwsgi.snmp) {
//snmp_init();
}
#endif
//init apps hook
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_apps) {
@@ -1730,6 +1768,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) {
@@ -1776,6 +1820,20 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
uwsgi_log("spawned uWSGI master process (pid: %d)\n", uwsgi.mypid);
}
}
// security in multiuser environment: allow only a subset of modifiers
if (uwsgi.allowed_modifiers) {
for (i = 0; i < 0xFF; i++) {
if (!uwsgi_list_has_num(uwsgi.allowed_modifiers, i)) {
uwsgi.p[i]->request = unconfigured_hook;
uwsgi.p[i]->after_request = unconfigured_after_hook;
}
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir != NULL && uwsgi.sockets_cnt > 0) {
uwsgi.shared->spooler_pid = spooler_start();
@@ -1836,6 +1894,29 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
//from now on the process is a real worker
}
if (uwsgi.cpu_affinity) {
#ifdef __linux__
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
int ncpu = sysconf(_SC_NPROCESSORS_ONLN);
int base_cpu = (uwsgi.mywid-1)*uwsgi.cpu_affinity;
if (base_cpu >= ncpu) {
base_cpu = base_cpu % ncpu;
}
uwsgi_log("set cpu affinity for worker %d to", uwsgi.mywid);
for(i=0;i<uwsgi.cpu_affinity;i++) {
if (base_cpu >= ncpu) base_cpu = 0 ;
CPU_SET(base_cpu, &cpuset);
uwsgi_log(" %d", base_cpu);
base_cpu++;
}
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) {
uwsgi_error("sched_setaffinity()");
}
uwsgi_log("\n");
#endif
}
if (uwsgi.worker_exec) {
char *w_argv[2];
w_argv[0] = uwsgi.worker_exec;
@@ -1881,6 +1962,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
@@ -1918,6 +2009,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;
}
@@ -1949,6 +2041,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);
}
@@ -1993,7 +2086,7 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
long y = 0;
simple_loop((void *) y);
} else {
complex_loop();
async_loop(NULL);
}
}
@@ -2038,6 +2131,9 @@ end:
case LONG_ARGS_REMAP_MODIFIER:
uwsgi.remap_modifier = optarg;
return 1;
case LONG_ARGS_ALLOWED_MODIFIERS:
uwsgi.allowed_modifiers = optarg;
return 1;
case LONG_ARGS_PLUGINS:
p = strtok(optarg, ",");
while (p != NULL) {
@@ -2047,7 +2143,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;
@@ -2110,6 +2206,10 @@ end:
#ifdef UWSGI_SNMP
case LONG_ARGS_SNMP:
uwsgi.snmp = 1;
if (optarg) {
uwsgi.snmp_addr = optarg;
uwsgi.master_process = 1;
}
return 1;
case LONG_ARGS_SNMP_COMMUNITY:
uwsgi.snmp = 1;
@@ -2212,6 +2312,9 @@ end:
case LONG_ARGS_PRIO:
uwsgi.prio = (int) strtol(optarg, NULL, 10);
return 1;
case LONG_ARGS_CPU_AFFINITY:
uwsgi.cpu_affinity = (int) strtol(optarg, NULL, 10);
return 1;
case LONG_ARGS_POST_BUFFERING:
uwsgi.post_buffering = atoi(optarg);
return 1;
@@ -2237,6 +2340,13 @@ end:
case LONG_ARGS_CACHE:
uwsgi.cache_max_items = atoi(optarg);
return 1;
case LONG_ARGS_CACHE_STORE:
uwsgi.cache_store = optarg;
uwsgi.master_process = 1;
return 1;
case LONG_ARGS_CACHE_STORE_SYNC:
uwsgi.cache_store_sync = atoi(optarg);
return 1;
case LONG_ARGS_CACHE_BLOCKSIZE:
uwsgi.cache_blocksize = atoi(optarg);
return 1;
@@ -2320,6 +2430,7 @@ end:
return 1;
case 'p':
if (!strcmp(optarg, "auto")) {
#ifndef __sun__
struct rlimit rl;
if (getrlimit(RLIMIT_NPROC, &rl)) {
uwsgi_error("getrlimit()");
@@ -2346,6 +2457,9 @@ end:
uwsgi.master_process = 1;
}
}
#else
uwsgi.numproc = 4;
#endif
}
else {
uwsgi.numproc = atoi(optarg);
@@ -2413,104 +2527,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;
}
@@ -2963,3 +2984,245 @@ 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"},
{"processes <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"},
{"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", "enable SNMP support in the UDP server"},
{"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"},
{"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"},
{"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"},
{"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[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[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[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);
}
+80 -38
View File
@@ -7,6 +7,7 @@
#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()")
@@ -98,6 +99,10 @@
#ifdef __linux
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <sched.h>
#include <sys/prctl.h>
#include <linux/limits.h>
#include <sys/mount.h>
@@ -204,6 +209,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;
@@ -357,7 +369,11 @@ struct uwsgi_opt {
#define LONG_ARGS_SUBSCRIBE_TO 17078
#define LONG_ARGS_CLUSTER_NODES 17079
#define LONG_ARGS_RELOAD_MERCY 17080
#define LONG_ARGS_ALLOWED_MODIFIERS 17081
#define LONG_ARGS_LINUX_NS_NET 17082
#define LONG_ARGS_CPU_AFFINITY 17083
#define LONG_ARGS_CACHE_STORE 17084
#define LONG_ARGS_CACHE_STORE_SYNC 17085
#define UWSGI_OK 0
@@ -485,6 +501,8 @@ struct uwsgi_plugin {
uint16_t (*rpc)(void *, uint8_t, char **, char *);
struct uwsgi_help_item *help;
};
@@ -554,6 +572,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;
@@ -633,14 +658,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;
@@ -652,6 +677,8 @@ struct wsgi_request {
int async_plagued;
int suspended;
int *ovector;
size_t post_cl;
char *post_buffering_buf;
@@ -717,6 +744,8 @@ struct uwsgi_server {
time_t master_mercy;
int cpu_affinity;
int reload_mercy;
int option_index;
struct option *long_options;
@@ -764,8 +793,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;
@@ -794,13 +831,10 @@ struct uwsgi_server {
char *spool_dir;
#endif
#ifdef UWSGI_NAGIOS
int nagios;
#endif
#ifdef UWSGI_SNMP
int snmp;
char *snmp_community;
char *snmp_addr;
char *snmp_community;
#endif
@@ -830,14 +864,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;
@@ -943,6 +969,7 @@ struct uwsgi_server {
// usedby suspend/resume loops
void (*schedule_to_main) (struct wsgi_request *);
void (*schedule_to_req) (void);
int close_on_exec;
@@ -953,6 +980,8 @@ struct uwsgi_server {
struct uwsgi_plugin *p[0xFF];
struct uwsgi_plugin *gp[MAX_GENERIC_PLUGINS];
int gp_cnt;
char *allowed_modifiers;
char *upload_progress;
@@ -967,6 +996,9 @@ struct uwsgi_server {
uint64_t cache_blocksize;
struct uwsgi_cache_item *cache_items;
void *cache;
char *cache_store;
size_t cache_filesize;
int cache_store_sync;
uint64_t queue_size;
uint64_t queue_blocksize;
@@ -1258,14 +1290,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
@@ -1273,11 +1306,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
@@ -1292,18 +1322,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);
@@ -1365,7 +1388,6 @@ int find_worker_id(pid_t);
void *simple_loop(void *);
void complex_loop(void);
int count_options(struct option *);
@@ -1435,7 +1457,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);
@@ -1609,3 +1631,23 @@ void uwsgi_unix_signal(int, void (*)(int));
char *uwsgi_get_exported_opt(char *);
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
char *uwsgi_get_optname_by_index(int);
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);
+18 -4
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('/')
@@ -335,7 +342,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:
@@ -377,9 +385,15 @@ class uConf(object):
self.gcc_list.append('yaml')
if self.get('ldap'):
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('ldap')
self.libs.append('-lldap')
if self.get('ldap') == 'auto':
if os.path.exists('/usr/include/ldap.h'):
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('ldap')
self.libs.append('-lldap')
else:
self.cflags.append("-DUWSGI_LDAP")
self.gcc_list.append('ldap')
self.libs.append('-lldap')
if self.get('evdis'):
self.cflags.append("-DUWSGI_EVDIS")
+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);
}