mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6eed48b28d | ||
|
|
9c5d289098 | ||
|
|
42ab7f23d8 | ||
|
|
c9c2f4232e | ||
|
|
d4f23cc6bd | ||
|
|
b0db67d4d4 | ||
|
|
703cad6715 | ||
|
|
667d67460f | ||
|
|
35cf9ae328 | ||
|
|
c04131af4b | ||
|
|
9cc4db1a12 | ||
|
|
b326500913 | ||
|
|
a26579fcf5 | ||
|
|
a2b9c44433 | ||
|
|
c3b97da1d4 | ||
|
|
048cf0232a | ||
|
|
89c113bee6 | ||
|
|
6b9969a302 | ||
|
|
a6e7513d2a | ||
|
|
8a04f4810f | ||
|
|
1d9d443de0 | ||
|
|
00e5809a71 | ||
|
|
07ba4a040b | ||
|
|
7b319d230a | ||
|
|
641bc2daec | ||
|
|
fbaa30cc08 | ||
|
|
a0c2c9056b | ||
|
|
30ab5fd76b | ||
|
|
30beab4017 | ||
|
|
4ec1493b09 | ||
|
|
e7cbe9709e | ||
|
|
aacaeba525 | ||
|
|
6e4da5efb7 | ||
|
|
87443a4ff2 | ||
|
|
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 | ||
|
|
a068a7eb5b | ||
|
|
aa004c1893 | ||
|
|
9a9c149370 | ||
|
|
9e6e226e4b | ||
|
|
06c2aed0e0 | ||
|
|
df4f610cfc | ||
|
|
64249abae1 | ||
|
|
94f4be58bd | ||
|
|
35987d3741 | ||
|
|
be73e00dde | ||
|
|
a5f272f337 | ||
|
|
406691aa69 |
@@ -11,3 +11,11 @@ b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
|
||||
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
|
||||
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
|
||||
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
|
||||
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
|
||||
|
||||
@@ -1,5 +1,77 @@
|
||||
*** april 2011 ***
|
||||
|
||||
* 0.9.7.2 [20110406]
|
||||
|
||||
- new option --touch-reload <file> to reload the stack on <file> modification
|
||||
--static-map <mountpoint=documentroot> allows to serve static files
|
||||
- fixed --post-limit management
|
||||
- disallow empty socket names
|
||||
- implemented exception_info WSGI support
|
||||
- new options --reload-on-as <n> and --reload-on-rss <n> allows
|
||||
to recycle workers when their memory usage is higher than <n> MB
|
||||
- fixed syslog support (use --log-syslog[=facility] to enable it)
|
||||
- improved plugin loading system
|
||||
- added support for RabbitMQ as event dispatcher for the Emperor
|
||||
- fixed FreeBSD memory report
|
||||
- PSGI plugin can be compiled without ithreads
|
||||
- various Emperor fixes
|
||||
- fixed a regression with setgroups()
|
||||
- support for shared sockets (used in jails within network namespaces)
|
||||
|
||||
*** march 2011 ***
|
||||
|
||||
* 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
|
||||
- fixed multithreading + --max-requests
|
||||
- added support for reference in configuration files
|
||||
|
||||
* 0.9.7-rc1 [20110307]
|
||||
|
||||
- export %v in emperor mode
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,7 +13,7 @@ sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
@@ -21,7 +21,7 @@ xml_implementation = libxml2
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, nagios, rpc, fastrouter, http
|
||||
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
plugin_dir = /usr/lib/uwsgi
|
||||
embedded_plugins = null
|
||||
@@ -1,4 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_plugins
|
||||
|
||||
@@ -330,6 +330,27 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_cache_fix() {
|
||||
|
||||
uint64_t i;
|
||||
|
||||
for(i=0;i< uwsgi.cache_max_items;i++) {
|
||||
// valid record ?
|
||||
if (uwsgi.cache_items[i].keysize) {
|
||||
if (!uwsgi.cache_items[i].prev) {
|
||||
// put value in hash_table
|
||||
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// put this record in unused stack
|
||||
uwsgi.shared->cache_first_available_item = i;
|
||||
uwsgi.shared->cache_unused_stack_ptr++;
|
||||
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
|
||||
|
||||
uint64_t index = 0, last_index = 0 ;
|
||||
@@ -476,7 +497,7 @@ void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && tmp_vallen > 0) {
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, val, vallen);
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -528,6 +549,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// dict
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import django
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
import os
|
||||
import sys
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
|
||||
|
||||
http_port = '8000'
|
||||
socket_addr = None
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for arg in args:
|
||||
k,v = arg.split('=')
|
||||
if k == 'http':
|
||||
if self.http_port:
|
||||
self.http_port = v
|
||||
elif k == 'socket':
|
||||
self.http_port = None
|
||||
self.socket_addr = v
|
||||
|
||||
# load http and python plugin: first the specific version, otherwise try with the generic one
|
||||
if self.http_port:
|
||||
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
|
||||
else:
|
||||
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
|
||||
|
||||
# load the Django WSGI handler
|
||||
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
|
||||
# DJANGO settings
|
||||
if options['settings']:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
|
||||
else:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||
|
||||
# bind the http server to the default port
|
||||
if self.http_port:
|
||||
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
|
||||
elif self.socket_addr:
|
||||
os.environ['UWSGI_SOCKET'] = self.socket_addr
|
||||
|
||||
# map admin static files
|
||||
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
|
||||
# remove sockets/pidfile at exit
|
||||
os.environ['UWSGI_VACUUM'] = '1'
|
||||
# retrieve/set the PythonHome
|
||||
os.environ['UWSGI_PYHOME'] = sys.prefix
|
||||
# increase buffer size a bit
|
||||
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
|
||||
# add threads for concurrency
|
||||
os.environ['UWSGI_THREADS'] = '8'
|
||||
# enable the master process
|
||||
os.environ['UWSGI_MASTER'] = '1'
|
||||
# use uWSGI python module aliasing to fix the PYTHONPATH
|
||||
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
|
||||
# exec the uwsgi binary
|
||||
os.execvp('uwsgi', ('uwsgi',))
|
||||
|
||||
def usage(self, subcomand):
|
||||
return r"""
|
||||
run this project on the uWSGI server
|
||||
|
||||
http=PORT run the embedded http server on port PORT
|
||||
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
|
||||
"""
|
||||
@@ -10,24 +10,29 @@ struct uwsgi_instance {
|
||||
struct uwsgi_instance *ui_next;
|
||||
|
||||
char name[0xff];
|
||||
pid_t pid ;
|
||||
pid_t pid;
|
||||
|
||||
int status;
|
||||
time_t born;
|
||||
time_t last_mod;
|
||||
|
||||
uint64_t respawns;
|
||||
int use_config;
|
||||
|
||||
int pipe[2];
|
||||
int pipe_config[2];
|
||||
|
||||
char *config;
|
||||
uint32_t config_len;
|
||||
};
|
||||
|
||||
struct uwsgi_instance *ui;
|
||||
|
||||
struct uwsgi_instance *emperor_get(char *name) {
|
||||
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while(c_ui->ui_next) {
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
if (!strcmp(c_ui->name, name)) {
|
||||
@@ -50,6 +55,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
// this will destroy the whole uWSGI instance (and workers)
|
||||
close(c_ui->pipe[0]);
|
||||
|
||||
if (c_ui->use_config) {
|
||||
close(c_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
|
||||
|
||||
free(c_ui);
|
||||
@@ -71,32 +80,45 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
if (c_ui->use_config) {
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
c_ui->respawns++;
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
|
||||
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(char *name, time_t born) {
|
||||
void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid ;
|
||||
pid_t pid;
|
||||
char *argv[4];
|
||||
char *uef ;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
|
||||
while(c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
|
||||
memset(n_ui, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
if (config) {
|
||||
n_ui->use_config = 1;
|
||||
n_ui->config = config;
|
||||
n_ui->config_len = config_size;
|
||||
}
|
||||
|
||||
c_ui->ui_next = n_ui;
|
||||
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
|
||||
n_ui->ui_prev = c_ui;
|
||||
@@ -109,6 +131,13 @@ void emperor_add(char *name, time_t born) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
// a new uWSGI instance will start
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
@@ -118,6 +147,16 @@ void emperor_add(char *name, time_t born) {
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -131,10 +170,19 @@ void emperor_add(char *name, time_t born) {
|
||||
}
|
||||
free(uef);
|
||||
|
||||
if (n_ui->use_config) {
|
||||
uef = uwsgi_num2str(n_ui->pipe_config[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
exit(1);
|
||||
}
|
||||
free(uef);
|
||||
}
|
||||
|
||||
uenvs = environ;
|
||||
while(*uenvs) {
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs+13);
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
@@ -156,13 +204,21 @@ void emperor_add(char *name, time_t born) {
|
||||
// close the left side of the pipe
|
||||
close(n_ui->pipe[0]);
|
||||
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
|
||||
// set args
|
||||
argv[0] = uwsgi.binary_path;
|
||||
if (!strcmp(name+(strlen(name)-4), ".xml")) argv[1] = "--xml";
|
||||
if (!strcmp(name+(strlen(name)-4), ".ini")) argv[1] = "--ini";
|
||||
if (!strcmp(name+(strlen(name)-4), ".yml")) argv[1] = "--yaml";
|
||||
if (!strcmp(name+(strlen(name)-5), ".yaml")) argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
argv[1] = "--yaml";
|
||||
argv[2] = name;
|
||||
argv[3] = NULL;
|
||||
// start !!!
|
||||
@@ -173,7 +229,7 @@ void emperor_add(char *name, time_t born) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
clear:
|
||||
clear:
|
||||
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
@@ -196,56 +252,152 @@ void emperor_loop() {
|
||||
glob_t g;
|
||||
int i;
|
||||
struct dirent *de;
|
||||
char *amqp_port;
|
||||
int amqp_fd = -1;
|
||||
char *amqp_routing_key;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
uwsgi_log("*** starting uWSGI Emperor ***\n");
|
||||
|
||||
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
|
||||
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0])-1] == '/' ) {
|
||||
simple_mode = 1;
|
||||
if (chdir(uwsgi.emperor_dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
amqp_port = strchr(uwsgi.emperor_dir, ':');
|
||||
|
||||
if (amqp_port) {
|
||||
reconnect:
|
||||
while(amqp_fd == -1) {
|
||||
uwsgi_log("connecting to AMQP server...\n");
|
||||
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
|
||||
if (amqp_fd < 0) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("subscribing to queue...\n");
|
||||
if (uwsgi_amqp_consume_queue(amqp_fd, "/", "", "uwsgi.emperor", "fanout") < 0) {
|
||||
close(amqp_fd);
|
||||
amqp_fd = -1;
|
||||
goto reconnect;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
|
||||
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
|
||||
simple_mode = 1;
|
||||
if (chdir(uwsgi.emperor_dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ui = &ui_base;
|
||||
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
|
||||
|
||||
if (!i_am_alone) {
|
||||
diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
else if (diedpid > 0) {
|
||||
if (diedpid < 0 || diedpid > 0) {
|
||||
i_am_alone = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (simple_mode) {
|
||||
if (amqp_fd > -1) {
|
||||
uint64_t msgsize;
|
||||
if (uwsgi_waitfd(amqp_fd, 3)) {
|
||||
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
|
||||
|
||||
if (!config) {
|
||||
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
|
||||
close(amqp_fd);
|
||||
amqp_fd = -1;
|
||||
goto reconnect;
|
||||
}
|
||||
|
||||
if (amqp_routing_key) {
|
||||
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
|
||||
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
|
||||
free(amqp_routing_key);
|
||||
|
||||
ui_current = emperor_get(config_file);
|
||||
|
||||
if (ui_current) {
|
||||
free(ui_current->config);
|
||||
ui_current->config = config;
|
||||
ui_current->config_len = msgsize;
|
||||
if (!msgsize) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
else {
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (msgsize > 0) {
|
||||
emperor_add(config_file, time(NULL), config, msgsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(config_file);
|
||||
}
|
||||
else {
|
||||
if (msgsize) {
|
||||
if (msgsize >= 0xff) { free(config); continue; }
|
||||
|
||||
uwsgi_log("%.*s\n", (int)msgsize, config);
|
||||
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
|
||||
free(config);
|
||||
|
||||
if (strncmp(config_file, "http://", 7)) {
|
||||
if (stat(config_file, &st)) {
|
||||
free(config_file);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
free(config_file);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ui_current = emperor_get(config_file);
|
||||
|
||||
if (ui_current) {
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
else {
|
||||
emperor_add(config_file, time(NULL), NULL, 0);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (simple_mode) {
|
||||
DIR *dir = opendir(".");
|
||||
while((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name+(strlen(de->d_name)-4), ".xml") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".ini") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".yml") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-5), ".yaml")
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") || !strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") || !strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") || !strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml")
|
||||
) {
|
||||
|
||||
|
||||
if (strlen(de->d_name) >= 0xff) continue;
|
||||
|
||||
if (stat(de->d_name, &st)) continue;
|
||||
if (strlen(de->d_name) >= 0xff)
|
||||
continue;
|
||||
|
||||
if (stat(de->d_name, &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode)) continue;
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
if (ui_current) {
|
||||
@@ -255,7 +407,7 @@ void emperor_loop() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(de->d_name, st.st_mtime);
|
||||
emperor_add(de->d_name, st.st_mtime, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,33 +419,36 @@ void emperor_loop() {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i=0;i<(int)g.gl_pathc;i++) {
|
||||
if (!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".xml") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".ini") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".yml") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-5), ".yaml")
|
||||
) {
|
||||
for (i = 0; i < (int) g.gl_pathc; i++) {
|
||||
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
|
||||
) {
|
||||
|
||||
|
||||
if (strlen(g.gl_pathv[i]) >= 0xff) continue;
|
||||
if (strlen(g.gl_pathv[i]) >= 0xff)
|
||||
continue;
|
||||
|
||||
if (stat(g.gl_pathv[i], &st)) continue;
|
||||
if (stat(g.gl_pathv[i], &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode)) continue;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
if (ui_current) {
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,8 +456,8 @@ void emperor_loop() {
|
||||
|
||||
ui_current = ui;
|
||||
has_children = 0;
|
||||
while(ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
has_children++;
|
||||
}
|
||||
|
||||
@@ -310,42 +465,48 @@ void emperor_loop() {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
else {
|
||||
// vacuum
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
diedpid = 0;
|
||||
}
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
ui_current = ui;
|
||||
while(ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->pid == diedpid) {
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->status == 1) {
|
||||
if (ui_current->config) free(ui_current->config);
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st)) {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance
|
||||
emperor_add(ui_current->name, ui_current->last_mod);
|
||||
emperor_del(ui_current);
|
||||
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
else {
|
||||
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (ui_current->status == 1) {
|
||||
// remove 'marked for dead' instance
|
||||
if (ui_current->config) free(ui_current->config);
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_current->status == 1) {
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (stat(ui_current->name, &st)) {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amqp_fd < 0)
|
||||
sleep(3);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -37,71 +45,162 @@ int calc_ldap_name(char *name) {
|
||||
return strlen(name) + counter;
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump_ldif() {
|
||||
struct option *aopt, *lopt;
|
||||
struct uwsgi_ldap_entry {
|
||||
int num;
|
||||
char names[1024];
|
||||
int has_arg;
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
lopt = uwsgi.long_options;
|
||||
int i;
|
||||
int counter = 30000;
|
||||
char *ptr = dst;
|
||||
|
||||
memset(dst, 0, 1024);
|
||||
|
||||
strcat(dst, " 'uWSGI");
|
||||
|
||||
ptr+= 7;
|
||||
|
||||
for(i=0;i< (int)strlen(src);i++) {
|
||||
if (src[i] == '-') {
|
||||
i++;
|
||||
*ptr++= toupper( (int) src[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
strcat(dst, "'");
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for(i=0;i<count;i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for(i=0;i<count;i++) {
|
||||
ule = &root[i];
|
||||
if (uwsgi_list_has_str(ule->names, name+1)) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct option *aopt, *lopt;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
char ldap_name[1024];
|
||||
static int counter = 30000000;
|
||||
|
||||
*count = 0;
|
||||
lopt = uwsgi.long_options;
|
||||
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
|
||||
|
||||
entry = search_ldap_cache(ule, ldap_name, *count);
|
||||
|
||||
if (entry) goto next;
|
||||
|
||||
if (aopt->flag) {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = counter;
|
||||
strcpy(entry->names, ldap_name);
|
||||
counter++;
|
||||
*count = *count+1;
|
||||
}
|
||||
else {
|
||||
entry = get_ldap_by_num(ule, aopt->val, *count);
|
||||
if (entry) {
|
||||
strcat(entry->names, ldap_name);
|
||||
}
|
||||
else {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = aopt->val;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count+1;
|
||||
}
|
||||
}
|
||||
|
||||
entry->has_arg = aopt->has_arg;
|
||||
|
||||
next:
|
||||
lopt++;
|
||||
}
|
||||
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump_ldif() {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
|
||||
uwsgi_log("\n");
|
||||
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
|
||||
uwsgi_log("objectClass: olcSchemaConfig\n");
|
||||
uwsgi_log("cn: uwsgi\n");
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
if (aopt->flag) {
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
|
||||
counter++;
|
||||
for(i=0;i<items;i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->has_arg) {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
lopt = uwsgi.long_options;
|
||||
|
||||
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
for(i=0;i<items;i++) {
|
||||
|
||||
uwsgi_log("uWSGI");
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names+1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
uwsgi_log(" $ ");
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
@@ -112,67 +211,47 @@ void uwsgi_ldap_schema_dump_ldif() {
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump() {
|
||||
struct option *aopt, *lopt;
|
||||
|
||||
lopt = uwsgi.long_options;
|
||||
int i;
|
||||
int counter = 30000;
|
||||
int items;
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
for(i=0;i<items;i++) {
|
||||
|
||||
if (aopt->flag) {
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
|
||||
counter++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
|
||||
}
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
entry = &ule[i];
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->has_arg) {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
lopt = uwsgi.long_options;
|
||||
|
||||
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
for(i=0;i<items;i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names+1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("uWSGI");
|
||||
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
uwsgi_log(" $ ");
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
@@ -194,8 +273,6 @@ void uwsgi_ldap_config() {
|
||||
int desired_version = LDAP_VERSION3;
|
||||
int ret;
|
||||
|
||||
struct option *aopt, *lopt;
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (uwsgi.ldap) {
|
||||
@@ -211,6 +288,8 @@ void uwsgi_ldap_config() {
|
||||
uwsgi_log("unable to parse LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
|
||||
|
||||
url_slash = strchr(url, '/');
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
@@ -225,10 +304,17 @@ void uwsgi_ldap_config() {
|
||||
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
|
||||
#endif
|
||||
|
||||
#if LDAP_API_VERSION >= 3000
|
||||
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
|
||||
uwsgi_error("ldap_init()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
|
||||
@@ -255,9 +341,11 @@ void uwsgi_ldap_config() {
|
||||
|
||||
entry = ldap_first_entry(ldp, results);
|
||||
|
||||
int found = 0;
|
||||
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
|
||||
if (!strncmp(attr,"uWSGI",5)) {
|
||||
|
||||
found = 1;
|
||||
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
|
||||
if (!uwsgi_attr) {
|
||||
uwsgi_error("malloc()");
|
||||
@@ -271,7 +359,7 @@ void uwsgi_ldap_config() {
|
||||
#endif
|
||||
bervalues = ldap_get_values_len(ldp, entry, attr);
|
||||
if (bervalues) {
|
||||
// do not free uwsgi_val;
|
||||
// do not free uwsgi_attr/uwsgi_val;
|
||||
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
|
||||
if (!uwsgi_val) {
|
||||
uwsgi_error("malloc()");
|
||||
@@ -281,29 +369,21 @@ void uwsgi_ldap_config() {
|
||||
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
|
||||
uwsgi_val[bervalues[0]->bv_len] = 0;
|
||||
|
||||
lopt = uwsgi.long_options;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp(uwsgi_attr, aopt->name)) {
|
||||
if (aopt->flag) {
|
||||
*aopt->flag = aopt->val;
|
||||
add_exported_option(0, (char*) uwsgi_attr);
|
||||
}
|
||||
else {
|
||||
manage_opt(aopt->val, uwsgi_val);
|
||||
}
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
|
||||
free(bervalues);
|
||||
}
|
||||
else {
|
||||
free(uwsgi_attr);
|
||||
}
|
||||
|
||||
free(bervalues);
|
||||
free(uwsgi_attr);
|
||||
}
|
||||
free(attr);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_log("no uWSGI LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(ber);
|
||||
free(results);
|
||||
|
||||
|
||||
+799
@@ -0,0 +1,799 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define ntohll(x) x
|
||||
#else
|
||||
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
|
||||
#endif
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
|
||||
|
||||
struct amqp_frame_header {
|
||||
|
||||
char type;
|
||||
uint16_t channel;
|
||||
uint32_t size;
|
||||
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct amqp_frame_method {
|
||||
uint16_t class_id;
|
||||
uint16_t method_id;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
|
||||
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
|
||||
|
||||
/*
|
||||
static char *amqp_get_longstr(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t longstr_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&longstr_size, ptr, 4);
|
||||
longstr_size = ntohl(longstr_size);
|
||||
|
||||
if (ptr+4+longstr_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+longstr_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
|
||||
uint8_t str_size;
|
||||
|
||||
// over engeneering...
|
||||
if (ptr+1 > watermark) return NULL;
|
||||
|
||||
str_size = *ptr;
|
||||
|
||||
if (ptr+1+str_size > watermark) return NULL;
|
||||
|
||||
return ptr+1+str_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static char *amqp_get_table(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t table_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&table_size, ptr, 4);
|
||||
|
||||
table_size = ntohl(table_size);
|
||||
|
||||
if (ptr+4+table_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+table_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
|
||||
|
||||
uint16_t tmp_short;
|
||||
|
||||
if (ptr+2 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_short, ptr, 2);
|
||||
|
||||
*sv = ntohs(tmp_short);
|
||||
|
||||
return ptr+2;
|
||||
}
|
||||
|
||||
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
|
||||
|
||||
uint32_t tmp_long;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_long, ptr, 4);
|
||||
|
||||
*lv = ntohl(tmp_long);
|
||||
return ptr+4;
|
||||
}
|
||||
|
||||
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
|
||||
|
||||
uint64_t tmp_longlong;
|
||||
|
||||
if (ptr+8 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_longlong, ptr, 8);
|
||||
|
||||
*llv = ntohll(tmp_longlong);
|
||||
return ptr+8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
|
||||
|
||||
uint32_t size = 4 + 8 + 1;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 80
|
||||
amqp_send(fd, "\x00\x3C\x00\x50", 4);
|
||||
|
||||
// set delivery_tag
|
||||
delivery_tag = htonll(delivery_tag);
|
||||
amqp_send(fd, &delivery_tag, 8);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
|
||||
uint32_t size;
|
||||
struct amqp_frame_header fh;
|
||||
uint64_t delivery_tag;
|
||||
uint64_t current_size = 0;
|
||||
char *ptr;
|
||||
char *watermark;
|
||||
uint16_t sv;
|
||||
|
||||
char *frame = amqp_get_method(fd, 60, 60, &size);
|
||||
if (!frame) return NULL;
|
||||
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
|
||||
// consumer_tag
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
|
||||
// delivery_tag (needed for ack)
|
||||
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
|
||||
// redelivered
|
||||
if (ptr+1 > watermark) goto clear;
|
||||
ptr++;
|
||||
// exchange
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
|
||||
// routing_key
|
||||
if (ptr+1 > watermark) goto clear;
|
||||
uint8_t rk_size = (uint8_t) *ptr;
|
||||
ptr++;
|
||||
if (ptr+rk_size > watermark) goto clear;
|
||||
|
||||
if (rk_size > 0) {
|
||||
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
|
||||
ptr+=rk_size;
|
||||
|
||||
*routing_key = rkey;
|
||||
}
|
||||
else {
|
||||
*routing_key = NULL;
|
||||
}
|
||||
|
||||
char *header = amqp_simple_get_frame(fd, &fh);
|
||||
if (!header) goto clear;
|
||||
|
||||
if (fh.type != 2) goto clear2;
|
||||
|
||||
ptr = header;
|
||||
watermark = ptr+fh.size;
|
||||
|
||||
// header class_id
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
|
||||
// header weight
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
|
||||
// message size;
|
||||
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
|
||||
|
||||
free(frame);
|
||||
free(header);
|
||||
|
||||
char *fullbody = uwsgi_malloc(*msgsize);
|
||||
char *message;
|
||||
|
||||
while(current_size < *msgsize) {
|
||||
message = amqp_simple_get_frame(fd, &fh);
|
||||
if (!message) goto clear;
|
||||
|
||||
if (fh.type != 3) {
|
||||
free(message);
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
if (fh.size+current_size > *msgsize) {
|
||||
free(message);
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
memcpy(fullbody+current_size, message, fh.size);
|
||||
current_size+=fh.size;
|
||||
free(message);
|
||||
}
|
||||
|
||||
if (amqp_send_ack(fd, delivery_tag) < 0) {
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
return fullbody;
|
||||
|
||||
clear3:
|
||||
free(fullbody);
|
||||
return NULL;
|
||||
|
||||
clear2:
|
||||
free(header);
|
||||
clear:
|
||||
free(frame);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
|
||||
uint8_t shortsize = strlen(exchange) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 40 method 10
|
||||
amqp_send(fd, "\x00\x28\x00\x0A", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set exchange name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange, shortsize);
|
||||
|
||||
// set exchange type
|
||||
shortsize = strlen(exchange_type);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange_type, shortsize);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 50 method 20
|
||||
amqp_send(fd, "\x00\x32\x00\x14", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// set exchange name
|
||||
shortsize = strlen(exchange);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange, shortsize);
|
||||
|
||||
// set empty routing-key
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_consume( int fd, char *queue) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 20
|
||||
amqp_send(fd, "\x00\x3C\x00\x14", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// set tag name
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amqp_wait_connection_start(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 10, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int amqp_wait_exchange_declare_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 40, 11, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_basic_consume_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 60, 21, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_channel_open_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 20, 11, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int amqp_wait_queue_bind_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 50, 21, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static char *amqp_wait_queue_declare_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 50, 11, &size);
|
||||
char *queue = NULL;
|
||||
char *ptr;
|
||||
char *watermark;
|
||||
|
||||
if (frame) {
|
||||
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
|
||||
|
||||
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
|
||||
|
||||
free(frame);
|
||||
return queue;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_connection_open_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 41, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_connection_tune(int fd) {
|
||||
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 30, &size);
|
||||
|
||||
uint16_t sv;
|
||||
uint32_t lv;
|
||||
char *watermark ;
|
||||
char *ptr;
|
||||
|
||||
|
||||
if (frame) {
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP max channels: %d\n", sv);
|
||||
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP max frame size: %d\n", lv);
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP heartbeath: %d\n", sv);
|
||||
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
char *ptr = (char *) fh;
|
||||
size_t len = 0, rlen;
|
||||
|
||||
while(len < 7) {
|
||||
rlen = recv(fd, ptr, 7-len, 0);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
return NULL;
|
||||
}
|
||||
len += rlen;
|
||||
ptr += rlen;
|
||||
}
|
||||
|
||||
fh->channel = ntohs(fh->channel);
|
||||
fh->size = ntohl(fh->size);
|
||||
|
||||
len = 0;
|
||||
|
||||
char *frame = malloc(fh->size+1);
|
||||
ptr = frame;
|
||||
|
||||
while(len < fh->size+1) {
|
||||
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
return NULL;
|
||||
}
|
||||
len += rlen;
|
||||
ptr += rlen;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
|
||||
|
||||
struct amqp_frame_header fh;
|
||||
struct amqp_frame_method *fm;
|
||||
|
||||
char *frame = amqp_simple_get_frame(fd, &fh);
|
||||
if (!frame) return NULL;
|
||||
|
||||
if (fh.type != 1) goto clear;
|
||||
|
||||
fm = (struct amqp_frame_method *) frame;
|
||||
fm->class_id = ntohs(fm->class_id);
|
||||
fm->method_id = ntohs(fm->method_id);
|
||||
|
||||
if (fm->class_id != class_id) goto clear;
|
||||
if (fm->method_id != method_id) goto clear;
|
||||
|
||||
*size = fh.size;
|
||||
return frame;
|
||||
|
||||
clear:
|
||||
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int amqp_send_channel_open(int fd, uint16_t id) {
|
||||
|
||||
uint32_t size = 4 + 1;
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 20 method 10
|
||||
amqp_send(fd, "\x00\x14\x00\x0A", 4);
|
||||
|
||||
amqp_send(fd, "\0", 1);
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amqp_send_connection_open(int fd, char *vhost) {
|
||||
|
||||
uint8_t shortsize = strlen(vhost);
|
||||
uint32_t size = 4 + 1 +strlen(vhost) + 2;
|
||||
size = htonl(size);
|
||||
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 28
|
||||
amqp_send(fd, "\x00\x0A\x00\x28", 4);
|
||||
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, vhost, strlen(vhost));
|
||||
|
||||
shortsize = 0;
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
|
||||
|
||||
uint32_t size = 4 + 2 + 4 + 2;
|
||||
size = htonl(size);
|
||||
|
||||
max_chan = htons(max_chan);
|
||||
max_frame_size = htonl(max_frame_size);
|
||||
heartbeat = htons(heartbeat);
|
||||
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 15
|
||||
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
|
||||
|
||||
amqp_send(fd, &max_chan, 2);
|
||||
amqp_send(fd, &max_frame_size, 4);
|
||||
amqp_send(fd, &heartbeat, 2);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_declare(int fd, char *queue) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 50 method 10
|
||||
amqp_send(fd, "\x00\x32\x00\x0A", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *amqp_get_queue(int fd, char *queue) {
|
||||
|
||||
if (amqp_send_queue_declare(fd, queue) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return amqp_wait_queue_declare_ok(fd);
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
|
||||
|
||||
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
|
||||
uint8_t shortsize ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 11
|
||||
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
|
||||
|
||||
// send empty client properties
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send mechanism short string
|
||||
shortsize = strlen(mech);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, mech, strlen(mech));
|
||||
|
||||
// send sasl response
|
||||
size = htonl(sasl_response_size);
|
||||
amqp_send(fd, &size, 4);
|
||||
amqp_send(fd, sasl_response, sasl_response_size);
|
||||
|
||||
// send locale
|
||||
shortsize = strlen(locale);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, locale, strlen(locale));
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *queue, char *exchange, char *exchange_type) {
|
||||
|
||||
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_connection_start(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.start\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.start-ok\n");
|
||||
if (amqp_send_connection_start_ok(fd, "PLAIN", "\0guest\0guest", 12, "en_US") < 0) {
|
||||
uwsgi_log("AMQP error sending Connection.start-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_connection_tune(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.tune\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.tune-ok\n");
|
||||
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
|
||||
uwsgi_log("AMQP error sending Connection.tune-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.open\n");
|
||||
if (amqp_send_connection_open(fd, vhost) < 0) {
|
||||
uwsgi_log("AMQP error sending Connection.open\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_connection_open_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Channel.open\n");
|
||||
if (amqp_send_channel_open(fd, 1) < 0) {
|
||||
uwsgi_log("AMQP error sending Channel.open\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_channel_open_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
queue = amqp_get_queue(fd, queue);
|
||||
if (!queue) {
|
||||
uwsgi_log("AMQP error sending Queue.declare\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (exchange) {
|
||||
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
|
||||
uwsgi_log("AMQP error sending Exchange.declare\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_exchange_declare_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
|
||||
uwsgi_log("AMQP error sending Queue.bind\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_queue_bind_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (amqp_send_queue_consume(fd, queue) < 0) {
|
||||
uwsgi_log("AMQP error sending Basic.consume\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_basic_consume_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(queue);
|
||||
return 0;
|
||||
}
|
||||
+379
@@ -0,0 +1,379 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
#ifndef VETH_INFO_PEER
|
||||
# define VETH_INFO_PEER 1
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_nl_req {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct ifinfomsg ifinfomsg;
|
||||
};
|
||||
|
||||
struct uwsgi_nl_ipreq {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct ifaddrmsg ifaddrmsg;
|
||||
};
|
||||
|
||||
struct uwsgi_nl_rtreq {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct rtmsg rtmsg;
|
||||
};
|
||||
|
||||
int uwsgi_nl_send(struct nlmsghdr *);
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
unr->ifinfomsg.ifi_family = AF_UNSPEC;
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWLINK;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
|
||||
uni->ifaddrmsg.ifa_family = AF_INET;
|
||||
uni->ifaddrmsg.ifa_scope = 0;
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWADDR;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
|
||||
unr->rtmsg.rtm_family = AF_INET;
|
||||
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
|
||||
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
|
||||
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
unr->rtmsg.rtm_type = RTN_UNICAST;
|
||||
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWROUTE;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
struct in_addr oa;
|
||||
struct in_addr ga;
|
||||
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
|
||||
|
||||
if (inet_pton(AF_INET, src, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, dst, &oa) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, gw, &ga) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_PREFSRC;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_DST;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_GATEWAY;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
unr->rtmsg.rtm_src_len = 0;
|
||||
unr->rtmsg.rtm_dst_len = dst_prefix;
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_netlink_gw(char *iface, char *ip) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
uint32_t zero = 0;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
if (inet_pton(AF_INET, ip, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_GATEWAY;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_DST;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &zero, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_OIF;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(int));
|
||||
memcpy(RTA_DATA(rta), &index, sizeof(int));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
|
||||
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
uni->ifaddrmsg.ifa_index = index;
|
||||
uni->ifaddrmsg.ifa_prefixlen = prefix;
|
||||
|
||||
if (inet_pton(AF_INET, ip, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFA_LOCAL;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
|
||||
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFA_ADDRESS;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
|
||||
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
struct rtattr *rta;
|
||||
|
||||
int index = if_nametoindex(veth1);
|
||||
if (!index) return -1;
|
||||
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_NET_NS_PID;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
|
||||
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_netlink_ifup(char *iface) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
unr->ifinfomsg.ifi_change |= IFF_UP;
|
||||
unr->ifinfomsg.ifi_flags |= IFF_UP;
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_netlink_del(char *iface) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
nlmsg->nlmsg_type = RTM_DELLINK;
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_netlink_veth(char *veth0, char *veth1) {
|
||||
|
||||
struct rtattr *rta, *rta0, *rta1, *rta2;
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
|
||||
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
// IFLA_LINKINFO
|
||||
rta0 = NLMSG_TAIL(nlmsg);
|
||||
rta0->rta_type = IFLA_LINKINFO;
|
||||
rta0->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
|
||||
|
||||
// IFLA_INFO_KIND
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_INFO_KIND;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), "veth", 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
// IFLA_INFO_DATA
|
||||
rta1 = NLMSG_TAIL(nlmsg);
|
||||
rta1->rta_type = IFLA_INFO_DATA;
|
||||
rta1->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
|
||||
|
||||
// VETH_INFO_PEER
|
||||
rta2 = NLMSG_TAIL(nlmsg);
|
||||
rta2->rta_type = VETH_INFO_PEER;
|
||||
rta2->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
|
||||
|
||||
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
|
||||
|
||||
// IFLA_IFNAME
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_IFNAME;
|
||||
rta->rta_len = RTA_LENGTH(strlen(veth1));
|
||||
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
|
||||
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
|
||||
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
|
||||
|
||||
// IFLA_IFNAME
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_IFNAME;
|
||||
rta->rta_len = RTA_LENGTH(strlen(veth0));
|
||||
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
|
||||
|
||||
struct sockaddr_nl nladdr;
|
||||
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*)nlmsg,
|
||||
.iov_len = nlmsg->nlmsg_len,
|
||||
};
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
int ret;
|
||||
int nlfd;
|
||||
|
||||
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
|
||||
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (nlfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sendmsg(nlfd, &msg, 0);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return -1;
|
||||
}
|
||||
ret = recvmsg(nlfd, &msg, 0);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("recvmsg()");
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
|
||||
ret = err->error;
|
||||
}
|
||||
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* function written by Ben Taylor (found in the qemu-devel list) */
|
||||
|
||||
#include "../uwsgi.h"
|
||||
|
||||
time_t timegm(struct tm *t) {
|
||||
time_t tl, tb;
|
||||
struct tm *tg;
|
||||
|
||||
tl = mktime (t);
|
||||
if (tl == -1) {
|
||||
t->tm_hour--;
|
||||
tl = mktime (t);
|
||||
if (tl == -1)
|
||||
return -1; /* can't deal with output from strptime */
|
||||
|
||||
tl += 3600;
|
||||
}
|
||||
tg = gmtime (&tl);
|
||||
tg->tm_isdst = 0;
|
||||
tb = mktime (tg);
|
||||
if (tb == -1) {
|
||||
tg->tm_hour--;
|
||||
tb = mktime (tg);
|
||||
if (tb == -1)
|
||||
return -1; /* can't deal with output from gmtime */
|
||||
tb += 3600;
|
||||
}
|
||||
return (tl - (tb - tl));
|
||||
}
|
||||
@@ -134,21 +134,17 @@ void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
#define UWSGI_LOCK_SIZE 8
|
||||
#define UWSGI_RWLOCK_SIZE 8
|
||||
|
||||
static int lock_counter = 0;
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
|
||||
char filename[17];
|
||||
FILE *tf = tmpfile();
|
||||
int fd;
|
||||
|
||||
if (snprintf(filename, 17, ".uwsgiflock%d", lock_counter) < 0) {
|
||||
uwsgi_log("unable to create lock %d\n", lock_counter);
|
||||
}
|
||||
|
||||
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("open()");
|
||||
if (!tf) {
|
||||
uwsgi_error_open("temp lock file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = fileno(tf);
|
||||
|
||||
memcpy(lock, &fd, sizeof(int));
|
||||
}
|
||||
|
||||
@@ -169,7 +169,11 @@ void get_memusage() {
|
||||
kvm_t *kv;
|
||||
int cnt;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
|
||||
#else
|
||||
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
||||
#endif
|
||||
if (kv) {
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,6 +42,7 @@ void uwsgi_subscribe(char *subscription) {
|
||||
if (!udp_address) return;
|
||||
|
||||
char *subscription_key = strchr(udp_address+1, ':');
|
||||
if (!subscription_key) return;
|
||||
udp_address = uwsgi_concat2n(subscription, subscription_key-subscription, "", 0);
|
||||
|
||||
ssb = subscrbuf;
|
||||
@@ -146,8 +147,6 @@ void master_loop(char **argv, char **environ) {
|
||||
uint8_t uwsgi_signal;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
struct pollfd uwsgi_poll[2];
|
||||
int uwsgi_poll_size = 0;
|
||||
struct sockaddr_in udp_client;
|
||||
socklen_t udp_len;
|
||||
char udp_client_addr[16];
|
||||
@@ -165,6 +164,10 @@ void master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
int snmp_fd = -1;
|
||||
#endif
|
||||
|
||||
int i=0,j;
|
||||
int rlen;
|
||||
|
||||
@@ -206,21 +209,16 @@ void master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_UDP
|
||||
if (uwsgi.udp_socket) {
|
||||
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
|
||||
uwsgi_poll[uwsgi_poll_size].fd = udp_fd;
|
||||
if (uwsgi_poll[uwsgi_poll_size].fd < 0) {
|
||||
if (udp_fd < 0) {
|
||||
uwsgi_log( "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "UDP server enabled.\n");
|
||||
uwsgi_poll[uwsgi_poll_size].events = POLLIN;
|
||||
uwsgi_poll_size++;
|
||||
event_queue_add_fd_read(uwsgi.master_queue, udp_fd);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (uwsgi.cluster) {
|
||||
uwsgi_poll[uwsgi_poll_size].fd = uwsgi.cluster_fd;
|
||||
uwsgi_poll[uwsgi_poll_size].events = POLLIN;
|
||||
uwsgi_poll_size++;
|
||||
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.cluster_fd);
|
||||
|
||||
@@ -288,12 +286,28 @@ void master_loop(char **argv, char **environ) {
|
||||
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
|
||||
}
|
||||
}
|
||||
uwsgi_log( "filling SNMP table...");
|
||||
|
||||
uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
|
||||
|
||||
uwsgi_log( "done\n");
|
||||
for(i=0;i<uwsgi.numproc;i++) {
|
||||
uwsgi.shared->snmp_gvalue[30+i].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_gvalue[30+i].val = &uwsgi.workers[i+1].requests;
|
||||
}
|
||||
|
||||
if (uwsgi.snmp_addr) {
|
||||
snmp_fd = bind_to_udp(uwsgi.snmp_addr, 0, 0);
|
||||
if (snmp_fd < 0) {
|
||||
uwsgi_log( "unable to bind to udp socket. SNMP service will be disabled.\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "SNMP server enabled on %s\n", uwsgi.snmp_addr);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, snmp_fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "SNMP agent enabled.\n");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -317,6 +331,31 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi_subscribe(uwsgi.subscriptions[i]);
|
||||
}
|
||||
|
||||
// sync the cache store if needed
|
||||
if (uwsgi.cache_store && uwsgi.cache_filesize) {
|
||||
if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) {
|
||||
uwsgi_error("msync()");
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.queue_store && uwsgi.queue_filesize) {
|
||||
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
|
||||
uwsgi_error("msync()");
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.touch_reload) {
|
||||
struct stat tr_st;
|
||||
if (stat(uwsgi.touch_reload, &tr_st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
|
||||
uwsgi.touch_reload = NULL;
|
||||
}
|
||||
else {
|
||||
uwsgi.last_touch_reload_mtime = tr_st.st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
|
||||
|
||||
@@ -368,18 +407,24 @@ void master_loop(char **argv, char **environ) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log( "binary reloading uWSGI...\n");
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log( "closing all non-uwsgi socket fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf(_SC_OPEN_MAX));
|
||||
for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
|
||||
int found = 0;
|
||||
for(j=0;j<uwsgi.sockets_cnt;j++) {
|
||||
if (i == uwsgi.sockets[j].fd) {
|
||||
uwsgi_log("found fd %d\n", i);
|
||||
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, j, uwsgi.sockets[j].name);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@@ -590,8 +635,7 @@ void master_loop(char **argv, char **environ) {
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
uwsgi.has_emperor = 0;
|
||||
kill_them_all(0);
|
||||
if (!uwsgi.to_hell) kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
@@ -601,11 +645,26 @@ void master_loop(char **argv, char **environ) {
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
uwsgi.has_emperor = 0;
|
||||
kill_them_all(0);
|
||||
if (!uwsgi.to_hell) kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SNMP
|
||||
if (uwsgi.snmp_addr && interesting_fd == snmp_fd) {
|
||||
udp_len = sizeof(udp_client);
|
||||
rlen = recvfrom(snmp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
if (uwsgi.udp_socket && interesting_fd == udp_fd) {
|
||||
@@ -709,7 +768,6 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi_lock(uwsgi.fmon_table_lock);
|
||||
for(i=0;i<ushared->files_monitored_cnt;i++) {
|
||||
if (ushared->files_monitored[i].registered) {
|
||||
uwsgi_log("fmon check %d == %d\n", interesting_fd, ushared->files_monitored[i].fd) ;
|
||||
if (interesting_fd == ushared->files_monitored[i].fd) {
|
||||
struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd);
|
||||
// now call the file_monitor handler
|
||||
@@ -905,15 +963,43 @@ void master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// resubscribe every 10 cycles
|
||||
if (uwsgi.subscriptions_cnt > 0 && (master_cycles % 10) == 0) {
|
||||
if (uwsgi.subscriptions_cnt > 0 && ((master_cycles % 10) == 0 || master_cycles == 1)) {
|
||||
for(i=0;i<uwsgi.subscriptions_cnt;i++) {
|
||||
uwsgi_subscribe(uwsgi.subscriptions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
if (uwsgi.cache_store && uwsgi.cache_filesize && uwsgi.cache_store_sync && ((master_cycles % uwsgi.cache_store_sync) == 0)) {
|
||||
if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) {
|
||||
uwsgi_error("msync()");
|
||||
}
|
||||
}
|
||||
|
||||
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()");
|
||||
}
|
||||
}
|
||||
|
||||
// check touch_reload
|
||||
if (uwsgi.touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
struct stat tr_st;
|
||||
if (stat(uwsgi.touch_reload, &tr_st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
|
||||
uwsgi.touch_reload = NULL;
|
||||
}
|
||||
else {
|
||||
if (tr_st.st_mtime > uwsgi.last_touch_reload_mtime) {
|
||||
uwsgi_log("*** %s has been touched... grace them all !!! ***\n");
|
||||
grace_them_all(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now check for lb pool
|
||||
|
||||
|
||||
@@ -1001,7 +1087,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");
|
||||
@@ -1036,28 +1124,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
|
||||
|
||||
@@ -2,25 +2,6 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void embed_plugins() {
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_PSGI
|
||||
if (uwsgi.plugin_arg_psgi)
|
||||
uwsgi_load_plugin(5, "psgi_plugin.so", uwsgi.plugin_arg_psgi, 0);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_LUA
|
||||
if (uwsgi.plugin_arg_lua)
|
||||
uwsgi_load_plugin(6, "lua_plugin.so", uwsgi.plugin_arg_lua, 0);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_RACK
|
||||
if (uwsgi.plugin_arg_rack)
|
||||
uwsgi_load_plugin(7, "rack_plugin.so", uwsgi.plugin_arg_rack, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
|
||||
|
||||
void *plugin_handle;
|
||||
@@ -28,6 +9,59 @@ int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
|
||||
char *plugin_name;
|
||||
char *plugin_entry_symbol;
|
||||
struct uwsgi_plugin *up;
|
||||
int i;
|
||||
|
||||
char *colon = strchr(plugin, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
check:
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gp_cnt;i++) {
|
||||
|
||||
if (uwsgi.gp[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
plugin = colon+1;
|
||||
colon[0] = ':';
|
||||
colon = NULL;
|
||||
goto check;
|
||||
}
|
||||
|
||||
if (absolute) {
|
||||
plugin_name = malloc(strlen(plugin) + 1);
|
||||
@@ -58,7 +92,4 @@ int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -447,6 +447,7 @@ int erlang_opt(int i, char *optarg) {
|
||||
|
||||
struct uwsgi_plugin erlang_plugin = {
|
||||
|
||||
.name = "erlang",
|
||||
.options = erlang_options,
|
||||
.manage_opt = erlang_opt,
|
||||
.init = erlang_init,
|
||||
|
||||
+187
-81
@@ -12,10 +12,12 @@
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#define LONG_ARGS_FASTROUTER 150001
|
||||
#define LONG_ARGS_FASTROUTER_EVENTS 150002
|
||||
#define LONG_ARGS_FASTROUTER_USE_PATTERN 150003
|
||||
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
|
||||
#define LONG_ARGS_FASTROUTER 150001
|
||||
#define LONG_ARGS_FASTROUTER_EVENTS 150002
|
||||
#define LONG_ARGS_FASTROUTER_USE_PATTERN 150003
|
||||
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
|
||||
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
|
||||
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
|
||||
|
||||
#define FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
@@ -23,6 +25,9 @@
|
||||
#define FASTROUTER_STATUS_RECV_VARS 3
|
||||
#define FASTROUTER_STATUS_RESPONSE 4
|
||||
|
||||
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
|
||||
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
|
||||
|
||||
struct uwsgi_fastrouter {
|
||||
char *socket_name;
|
||||
int use_cache;
|
||||
@@ -33,6 +38,13 @@ struct uwsgi_fastrouter {
|
||||
|
||||
char *base;
|
||||
int base_len;
|
||||
|
||||
char *subscription_server;
|
||||
struct uwsgi_dict *subscription_dict;
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
} ufr;
|
||||
|
||||
struct option fastrouter_options[] = {
|
||||
@@ -41,11 +53,27 @@ struct option fastrouter_options[] = {
|
||||
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
|
||||
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
|
||||
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
|
||||
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
|
||||
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;
|
||||
|
||||
if (!uwsgi_strncmp("key", 3, key, keylen)) {
|
||||
usr->key = val;
|
||||
usr->keylen = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("address", 7, key, keylen)) {
|
||||
usr->address = val;
|
||||
usr->address_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
struct fastrouter_session {
|
||||
|
||||
int fd;
|
||||
@@ -62,9 +90,53 @@ struct fastrouter_session {
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
struct uwsgi_subscriber_name *un;
|
||||
int pass_fd;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
};
|
||||
|
||||
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
|
||||
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
if (fr_session->instance_fd != -1) {
|
||||
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
fr_session->un->len = 0;
|
||||
}
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
}
|
||||
del_timeout(fr_session);
|
||||
free(fr_session);
|
||||
}
|
||||
|
||||
static struct uwsgi_rb_timer *reset_timeout(struct fastrouter_session *fr_session) {
|
||||
del_timeout(fr_session);
|
||||
return add_timeout(fr_session);
|
||||
}
|
||||
|
||||
static void expire_timeouts(struct fastrouter_session **fr_table) {
|
||||
|
||||
time_t current = time(NULL);
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for(;;) {
|
||||
urbt = uwsgi_min_rb_timer(ufr.timeouts);
|
||||
if (urbt == NULL) return;
|
||||
|
||||
if (urbt->key <= current) {
|
||||
close_session(fr_table, (struct fastrouter_session *)urbt->data);
|
||||
uwsgi_log("timeout !!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
struct fastrouter_session *fr_session = (struct fastrouter_session *) data;
|
||||
@@ -91,18 +163,27 @@ struct fastrouter_session *alloc_fr_session() {
|
||||
void fastrouter_loop() {
|
||||
|
||||
int fr_queue;
|
||||
int fr_server;
|
||||
int fr_server = -1;
|
||||
int nevents;
|
||||
int interesting_fd;
|
||||
int new_connection;
|
||||
ssize_t len;
|
||||
int i;
|
||||
|
||||
time_t delta;
|
||||
char bbuf[UMAX16];
|
||||
|
||||
char *tcp_port;
|
||||
|
||||
char *tmp_socket_name;
|
||||
int tmp_socket_name_len;
|
||||
|
||||
struct uwsgi_subscribe_req usr;
|
||||
|
||||
char *magic_table[0xff];
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
|
||||
void *events;
|
||||
struct msghdr msg;
|
||||
union {
|
||||
@@ -123,11 +204,32 @@ void fastrouter_loop() {
|
||||
int soopt;
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
int ufr_subserver = -1;
|
||||
|
||||
for(i=0;i<2048;i++) {
|
||||
fr_table[i] = NULL;
|
||||
}
|
||||
|
||||
fr_server = bind_to_tcp(ufr.socket_name, uwsgi.listen_queue, ufr.socket_name);
|
||||
if (ufr.socket_name[0] == '=') {
|
||||
int shared_socket = atoi(ufr.socket_name+1);
|
||||
if (shared_socket >= 0 && shared_socket < uwsgi.shared_sockets_cnt) {
|
||||
if (uwsgi.shared_sockets[shared_socket].name) {
|
||||
fr_server = uwsgi.shared_sockets[shared_socket].fd;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
tcp_port = strchr(ufr.socket_name, ':');
|
||||
if (tcp_port) {
|
||||
fr_server = bind_to_tcp(ufr.socket_name, uwsgi.listen_queue, tcp_port);
|
||||
}
|
||||
else {
|
||||
fr_server = bind_to_unix(ufr.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
}
|
||||
|
||||
fr_queue = event_queue_init();
|
||||
|
||||
@@ -135,13 +237,38 @@ void fastrouter_loop() {
|
||||
|
||||
event_queue_add_fd_read(fr_queue, fr_server);
|
||||
|
||||
if (ufr.subscription_server) {
|
||||
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
|
||||
event_queue_add_fd_read(fr_queue, ufr_subserver);
|
||||
ufr.subscription_dict = uwsgi_dict_create(30, 0);
|
||||
}
|
||||
|
||||
if (ufr.pattern) {
|
||||
init_magic_table(magic_table);
|
||||
}
|
||||
|
||||
ufr.timeouts = uwsgi_init_rb_timer();
|
||||
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
|
||||
|
||||
for (;;) {
|
||||
|
||||
nevents = event_queue_wait_multi(fr_queue, -1, events, ufr.nevents);
|
||||
min_timeout = uwsgi_min_rb_timer(ufr.timeouts);
|
||||
if (min_timeout == NULL ) {
|
||||
delta = -1;
|
||||
}
|
||||
else {
|
||||
delta = min_timeout->key - time(NULL);
|
||||
if (delta <= 0) {
|
||||
expire_timeouts(fr_table);
|
||||
delta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nevents = event_queue_wait_multi(fr_queue, delta, events, ufr.nevents);
|
||||
|
||||
if (nevents == 0) {
|
||||
expire_timeouts(fr_table);
|
||||
}
|
||||
|
||||
for (i=0;i<nevents;i++) {
|
||||
|
||||
@@ -161,11 +288,25 @@ void fastrouter_loop() {
|
||||
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
|
||||
fr_table[new_connection]->h_pos = 0;
|
||||
fr_table[new_connection]->pos = 0;
|
||||
fr_table[new_connection]->instance_failed = 0;
|
||||
fr_table[new_connection]->instance_address_len = 0;
|
||||
|
||||
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
|
||||
|
||||
event_queue_add_fd_read(fr_queue, new_connection);
|
||||
|
||||
}
|
||||
else if (interesting_fd == ufr_subserver) {
|
||||
len = recv(ufr_subserver, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(fr_queue, ufr_subserver);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
|
||||
uwsgi_add_subscriber(ufr.subscription_dict, usr.key, usr.keylen, usr.address, usr.address_len);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fr_session = fr_table[interesting_fd];
|
||||
|
||||
@@ -173,25 +314,19 @@ void fastrouter_loop() {
|
||||
if (fr_session == NULL) continue;
|
||||
|
||||
if (event_queue_interesting_fd_has_error(events, i)) {
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
if (fr_session->instance_fd != -1) {
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
}
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
fr_session->timeout = reset_timeout(fr_session);
|
||||
|
||||
switch(fr_session->status) {
|
||||
|
||||
case FASTROUTER_STATUS_RECV_HDR:
|
||||
len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->h_pos += len;
|
||||
@@ -208,24 +343,18 @@ void fastrouter_loop() {
|
||||
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->pos += len;
|
||||
if (fr_session->pos == fr_session->uh.pktsize) {
|
||||
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->hostname_len == 0) {
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -240,6 +369,13 @@ void fastrouter_loop() {
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = tmp_socket_name;
|
||||
}
|
||||
else if (ufr.subscription_server) {
|
||||
fr_session->un = uwsgi_get_subscriber(ufr.subscription_dict, fr_session->hostname, fr_session->hostname_len);
|
||||
if (fr_session->un && fr_session->un->len) {
|
||||
fr_session->instance_address = fr_session->un->name;
|
||||
fr_session->instance_address_len = fr_session->un->len;
|
||||
}
|
||||
}
|
||||
else if (ufr.base) {
|
||||
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
@@ -248,9 +384,7 @@ void fastrouter_loop() {
|
||||
|
||||
// no address found
|
||||
if (!fr_session->instance_address_len) {
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -262,9 +396,11 @@ void fastrouter_loop() {
|
||||
if (tmp_socket_name) free(tmp_socket_name);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
free(fr_session);
|
||||
if (ufr.subscription_server) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
fr_session->un->len = 0;
|
||||
}
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -283,21 +419,15 @@ void fastrouter_loop() {
|
||||
|
||||
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
uwsgi_error("getsockopt()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (soopt) {
|
||||
uwsgi_log("unable to connect() to uwsgi instance: %s\n", strerror(soopt));
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -327,26 +457,17 @@ void fastrouter_loop() {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (writev(fr_session->instance_fd, iov, 2) < 0) {
|
||||
uwsgi_error("writev()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -359,11 +480,7 @@ void fastrouter_loop() {
|
||||
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0) uwsgi_error("recv()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -371,11 +488,7 @@ void fastrouter_loop() {
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0) uwsgi_error("send()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -386,11 +499,7 @@ void fastrouter_loop() {
|
||||
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0) uwsgi_error("recv()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -399,11 +508,7 @@ void fastrouter_loop() {
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0) uwsgi_error("send()");
|
||||
close(fr_session->fd);
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -415,13 +520,7 @@ void fastrouter_loop() {
|
||||
// fallback to destroy !!!
|
||||
default:
|
||||
uwsgi_log("default action\n");
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
if (fr_session->instance_fd != -1) {
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
}
|
||||
free(fr_session);
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -457,6 +556,9 @@ int fastrouter_opt(int i, char *optarg) {
|
||||
case LONG_ARGS_FASTROUTER:
|
||||
ufr.socket_name = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
|
||||
ufr.subscription_server = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_EVENTS:
|
||||
ufr.nevents = atoi(optarg);
|
||||
return 1;
|
||||
@@ -470,6 +572,9 @@ int fastrouter_opt(int i, char *optarg) {
|
||||
// optimization
|
||||
ufr.base_len = strlen(ufr.base);
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_TIMEOUT:
|
||||
ufr.socket_timeout = atoi(optarg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -477,6 +582,7 @@ int fastrouter_opt(int i, char *optarg) {
|
||||
|
||||
struct uwsgi_plugin fastrouter_plugin = {
|
||||
|
||||
.name = "fastrouter",
|
||||
.options = fastrouter_options,
|
||||
.manage_opt = fastrouter_opt,
|
||||
.init = fastrouter_init,
|
||||
|
||||
@@ -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']
|
||||
+54
-3
@@ -145,13 +145,13 @@ struct http_session {
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
};
|
||||
|
||||
struct uwsgi_rb_timer *reset_timeout(struct http_session *uhttp_session) {
|
||||
static struct uwsgi_rb_timer *reset_timeout(struct http_session *uhttp_session) {
|
||||
|
||||
del_timeout(uhttp_session);
|
||||
return add_timeout(uhttp_session);
|
||||
}
|
||||
|
||||
void close_session(struct http_session **uhttp_table, struct http_session *uhttp_session) {
|
||||
static void close_session(struct http_session **uhttp_table, struct http_session *uhttp_session) {
|
||||
|
||||
close(uhttp_session->fd);
|
||||
uhttp_table[uhttp_session->fd] = NULL;
|
||||
@@ -170,7 +170,7 @@ void close_session(struct http_session **uhttp_table, struct http_session *uhttp
|
||||
|
||||
}
|
||||
|
||||
void expire_timeouts(struct http_session **uhttp_table) {
|
||||
static void expire_timeouts(struct http_session **uhttp_table) {
|
||||
|
||||
time_t current = time(NULL);
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
@@ -429,12 +429,14 @@ void http_loop() {
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
void *events;
|
||||
#ifndef __sun__
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control [CMSG_SPACE (sizeof (int))];
|
||||
} msg_control;
|
||||
struct cmsghdr *cmsg;
|
||||
#endif
|
||||
|
||||
union uwsgi_sockaddr uhttp_addr;
|
||||
socklen_t uhttp_addr_len = sizeof(struct sockaddr_un);
|
||||
@@ -501,6 +503,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 +536,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 +563,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++) {
|
||||
@@ -695,6 +707,8 @@ void http_loop() {
|
||||
uhttp_session->iov_len++;
|
||||
}
|
||||
|
||||
|
||||
#ifndef __sun__
|
||||
// fd passing: PERFORMANCE EXTREME BOOST !!!
|
||||
if (uhttp_session->pass_fd && !uhttp_session->remains) {
|
||||
msg.msg_name = NULL;
|
||||
@@ -726,11 +740,33 @@ void http_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
#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 +779,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 +807,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);
|
||||
@@ -838,10 +880,17 @@ int http_init() {
|
||||
uwsgi_log("unable to register the http gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("HTTP router/proxy bound on %s\n", uhttp.socket_name);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -892,8 +941,10 @@ int http_opt(int i, char *optarg) {
|
||||
|
||||
struct uwsgi_plugin http_plugin = {
|
||||
|
||||
.name = "http",
|
||||
.options = http_options,
|
||||
.manage_opt = http_opt,
|
||||
.help = http_help,
|
||||
.init = http_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#undef __USE_GNU
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#define HAS_BOOL 1
|
||||
#include <EXTERN.h>
|
||||
#include <perl.h>
|
||||
#include "XSUB.h"
|
||||
|
||||
@@ -26,8 +26,11 @@ XS(XS_stream)
|
||||
uwsgi_log("type %d\n", SvTYPE(stack));
|
||||
response = (AV* ) SvRV(stack) ;
|
||||
|
||||
|
||||
#ifdef my_perl
|
||||
psgi_response(wsgi_req, my_perl, response);
|
||||
#else
|
||||
psgi_response(wsgi_req, uperl.main, response);
|
||||
#endif
|
||||
|
||||
//mXPUSHp("x", 1);
|
||||
XSRETURN(0);
|
||||
@@ -102,7 +105,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);
|
||||
}
|
||||
|
||||
@@ -146,6 +149,7 @@ void uwsgi_psgi_app() {
|
||||
|
||||
}
|
||||
|
||||
#ifdef my_perl
|
||||
void uwsgi_perl_enable_threads() {
|
||||
|
||||
int i;
|
||||
@@ -192,6 +196,7 @@ void uwsgi_perl_enable_threads() {
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -412,7 +417,9 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
//.magic = uwsgi_perl_magic,
|
||||
//.help = uwsgi_perl_help,
|
||||
#ifdef my_perl
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
#endif
|
||||
.manage_opt = uwsgi_perl_manage_options,
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
.request = uwsgi_perl_request,
|
||||
|
||||
@@ -478,11 +478,13 @@ int py_to_erl(PyObject *pobj, ei_x_buff *x) {
|
||||
ei_x_encode_long(x, PyInt_AsLong(pobj));
|
||||
}
|
||||
else if (PyList_Check(pobj)) {
|
||||
ei_x_encode_list_header(x, PyList_Size(pobj));
|
||||
for (i = 0; i < PyList_Size(pobj); i++) {
|
||||
pobj2 = PyList_GetItem(pobj, i);
|
||||
if (py_to_erl(pobj2, x) < 0) return -1;
|
||||
}
|
||||
if (PyList_Size(pobj) > 0) {
|
||||
ei_x_encode_list_header(x, PyList_Size(pobj));
|
||||
for (i = 0; i < PyList_Size(pobj); i++) {
|
||||
pobj2 = PyList_GetItem(pobj, i);
|
||||
if (py_to_erl(pobj2, x) < 0) return -1;
|
||||
}
|
||||
}
|
||||
ei_x_encode_empty_list(x);
|
||||
}
|
||||
else if (PyTuple_Check(pobj)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -431,6 +439,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
|
||||
quick_callable[strlen(quick_callable) -2 ] = 0;
|
||||
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
|
||||
quick_callable[strlen(quick_callable) -2 ] = '(';
|
||||
if (tmp_callable) {
|
||||
return python_call(tmp_callable, PyTuple_New(0), 0);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -62,7 +85,6 @@ int uwsgi_python_init() {
|
||||
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
|
||||
if (up.home != NULL) {
|
||||
uwsgi_log("Setting PythonHome to %s...\n", up.home);
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wpyhome;
|
||||
wpyhome = malloc((sizeof(wchar_t) * strlen(up.home)) + 2);
|
||||
@@ -76,6 +98,7 @@ int uwsgi_python_init() {
|
||||
#else
|
||||
Py_SetPythonHome(up.home);
|
||||
#endif
|
||||
uwsgi_log("Set PythonHome to %s\n", up.home);
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
@@ -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,15 +990,21 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_plugin python_plugin = {
|
||||
|
||||
.name = "python",
|
||||
.alias = "python",
|
||||
.modifier1 = 0,
|
||||
.init = uwsgi_python_init,
|
||||
.post_fork = uwsgi_python_post_fork,
|
||||
@@ -972,8 +1030,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,19 +262,10 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
uwsgi_log("Invalid WSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.limit_post) {
|
||||
if (wsgi_req->post_cl > uwsgi.limit_post) {
|
||||
uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!up.ignore_script_name) {
|
||||
|
||||
if (!wsgi_req->script_name)
|
||||
@@ -398,8 +383,8 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
#ifdef PYTHREE
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, "ignore");
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, "ignore");
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
|
||||
#else
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
@@ -435,6 +420,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 +466,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
|
||||
}
|
||||
|
||||
|
||||
@@ -14,22 +14,36 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
PyObject *h_key, *h_value;
|
||||
int i, j;
|
||||
struct uwsgi_header uh;
|
||||
PyObject *exc_info = NULL;
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int base = 0;
|
||||
int shift = 0;
|
||||
|
||||
// use writev()
|
||||
// this must be done before headers management
|
||||
if (PyTuple_Size(args) > 2) {
|
||||
exc_info = PyTuple_GetItem(args, 2);
|
||||
if (exc_info && exc_info != Py_None) {
|
||||
PyObject *exc_type = PyTuple_GetItem(exc_info, 0);
|
||||
PyObject *exc_val = PyTuple_GetItem(exc_info, 1);
|
||||
PyObject *exc_tb = PyTuple_GetItem(exc_info, 2);
|
||||
|
||||
// is a Web3 response ?
|
||||
/*
|
||||
if (PyTuple_Size(args) == 3) {
|
||||
shift = 0;
|
||||
}
|
||||
*/
|
||||
if (!exc_type || !exc_val || !exc_tb) {
|
||||
PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
head = PyTuple_GetItem(args, 0+shift);
|
||||
Py_INCREF(exc_type);
|
||||
Py_INCREF(exc_val);
|
||||
Py_INCREF(exc_tb);
|
||||
// in this way, error will be reported to the log
|
||||
PyErr_Restore(exc_type, exc_val, exc_tb);
|
||||
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
head = PyTuple_GetItem(args, 0);
|
||||
if (!head) {
|
||||
goto clear;
|
||||
}
|
||||
@@ -68,7 +82,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,25 +101,22 @@ 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;
|
||||
}
|
||||
|
||||
headers = PyTuple_GetItem(args, 1);
|
||||
if (!headers) goto clear;
|
||||
|
||||
|
||||
headers = PyTuple_GetItem(args, 1+shift);
|
||||
if (!headers) {
|
||||
goto clear;
|
||||
}
|
||||
if (!PyList_Check(headers)) {
|
||||
uwsgi_log( "http headers must be in a python list\n");
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->header_cnt = PyList_Size(headers);
|
||||
|
||||
|
||||
|
||||
if (wsgi_req->header_cnt > uwsgi.max_vars) {
|
||||
wsgi_req->header_cnt = uwsgi.max_vars;
|
||||
}
|
||||
@@ -174,7 +185,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
|
||||
Py_INCREF(up.wsgi_writeout);
|
||||
|
||||
|
||||
return up.wsgi_writeout;
|
||||
|
||||
clear:
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
+257
-22
@@ -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,8 +669,19 @@ 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);
|
||||
if (uwsgi.limit_post) {
|
||||
if (wsgi_req->post_cl > uwsgi.limit_post) {
|
||||
uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
|
||||
@@ -570,19 +705,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,27 +786,25 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
// check if a file named 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);
|
||||
if (!uwsgi_file_serve(wsgi_req, uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// check static-map
|
||||
struct uwsgi_static_map *usm = uwsgi.static_maps;
|
||||
while(usm) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, usm->mountpoint_len, usm->mountpoint);
|
||||
#endif
|
||||
if (!stat(filename, &st)) {
|
||||
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("file %s found\n", filename);
|
||||
#endif
|
||||
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->response_size += uwsgi_sendfile(wsgi_req);
|
||||
wsgi_req->status = 200;
|
||||
free(filename);
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, usm->mountpoint, usm->mountpoint_len)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, usm->document_root, usm->document_root_len, wsgi_req->path_info+usm->mountpoint_len, wsgi_req->path_info_len-usm->mountpoint_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
usm = usm->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1149,3 +1307,80 @@ int uwsgi_simple_send_string(char *socket_name, uint8_t modifier1, uint8_t modif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
|
||||
|
||||
struct stat st;
|
||||
char real_filename[PATH_MAX];
|
||||
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
if (!stat(real_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 0;
|
||||
}
|
||||
}
|
||||
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", real_filename);
|
||||
#endif
|
||||
// no need to set content-type/content-length, they will be fixed by the http server/router
|
||||
|
||||
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);
|
||||
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
wsgi_req->header_cnt = 2;
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, "X-Accel-Redirect: ", 18);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, path_info, path_info_len);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
|
||||
}
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
wsgi_req->header_cnt = 2;
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, "X-Sendfile: ", 12);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, real_filename, strlen(real_filename));
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
|
||||
}
|
||||
else {
|
||||
wsgi_req->header_cnt = 1;
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
|
||||
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.2',
|
||||
description='The uWSGI server',
|
||||
author='Unbit',
|
||||
author_email='info@unbit.it',
|
||||
|
||||
@@ -317,6 +317,26 @@ char *generate_socket_name(char *socket_name) {
|
||||
|
||||
char *new_socket;
|
||||
char *tcp_port;
|
||||
int i;
|
||||
char *ptr = socket_name;
|
||||
|
||||
// ltrim spaces
|
||||
|
||||
for(i=0;i<(int)strlen(socket_name);i++) {
|
||||
if (isspace((int)socket_name[i])) {
|
||||
ptr++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
socket_name = ptr;
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
uwsgi_log("invalid/empty uwsgi socket name\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tcp_port = strchr(socket_name, ':');
|
||||
if (!tcp_port) return socket_name;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
if (unlink(spool_filename)) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_log("something horrible happened !!! check your spooler ASAP !!!\n");
|
||||
goodbye_cruel_world();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
-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
|
||||
@@ -182,12 +188,18 @@ void logto(char *logfile) {
|
||||
|
||||
void log_syslog(char *syslog_opts) {
|
||||
|
||||
if (syslog_opts == NULL) {
|
||||
syslog_opts= "uwsgi";
|
||||
}
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("log pipe %d %d\n", uwsgi.shared->worker_log_pipe[0], uwsgi.shared->worker_log_pipe[1]);
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[1] != 1) {
|
||||
if (dup2(uwsgi.shared->worker_log_pipe[1], 1) < 0) {
|
||||
@@ -197,14 +209,16 @@ void log_syslog(char *syslog_opts) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("opening syslog\n");
|
||||
#endif
|
||||
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
openlog("uwsgi", 0, LOG_DAEMON );
|
||||
openlog(syslog_opts, 0, LOG_DAEMON );
|
||||
|
||||
|
||||
}
|
||||
@@ -254,7 +268,7 @@ void uwsgi_as_root() {
|
||||
#endif
|
||||
|
||||
if (!getuid()) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
if (!uwsgi.master_as_root && !uwsgi.uidname) {
|
||||
uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
|
||||
}
|
||||
|
||||
@@ -269,7 +283,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 +309,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,12 +352,23 @@ 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)) {
|
||||
uwsgi_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (uwsgi.uid) {
|
||||
if (!uwsgi.master_as_root) uwsgi_log("setuid() to %d\n", uwsgi.uid);
|
||||
@@ -376,13 +401,14 @@ 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);
|
||||
|
||||
|
||||
// get memory usage
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1)
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.reload_on_as || uwsgi.reload_on_rss)
|
||||
get_memusage();
|
||||
|
||||
|
||||
@@ -408,12 +434,22 @@ 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();
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_as && (int) (uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024) >= uwsgi.reload_on_as) {
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_rss && (int) (uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024) >= uwsgi.reload_on_rss) {
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -426,9 +462,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 +476,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 +599,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) {
|
||||
@@ -697,6 +734,13 @@ inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
}
|
||||
|
||||
inline int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
if (slen < dlen) return -1;
|
||||
|
||||
return memcmp(src, dst, dlen);
|
||||
}
|
||||
|
||||
inline int uwsgi_startswith(char *src, char *what, int wlen) {
|
||||
|
||||
int i;
|
||||
@@ -937,6 +981,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 +989,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 +1112,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);
|
||||
}
|
||||
}
|
||||
@@ -1263,6 +1317,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
|
||||
char *magic_buf;
|
||||
|
||||
// http url ?
|
||||
|
||||
if (!strncmp("http://", url, 7)) {
|
||||
domain = url+7;
|
||||
uri = strchr(domain, '/');
|
||||
@@ -1313,6 +1368,8 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
|
||||
|
||||
len = write(fd, "\r\n\r\n", 4);
|
||||
|
||||
int http_status_code_ptr = 0;
|
||||
|
||||
while( read(fd, &byte, 1) == 1) {
|
||||
if (byte == '\r' && body == 0) {
|
||||
body = 1;
|
||||
@@ -1337,6 +1394,18 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
|
||||
}
|
||||
else {
|
||||
body = 0;
|
||||
http_status_code_ptr++;
|
||||
if (http_status_code_ptr == 10) {
|
||||
if (byte != '2') {
|
||||
uwsgi_log("Not usable HTTP response: %cxx\n", byte);
|
||||
if (uwsgi.has_emperor) {
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,15 +1414,44 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
else if (!strncmp("emperor://", url, 10)) {
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
exit(1);
|
||||
}
|
||||
char *tmp_buffer[4096];
|
||||
ssize_t rlen = 1;
|
||||
*size = 0;
|
||||
while(rlen > 0) {
|
||||
rlen = read(uwsgi.emperor_fd_config, tmp_buffer, 4096);
|
||||
if (rlen > 0) {
|
||||
*size += rlen;
|
||||
buffer = realloc(buffer, *size);
|
||||
if (!buffer) {
|
||||
uwsgi_error("realloc()");
|
||||
exit(1);
|
||||
}
|
||||
memcpy(buffer+(*size-rlen), tmp_buffer, rlen);
|
||||
}
|
||||
}
|
||||
close(uwsgi.emperor_fd_config);
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
|
||||
if (add_zero) {
|
||||
*size = *size + 1;
|
||||
buffer = realloc(buffer, *size);
|
||||
buffer[*size-1] = 0;
|
||||
}
|
||||
}
|
||||
// fallback to file
|
||||
else {
|
||||
fd = open(url, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("open()");
|
||||
uwsgi_error_open(url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1441,6 +1539,7 @@ char *uwsgi_get_last_char(char *what, char c) {
|
||||
char *ptr = NULL;
|
||||
|
||||
if (!strncmp("http://", what, 7)) j = 7;
|
||||
if (!strncmp("emperor://", what, 10)) j = 10;
|
||||
|
||||
for(i=j;i<(int)strlen(what);i++) {
|
||||
if (what[i] == c) {
|
||||
@@ -1612,3 +1711,87 @@ char *uwsgi_get_exported_opt(char *key) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_get_optname_by_index(int index) {
|
||||
|
||||
struct option *aopt;
|
||||
struct option *lopt = uwsgi.long_options;
|
||||
|
||||
while ( (aopt = lopt) ) {
|
||||
if (!aopt->name) break;
|
||||
if (aopt->val == index) {
|
||||
return (char *) aopt->name;
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_list_has_num(char *list, int num) {
|
||||
|
||||
char *list2 = uwsgi_concat2(list, "");
|
||||
|
||||
char *p = strtok(list2, ",");
|
||||
while (p != NULL) {
|
||||
if (atoi(p) == num) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_list_has_str(char *list, char *str) {
|
||||
|
||||
char *list2 = uwsgi_concat2(list+1, "");
|
||||
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
if (!strcasecmp(p, str)) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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.2"
|
||||
|
||||
#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
|
||||
@@ -97,7 +99,11 @@
|
||||
#include <sys/utsname.h>
|
||||
|
||||
|
||||
#ifdef __linux
|
||||
#ifdef __linux__
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sys/mount.h>
|
||||
@@ -204,6 +210,24 @@ 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;
|
||||
};
|
||||
|
||||
struct uwsgi_static_map {
|
||||
|
||||
char *mountpoint;
|
||||
int mountpoint_len;
|
||||
|
||||
char *document_root;
|
||||
int document_root_len;
|
||||
|
||||
struct uwsgi_static_map *next;
|
||||
};
|
||||
|
||||
|
||||
union uwsgi_sockaddr {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
@@ -357,7 +381,21 @@ struct uwsgi_opt {
|
||||
#define LONG_ARGS_SUBSCRIBE_TO 17078
|
||||
#define LONG_ARGS_CLUSTER_NODES 17079
|
||||
#define LONG_ARGS_RELOAD_MERCY 17080
|
||||
|
||||
#define LONG_ARGS_ALLOWED_MODIFIERS 17081
|
||||
#define LONG_ARGS_LINUX_NS_NET 17082
|
||||
#define LONG_ARGS_CPU_AFFINITY 17083
|
||||
#define LONG_ARGS_CACHE_STORE 17084
|
||||
#define LONG_ARGS_CACHE_STORE_SYNC 17085
|
||||
#define LONG_ARGS_QUEUE_STORE 17086
|
||||
#define LONG_ARGS_QUEUE_STORE_SYNC 17087
|
||||
#define LONG_ARGS_PIDFILE2 17088
|
||||
#define LONG_ARGS_MAP_SOCKET 17089
|
||||
#define LONG_ARGS_SHARED_SOCKET 17090
|
||||
#define LONG_ARGS_STATIC_MAP 17091
|
||||
#define LONG_ARGS_FILE_SERVE_MODE 17092
|
||||
#define LONG_ARGS_RELOAD_ON_AS 17093
|
||||
#define LONG_ARGS_RELOAD_ON_RSS 17094
|
||||
#define LONG_ARGS_TOUCH_RELOAD 17095
|
||||
|
||||
|
||||
#define UWSGI_OK 0
|
||||
@@ -431,6 +469,7 @@ struct uwsgi_opt {
|
||||
|
||||
#define UWSGI_RELOAD_CODE 17
|
||||
#define UWSGI_END_CODE 30
|
||||
#define UWSGI_EXILE_CODE 26
|
||||
|
||||
#define MAX_VARS 64
|
||||
#define MAX_LOOPS 60
|
||||
@@ -456,6 +495,7 @@ struct uwsgi_server;
|
||||
struct uwsgi_plugin {
|
||||
|
||||
const char *name;
|
||||
const char *alias;
|
||||
uint8_t modifier1;
|
||||
void *data;
|
||||
int (*init) (void);
|
||||
@@ -485,6 +525,10 @@ struct uwsgi_plugin {
|
||||
|
||||
uint16_t (*rpc)(void *, uint8_t, char **, char *);
|
||||
|
||||
void (*jail) (int (*)(void *), char**);
|
||||
|
||||
struct uwsgi_help_item *help;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -521,6 +565,9 @@ struct uwsgi_app {
|
||||
int requests;
|
||||
char *chdir;
|
||||
|
||||
char *touch_reload;
|
||||
time_t touch_reload_mtime;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -554,6 +601,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;
|
||||
@@ -616,6 +670,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;
|
||||
@@ -633,14 +696,14 @@ struct wsgi_request {
|
||||
|
||||
int async_id;
|
||||
int async_status;
|
||||
int async_waiting_fd;
|
||||
int async_waiting_fd_type;
|
||||
int async_waiting_fd_monitored;
|
||||
|
||||
int switches;
|
||||
|
||||
time_t async_timeout;
|
||||
int async_timeout_expired;
|
||||
int async_timed_out;
|
||||
int async_ready_fd;
|
||||
int async_last_ready_fd;
|
||||
struct uwsgi_rb_timer *async_timeout;
|
||||
struct uwsgi_async_fd *waiting_fds;
|
||||
|
||||
void *async_app;
|
||||
void *async_result;
|
||||
@@ -652,6 +715,8 @@ struct wsgi_request {
|
||||
|
||||
int async_plagued;
|
||||
|
||||
int suspended;
|
||||
|
||||
int *ovector;
|
||||
size_t post_cl;
|
||||
char *post_buffering_buf;
|
||||
@@ -712,12 +777,16 @@ struct uwsgi_server {
|
||||
|
||||
int has_emperor;
|
||||
int emperor_fd;
|
||||
int emperor_fd_config;
|
||||
char *emperor_dir;
|
||||
pid_t emperor_pid;
|
||||
|
||||
time_t master_mercy;
|
||||
|
||||
int cpu_affinity;
|
||||
|
||||
int reload_mercy;
|
||||
int exit_on_reload;
|
||||
int option_index;
|
||||
struct option *long_options;
|
||||
struct uwsgi_opt **exported_opts;
|
||||
@@ -754,8 +823,12 @@ struct uwsgi_server {
|
||||
int log_syslog;
|
||||
char *check_static;
|
||||
size_t check_static_len;
|
||||
int file_serve_mode;
|
||||
|
||||
struct uwsgi_static_map *static_maps;
|
||||
|
||||
char *logfile;
|
||||
int logfile_chown;
|
||||
|
||||
int vhost;
|
||||
int vhost_host;
|
||||
@@ -764,8 +837,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;
|
||||
@@ -775,6 +856,11 @@ struct uwsgi_server {
|
||||
size_t limit_post;
|
||||
int prio;
|
||||
|
||||
int reload_on_as;
|
||||
int reload_on_rss;
|
||||
char *touch_reload;
|
||||
time_t last_touch_reload_mtime;
|
||||
|
||||
int grunt;
|
||||
|
||||
char *binary_path;
|
||||
@@ -794,13 +880,10 @@ struct uwsgi_server {
|
||||
char *spool_dir;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_NAGIOS
|
||||
int nagios;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
int snmp;
|
||||
char *snmp_community;
|
||||
char *snmp_addr;
|
||||
char *snmp_community;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -821,6 +904,7 @@ struct uwsgi_server {
|
||||
int page_size;
|
||||
|
||||
char *pidfile;
|
||||
char *pidfile2;
|
||||
|
||||
int harakiri_verbose;
|
||||
|
||||
@@ -830,14 +914,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;
|
||||
|
||||
@@ -917,13 +993,19 @@ 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];
|
||||
|
||||
int shared_sockets_cnt;
|
||||
struct uwsgi_socket shared_sockets[MAX_SOCKETS];
|
||||
|
||||
char *map_socket[MAX_SOCKETS];
|
||||
|
||||
time_t respawn_delta;
|
||||
|
||||
char *mounts[MAX_APPS];
|
||||
@@ -943,6 +1025,7 @@ struct uwsgi_server {
|
||||
|
||||
// usedby suspend/resume loops
|
||||
void (*schedule_to_main) (struct wsgi_request *);
|
||||
void (*schedule_to_req) (void);
|
||||
|
||||
int close_on_exec;
|
||||
|
||||
@@ -953,6 +1036,8 @@ struct uwsgi_server {
|
||||
struct uwsgi_plugin *p[0xFF];
|
||||
struct uwsgi_plugin *gp[MAX_GENERIC_PLUGINS];
|
||||
int gp_cnt;
|
||||
|
||||
char *allowed_modifiers;
|
||||
|
||||
char *upload_progress;
|
||||
|
||||
@@ -960,6 +1045,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;
|
||||
@@ -967,10 +1054,16 @@ struct uwsgi_server {
|
||||
uint64_t cache_blocksize;
|
||||
struct uwsgi_cache_item *cache_items;
|
||||
void *cache;
|
||||
char *cache_store;
|
||||
size_t cache_filesize;
|
||||
int cache_store_sync;
|
||||
|
||||
uint64_t queue_size;
|
||||
uint64_t queue_blocksize;
|
||||
void *queue;
|
||||
char *queue_store;
|
||||
size_t queue_filesize;
|
||||
int queue_store_sync;
|
||||
|
||||
void *cache_lock;
|
||||
void *queue_lock;
|
||||
@@ -981,7 +1074,9 @@ struct uwsgi_server {
|
||||
void *rb_timer_table_lock;
|
||||
void *cron_table_lock;
|
||||
void *rpc_table_lock;
|
||||
#ifdef UWSGI_SPOOLER
|
||||
void *spooler_lock;
|
||||
#endif
|
||||
|
||||
void *daemon_table_lock;
|
||||
|
||||
@@ -1175,6 +1270,8 @@ struct uwsgi_worker {
|
||||
|
||||
uint64_t exceptions;
|
||||
|
||||
char sockets_mask[MAX_SOCKETS];
|
||||
|
||||
};
|
||||
|
||||
char *uwsgi_get_cwd(void);
|
||||
@@ -1258,14 +1355,15 @@ struct http_status_codes {
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
|
||||
#define ASYNC_IN 1
|
||||
#define ASYNC_OUT 2
|
||||
struct wsgi_request *async_loop(void);
|
||||
void *async_loop(void *);
|
||||
struct wsgi_request *find_first_available_wsgi_req(void);
|
||||
struct wsgi_request *find_first_accepting_wsgi_req(void);
|
||||
struct wsgi_request *find_wsgi_req_by_fd(int);
|
||||
struct wsgi_request *find_wsgi_req_by_id(int);
|
||||
|
||||
void async_add_fd_write(struct wsgi_request *, int, int);
|
||||
void async_add_fd_read(struct wsgi_request *, int, int);
|
||||
|
||||
#ifdef __clang__
|
||||
struct wsgi_request *next_wsgi_req(struct wsgi_request *);
|
||||
#else
|
||||
@@ -1273,11 +1371,8 @@ inline struct wsgi_request *next_wsgi_req(struct wsgi_request *);
|
||||
#endif
|
||||
|
||||
|
||||
int async_get_timeout(void);
|
||||
void async_set_timeout(struct wsgi_request*, time_t);
|
||||
void async_add_timeout(struct wsgi_request*, int);
|
||||
void async_expire_timeouts(void);
|
||||
void async_write_all(char *, size_t);
|
||||
void async_unpause_all(void);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1292,18 +1387,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);
|
||||
|
||||
@@ -1315,8 +1403,6 @@ void uwsgi_log_verbose(const char *,...);
|
||||
|
||||
|
||||
int uwsgi_load_plugin(int, char *, char *, int);
|
||||
void embed_plugins(void);
|
||||
|
||||
|
||||
int unconfigured_hook(struct wsgi_request *);
|
||||
|
||||
@@ -1365,7 +1451,6 @@ int find_worker_id(pid_t);
|
||||
|
||||
|
||||
void *simple_loop(void *);
|
||||
void complex_loop(void);
|
||||
|
||||
int count_options(struct option *);
|
||||
|
||||
@@ -1435,7 +1520,7 @@ int event_queue_init(void);
|
||||
void *event_queue_alloc(int);
|
||||
int event_queue_add_fd_read(int, int);
|
||||
int event_queue_add_fd_write(int, int);
|
||||
int event_queue_del_fd(int, int);
|
||||
int event_queue_del_fd(int, int, int);
|
||||
int event_queue_wait(int, int, int *);
|
||||
int event_queue_wait_multi(int, int, void *, int);
|
||||
int event_queue_interesting_fd(void *, int);
|
||||
@@ -1609,3 +1694,50 @@ void uwsgi_unix_signal(int, void (*)(int));
|
||||
char *uwsgi_get_exported_opt(char *);
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
|
||||
|
||||
char *uwsgi_get_optname_by_index(int);
|
||||
|
||||
int uwsgi_list_has_num(char *, int);
|
||||
|
||||
int uwsgi_list_has_str(char *, char *);
|
||||
|
||||
void uwsgi_cache_fix(void);
|
||||
|
||||
struct uwsgi_async_request {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
struct uwsgi_async_request *prev;
|
||||
struct uwsgi_async_request *next;
|
||||
};
|
||||
|
||||
inline int event_queue_read(void);
|
||||
inline int event_queue_write(void);
|
||||
|
||||
void uwsgi_help(void);
|
||||
|
||||
void uwsgi_queue_fix(void);
|
||||
|
||||
int uwsgi_str2_num(char *);
|
||||
int uwsgi_str3_num(char *);
|
||||
int uwsgi_str4_num(char *);
|
||||
|
||||
#ifdef __linux__
|
||||
int uwsgi_netlink_veth(char *, char *);
|
||||
int uwsgi_netlink_veth_attach(char *, pid_t);
|
||||
int uwsgi_netlink_ifup(char *);
|
||||
int uwsgi_netlink_ip(char *, char *, int);
|
||||
int uwsgi_netlink_gw(char *, char *);
|
||||
int uwsgi_netlink_rt(char *, char *, int, char *);
|
||||
int uwsgi_netlink_del(char *);
|
||||
#endif
|
||||
|
||||
|
||||
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *);
|
||||
char *uwsgi_amqp_consume(int, uint64_t *, char **);
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
inline int uwsgi_starts_with(char *, int, char *, int);
|
||||
|
||||
#ifdef __sun__
|
||||
time_t timegm(struct tm *);
|
||||
#endif
|
||||
|
||||
+27
-5
@@ -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('/')
|
||||
|
||||
@@ -150,7 +157,9 @@ class uConf(object):
|
||||
print("using profile: %s" % filename)
|
||||
self.config.read(filename)
|
||||
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'emperor',
|
||||
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'rb_timers', 'uwsgi']
|
||||
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
|
||||
#if uwsgi_os == 'Linux':
|
||||
# self.gcc_list.append('lib/netlink')
|
||||
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
|
||||
try:
|
||||
gcc_version = str(spcall("%s -dumpversion" % GCC))
|
||||
@@ -167,6 +176,8 @@ class uConf(object):
|
||||
|
||||
self.ldflags = os.environ.get("LDFLAGS", "").split()
|
||||
self.libs = ['-lpthread', '-rdynamic']
|
||||
if uwsgi_os == 'Linux':
|
||||
self.libs.append('-ldl')
|
||||
|
||||
# check for inherit option
|
||||
inherit = self.get('inherit')
|
||||
@@ -215,6 +226,7 @@ class uConf(object):
|
||||
|
||||
if uwsgi_os == 'SunOS':
|
||||
self.libs.append('-lsendfile')
|
||||
self.gcc_list.append('lib/sun_fixes')
|
||||
if not uwsgi_os_v.startswith('Nexenta'):
|
||||
self.libs.remove('-rdynamic')
|
||||
|
||||
@@ -227,6 +239,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 +350,8 @@ class uConf(object):
|
||||
if self.get('udp'):
|
||||
self.cflags.append("-DUWSGI_UDP")
|
||||
|
||||
if self.get('pcre'):
|
||||
# re-enable after pcre fix
|
||||
if self.get('pcreOFF'):
|
||||
if self.get('pcre') == 'auto':
|
||||
pcreconf = spcall('pcre-config --libs')
|
||||
if pcreconf:
|
||||
@@ -377,9 +393,15 @@ class uConf(object):
|
||||
self.gcc_list.append('yaml')
|
||||
|
||||
if self.get('ldap'):
|
||||
self.cflags.append("-DUWSGI_LDAP")
|
||||
self.gcc_list.append('ldap')
|
||||
self.libs.append('-lldap')
|
||||
if self.get('ldap') == 'auto':
|
||||
if os.path.exists('/usr/include/ldap.h'):
|
||||
self.cflags.append("-DUWSGI_LDAP")
|
||||
self.gcc_list.append('ldap')
|
||||
self.libs.append('-lldap')
|
||||
else:
|
||||
self.cflags.append("-DUWSGI_LDAP")
|
||||
self.gcc_list.append('ldap')
|
||||
self.libs.append('-lldap')
|
||||
|
||||
if self.get('evdis'):
|
||||
self.cflags.append("-DUWSGI_EVDIS")
|
||||
|
||||
Reference in New Issue
Block a user