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