Compare commits

..
16 Commits
28 changed files with 1065 additions and 852 deletions
+1
View File
@@ -12,3 +12,4 @@ 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
+15 -1
View File
@@ -1,6 +1,20 @@
*** march 2011 ***
* 0.9.7-rc2 [20010309]
* 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
+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;
+1 -1
View File
@@ -21,7 +21,7 @@ xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
locking = auto
event = auto
+37 -16
View File
@@ -6,6 +6,9 @@ extern struct uwsgi_server uwsgi;
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
@@ -18,7 +21,7 @@ int event_queue_init() {
return port;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
@@ -28,6 +31,17 @@ int event_queue_del_fd(int eq, int fd) {
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
@@ -76,12 +90,11 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget;
int i;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout > 0) {
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
@@ -99,13 +112,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
pe = (port_event_t *) events;
for(i=0;i<nget;i++) {
if (pe[i].portev_source == PORT_SOURCE_FD) {
if (port_associate(eq, pe[i].portev_source, pe[i].portev_object, pe[i].portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
}
return nget;
}
@@ -144,7 +150,6 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
uwsgi_log("port event interesting_fd: %d\n", *interesting_fd);
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -160,6 +165,9 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
@@ -207,12 +215,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
@@ -298,6 +307,10 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
@@ -329,11 +342,11 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
@@ -516,7 +529,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
return -1;
}
@@ -831,3 +844,11 @@ struct uwsgi_timer *event_queue_ack_timer(int id) {
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+15
View File
@@ -6,6 +6,14 @@ extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
@@ -296,10 +304,17 @@ void uwsgi_ldap_config() {
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
+1 -1
View File
@@ -146,7 +146,7 @@ void uwsgi_lock_init(void *lock) {
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
exit(1);
}
-103
View File
@@ -87,106 +87,3 @@ void *simple_loop(void *arg1) {
//never here
return NULL;
}
#ifdef UWSGI_ASYNC
void complex_loop() {
int current_async_timeout = 0;
int i, j;
int interesting_fd;
struct wsgi_request *wsgi_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
current_async_timeout = async_get_timeout();
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, current_async_timeout, uwsgi.async_events, 64);
async_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
interesting_fd = event_queue_interesting_fd(uwsgi.async_events, i);
if ( interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
// async system is full !!!
goto cycle;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
continue;
}
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_recv(uwsgi.wsgi_req)) {
continue;
}
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
goto reqclear;
}
}
else if ( interesting_fd == uwsgi.sockets_poll[uwsgi.sockets_cnt].fd) {
// wake up cores waiting for signal
char byte;
if (read(uwsgi.sockets_poll[uwsgi.sockets_cnt].fd, &byte, 1) == 1) {
}
else {
uwsgi_error("read()");
}
for(j=0;j<uwsgi.async_current_max;j++) {
wsgi_req = uwsgi.wsgi_requests[j] ;
if (wsgi_req->sigwait) {
wsgi_req->signal_received = byte;
wsgi_req->sigwait = 0;
}
}
}
else {
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
uwsgi.wsgi_req->async_waiting_fd = -1;
uwsgi.wsgi_req->async_waiting_fd_monitored = 0;
uwsgi.wsgi_req->async_timeout = 0;
}
event_queue_del_fd(uwsgi.async_queue, interesting_fd);
}
}
cycle:
uwsgi.wsgi_req = async_loop();
if (uwsgi.wsgi_req == NULL)
continue;
uwsgi.wsgi_req->async_status = UWSGI_OK;
reqclear:
uwsgi_close_request(uwsgi.wsgi_req);
}
}
#endif
+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);
}
+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
+31 -37
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
-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)
+28 -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);
}
+278 -120
View File
@@ -188,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");
@@ -913,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) {
@@ -1170,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) {
@@ -1209,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);
@@ -1369,7 +1370,7 @@ int uwsgi_start(void *v_argv) {
}
}
else {
if (cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
if ((size_t)cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
exit(1);
}
@@ -1378,7 +1379,7 @@ int uwsgi_start(void *v_argv) {
}
if (cache_fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(uwsgi.cache_store);
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
@@ -1577,7 +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) {
@@ -1674,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);
@@ -1781,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) {
@@ -1969,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
@@ -2006,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;
}
@@ -2037,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);
}
@@ -2081,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);
}
}
@@ -2138,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;
@@ -2425,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()");
@@ -2451,6 +2457,9 @@ end:
uwsgi.master_process = 1;
}
}
#else
uwsgi.numproc = 4;
#endif
}
else {
uwsgi.numproc = atoi(optarg);
@@ -2518,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;
}
@@ -3068,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);
}
+56 -32
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,7 +99,9 @@
#ifdef __linux
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <sched.h>
#include <sys/prctl.h>
#include <linux/limits.h>
@@ -206,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;
@@ -491,6 +501,8 @@ struct uwsgi_plugin {
uint16_t (*rpc)(void *, uint8_t, char **, char *);
struct uwsgi_help_item *help;
};
@@ -560,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;
@@ -639,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;
@@ -658,6 +677,8 @@ struct wsgi_request {
int async_plagued;
int suspended;
int *ovector;
size_t post_cl;
char *post_buffering_buf;
@@ -772,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;
@@ -835,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;
@@ -948,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;
@@ -1268,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
@@ -1283,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
@@ -1302,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);
@@ -1375,7 +1388,6 @@ int find_worker_id(pid_t);
void *simple_loop(void *);
void complex_loop(void);
int count_options(struct option *);
@@ -1445,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);
@@ -1627,3 +1639,15 @@ 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);
+9 -1
View File
@@ -71,6 +71,9 @@ def build_uwsgi(uc):
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
epc += "UDEP(%s);" % p
eplc += "ULEP(%s);" % p
epc += "\""
@@ -93,6 +96,10 @@ def build_uwsgi(uc):
print("*** uWSGI compiling embedded plugins ***")
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
path = 'plugins/%s' % p
path = path.rstrip('/')
@@ -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:
+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);
}