Compare commits

..
87 Commits
Author SHA1 Message Date
roberto@natty32 6eed48b28d updated Changelog and copyright year 2011-04-06 09:29:46 +02:00
roberto@netbsd64 9c5d289098 better locking for NetBSD and OpenBSD 2011-04-06 08:16:03 +02:00
roberto@solarisexpress 42ab7f23d8 added timegm to solaris 2011-04-06 06:03:17 +00:00
roberto@natty32 c9c2f4232e preparing for 0.9.7.2 release 2011-04-06 05:06:38 +02:00
roberto@longshot d4f23cc6bd use realpath() for document_root 2011-04-05 20:55:48 +02:00
roberto@natty32 b0db67d4d4 refactored post limit management 2011-04-05 16:51:40 +02:00
roberto@natty32 703cad6715 disallow empty socket names 2011-04-05 11:32:15 +02:00
roberto@natty32 667d67460f do not build netlink support (still useless for non-third-party plugins) 2011-04-05 09:00:58 +02:00
roberto@natty32 35cf9ae328 implemented exc_info in WSGI start_response and added --reload-on-as and --reload-on-rss 2011-04-05 08:58:22 +02:00
roberto@natty32 c04131af4b fixed syslog support 2011-04-04 17:17:47 +02:00
roberto@natty32 9cc4db1a12 various fixes 2011-04-04 09:46:17 +02:00
roberto@natty32 b326500913 --static-map mountpoint=documentroot option 2011-04-04 08:31:17 +02:00
roberto@natty32 a26579fcf5 better plugin loading 2011-04-03 08:18:51 +02:00
roberto@natty32 a2b9c44433 -ldl should be used only for Linux 2011-04-02 15:57:57 +02:00
roberto@natty32 c3b97da1d4 various Riccardo Magliocchetti build fixes 2011-04-02 15:26:00 +02:00
roberto@natty32 048cf0232a nailed connection between emperor and rabbitmq 2011-04-01 16:11:18 +02:00
roberto@natty32 89c113bee6 added EXILE mode for vassals 2011-04-01 08:35:20 +02:00
roberto@natty32 6b9969a302 allow emperor config files to be taken via http 2011-04-01 08:09:34 +02:00
roberto@natty32 a6e7513d2a declare exchange automatically 2011-04-01 07:13:09 +02:00
roberto@natty32 8a04f4810f allow vassals configuration to be stored on amqp/rabbitmq servers 2011-04-01 06:31:54 +02:00
roberto@natty32 1d9d443de0 amqp/rabbitmq emperor fixes 2011-04-01 05:17:50 +02:00
roberto@natty32 00e5809a71 preliminary amqp/rabbitmq support for emperor 2011-04-01 03:14:51 +02:00
roberto@freebsd64 07ba4a040b fixed freebsd kvm_open 2011-03-30 20:48:01 +02:00
roberto@mrspurr 7b319d230a allow building of psgi plugin without ithreads 2011-03-30 08:03:48 +02:00
roberto@natty32 641bc2daec fixed unbitstaff build profile 2011-03-29 12:06:13 +02:00
roberto@dj2 fbaa30cc08 various fixes 2011-03-28 11:31:40 -05:00
roberto@dj2 a0c2c9056b fixed a couple fo emperor race conditions 2011-03-28 09:37:17 -05:00
roberto@dj2 30ab5fd76b added --exit-on-reload 2011-03-28 07:31:51 -05:00
roberto@dj2 30beab4017 fixed a regression in setgroups() 2011-03-28 05:38:29 -05:00
roberto@dj2 4ec1493b09 fixed subscription system 2011-03-28 04:29:04 -05:00
roberto@dj2 e7cbe9709e build netlink support in Linux 2011-03-28 04:17:07 -05:00
roberto@dj2 aacaeba525 shared sockets support 2011-03-28 04:15:31 -05:00
roberto@dj2 6e4da5efb7 add netlink library 2011-03-28 04:11:31 -05:00
roberto@natty32 87443a4ff2 Added tag 0.9.7.1 for changeset 486e7760bcbc 2011-03-26 09:39:57 +01:00
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
roberto@natty32 f74e61b126 fixed psgi compilation 2011-03-16 21:29:52 +01:00
roberto@natty32 c8b4ba2b5b updated iobound_async example and improved pep3333-input 2011-03-16 20:54:54 +01:00
roberto@natty32 0a15ba1c5b remove stackless support, move it to async plugin 2011-03-16 13:12:50 +01:00
roberto@natty32 7ee5948233 better error reporting on failed open/fopen 2011-03-16 12:14:41 +01:00
roberto@natty32 85c8bcf9d2 removed memory leak in greenlet plugin 2011-03-16 11:12:55 +01:00
roberto@natty32 67394c6664 added greenlet plugin 2011-03-16 11:02:05 +01:00
roberto@silente 66ef7d8229 remove uGreen compilation on unsupported platforms 2010-12-29 23:06:47 +01:00
roberto@solarisexpress 3773bc69f2 fixed ldap solaris support 2011-03-16 09:48:52 +00:00
roberto@natty32 912416b119 fixed openldap support 2011-03-16 09:45:15 +01:00
roberto@solarisexpress 7dfe125013 solaris fixes 2011-03-16 09:39:02 +00:00
roberto@mrspurr 87db34ef0b removed setjmp code 2011-03-16 07:46:11 +01:00
roberto@natty32 d4f75ab53c re-added ugreen support (better and faster) 2011-03-16 07:28:23 +01:00
roberto@natty32 dc97e8fce5 new help system 2011-03-15 12:14:22 +01:00
roberto@natty32 b3965d9d67 updated async support 2011-03-15 10:45:23 +01:00
roberto@natty32 7ee90d1e12 fixed python uwsgi.cache_get 2011-03-12 14:52:11 +01:00
roberto@sirius 9d8b373e4f uWSGI 0.9.7-rc3 2011-03-12 14:21:16 +01:00
roberto@natty32 a068a7eb5b added support for cache backing store 2011-03-12 14:14:43 +01:00
roberto@natty32 aa004c1893 less verbose file monitoring 2011-03-12 09:31:14 +01:00
roberto@natty32 9a9c149370 fixed emperor waitpid and erlang list encoding 2011-03-12 07:35:41 +01:00
roberto@natty32 9e6e226e4b improved snmp agent and fixed cache modifier 4 2011-03-11 11:55:44 +01:00
roberto@mrspurr 06c2aed0e0 add modifier 3 in cache plugin 2011-03-11 10:57:39 +01:00
roberto@natty32 df4f610cfc preliminary cpu-affinity support 2011-03-11 07:37:43 +01:00
roberto@natty32 64249abae1 improved ldap support 2011-03-10 19:14:13 +01:00
roberto@sirius 94f4be58bd auto configure ldap support 2011-03-10 10:40:56 +01:00
roberto@sirius 35987d3741 added --allowed-modifiers 2011-03-10 10:21:08 +01:00
roberto@natty32 be73e00dde merge 2011-03-10 09:56:33 +01:00
roberto@natty32 a5f272f337 fixed a bug in getopt_long 2011-03-10 09:56:04 +01:00
roberto@sirius 406691aa69 uWSGI 0.9.7-rc2 2011-03-09 11:26:27 +01:00
54 changed files with 4576 additions and 1519 deletions
+8
View File
@@ -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
+72
View File
@@ -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
+325 -157
View File
@@ -2,198 +2,366 @@
extern struct uwsgi_server uwsgi;
int async_get_timeout() {
struct wsgi_request* wsgi_req ;
int i ;
time_t curtime, tdelta = 0 ;
int ret = 0 ;
// do not wait if there are cores running
if (!uwsgi.async_running) return 0;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_timeout_expired) {
// do not wait if there are timeout expired
return 0;
}
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout ;
}
}
}
}
curtime = time(NULL);
ret = tdelta - curtime ;
if (ret > 0) {
return ret;
}
return -1;
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
void async_expire_timeouts() {
void runqueue_remove(struct uwsgi_async_request *u_request) {
struct wsgi_request* wsgi_req ;
int i ;
time_t deadline = time(NULL);
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i] ;
if (wsgi_req->async_status == UWSGI_AGAIN && wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_timeout = 0 ;
wsgi_req->async_timeout_expired = 1 ;
if (wsgi_req->async_waiting_fd != -1) {
event_queue_del_fd(uwsgi.async_queue, wsgi_req->async_waiting_fd);
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = -1;
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_waiting_fd_monitored = 0;
}
}
}
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
struct wsgi_request* wsgi_req;
int i ;
struct wsgi_request *wsgi_req;
// optimization
if (uwsgi.async_current_max > 1) {
if (uwsgi.wsgi_requests[uwsgi.async_current_max-1]->async_status == UWSGI_OK) {
//uwsgi_log("decreasing current max cores\n");
uwsgi.async_current_max--;
}
if (uwsgi.async_queue_unused_ptr < 0) {
return NULL;
}
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i] ;
if (wsgi_req->async_status == UWSGI_OK) {
// optimization
if (i > uwsgi.async_current_max-1) uwsgi.async_current_max = i+1;
wsgi_req->async_id = i;
return wsgi_req ;
wsgi_req = uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr];
uwsgi.async_queue_unused_ptr--;
return wsgi_req;
}
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = time(NULL);
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (urbt == NULL) return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
break;
}
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct wsgi_request* wsgi_req = NULL ;
int core_id = uwsgi.async_waiting_fd_table[fd];
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (core_id == -1) return NULL;
if (fd < 0) return ;
wsgi_req = uwsgi.wsgi_requests[core_id];
//if (wsgi_req->async_waiting_fd_type == etype) return wsgi_req ;
return wsgi_req;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
return NULL ;
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_read();
uad->prev = last_uad;
uad->next = NULL;
}
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
void async_set_timeout(struct wsgi_request *wsgi_req, time_t timeout) {
wsgi_req->async_timeout = time(NULL);
wsgi_req->async_timeout += timeout;
wsgi_req->async_timeout_expired = 0 ;
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
}
void async_write_all(char *data, size_t len) {
struct wsgi_request *wsgi_req;
int i;
ssize_t rlen ;
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, time(NULL)+timeout, wsgi_req);
}
}
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
}
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
uwsgi.async_runqueue = NULL;
uwsgi.async_runqueue_cnt = 0;
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - time(NULL);
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
}
else {
wsgi_req->response_size += rlen ;
timeout = -1;
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
}
for(i=0;i<uwsgi.async_nevents;i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// new request coming in
if (interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_log("async queue is full !!!\n");
continue;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
continue;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_simple_recv(uwsgi.wsgi_req)) {
continue;
}
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
}
else {
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
close(interesting_fd);
continue;
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
}
}
}
}
void async_unpause_all() {
struct wsgi_request *wsgi_req ;
int i;
// event queue managed, give cpu to runqueue
if (!current_request)
current_request = uwsgi.async_runqueue;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_async_request;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
}
}
}
struct wsgi_request * async_loop() {
struct wsgi_request *wsgi_req ;
int i ;
int ret;
uwsgi.async_running = -1 ;
for(i=0;i<uwsgi.async_current_max;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->sigwait) {
uwsgi_log("waiting for signal\n");
continue;
}
else if (wsgi_req->async_waiting_fd != -1 && !wsgi_req->async_waiting_fd_monitored) {
// add fd to monitoring
ret = -1;
if (wsgi_req->async_waiting_fd_type == ASYNC_IN) {
ret = event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
else if (wsgi_req->async_waiting_fd_type == ASYNC_OUT) {
ret = event_queue_add_fd_write(uwsgi.async_queue, wsgi_req->async_waiting_fd);
}
if (ret < 0) {
// error adding fd to the async queue, better to close it...
close(wsgi_req->async_waiting_fd);
wsgi_req->async_status = UWSGI_OK ;
return wsgi_req;
}
uwsgi.async_waiting_fd_table[wsgi_req->async_waiting_fd] = wsgi_req->async_id;
wsgi_req->async_waiting_fd_monitored = 1;
wsgi_req->async_status = UWSGI_AGAIN;
}
else if (wsgi_req->async_waiting_fd == -1 && wsgi_req->async_timeout <= 0) {
uwsgi.async_running = 0 ;
// st global wsgi_req
uwsgi.wsgi_req = wsgi_req ;
uwsgi_log("!!! getting new part\n");
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);;
wsgi_req->switches++;
if (wsgi_req->async_status < UWSGI_AGAIN) {
return wsgi_req;
}
}
}
}
return NULL;
+2 -2
View File
@@ -13,7 +13,7 @@ sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
ldap = auto
pcre = auto
debug = false
unbit = false
@@ -21,7 +21,7 @@ xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
locking = auto
event = auto
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+1
View File
@@ -1,4 +1,5 @@
[uwsgi]
inherit = unbit
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+23 -1
View File
@@ -330,6 +330,27 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
return ret;
}
void uwsgi_cache_fix() {
uint64_t i;
for(i=0;i< uwsgi.cache_max_items;i++) {
// valid record ?
if (uwsgi.cache_items[i].keysize) {
if (!uwsgi.cache_items[i].prev) {
// put value in hash_table
uwsgi.cache_hashtable[ uwsgi.cache_items[i].djbhash % 0xffff] = i;
}
}
else {
// put this record in unused stack
uwsgi.shared->cache_first_available_item = i;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = i;
}
}
}
int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint16_t flags) {
uint64_t index = 0, last_index = 0 ;
@@ -476,7 +497,7 @@ void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, val, vallen);
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
}
}
@@ -528,6 +549,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh.pktsize > 0) {
+66
View File
@@ -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)
"""
+251 -90
View File
@@ -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);
}
}
+37 -16
View File
@@ -6,6 +6,9 @@ extern struct uwsgi_server uwsgi;
#include <port.h>
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int event_queue_init() {
int port = port_create();
@@ -18,7 +21,7 @@ int event_queue_init() {
return port;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
if (port_dissociate(eq, PORT_SOURCE_FD, fd)) {
uwsgi_error("port_disassociate");
@@ -28,6 +31,17 @@ int event_queue_del_fd(int eq, int fd) {
return fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
return fd;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
@@ -76,12 +90,11 @@ int event_queue_interesting_fd(void *events, int id) {
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget;
int i;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout > 0) {
if (timeout >= 0) {
ts.tv_sec = timeout;
ts.tv_nsec = 0;
ret = port_getn(eq, events, nevents, &nget, &ts);
@@ -99,13 +112,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
pe = (port_event_t *) events;
for(i=0;i<nget;i++) {
if (pe[i].portev_source == PORT_SOURCE_FD) {
if (port_associate(eq, pe[i].portev_source, pe[i].portev_object, pe[i].portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
}
return nget;
}
@@ -144,7 +150,6 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
*interesting_fd = (int) pe.portev_user;
uwsgi_log("port event interesting_fd: %d\n", *interesting_fd);
}
else {
*interesting_fd = (int) pe.portev_object;
@@ -160,6 +165,9 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#include <sys/epoll.h>
#define UWSGI_EVENT_IN EPOLLIN
#define UWSGI_EVENT_OUT EPOLLOUT
int event_queue_init() {
int epfd;
@@ -207,12 +215,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct epoll_event ee;
memset(&ee, 0, sizeof(struct epoll_event));
ee.data.fd = fd;
ee.events = event;
if (epoll_ctl(eq, EPOLL_CTL_DEL, fd, &ee)) {
uwsgi_error("epoll_ctl()");
@@ -298,6 +307,10 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
#endif
#ifdef UWSGI_EVENT_USE_KQUEUE
#define UWSGI_EVENT_IN EVFILT_READ
#define UWSGI_EVENT_OUT EVFILT_WRITE
int event_queue_init() {
int kfd = kqueue();
@@ -329,11 +342,11 @@ int event_queue_fd_write_to_read(int eq, int fd) {
return fd;
}
int event_queue_del_fd(int eq, int fd) {
int event_queue_del_fd(int eq, int fd, int event) {
struct kevent kev;
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
EV_SET(&kev, fd, event, EV_DELETE, 0, 0, 0);
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("kevent()");
return -1;
@@ -516,7 +529,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
return -1;
}
@@ -831,3 +844,11 @@ struct uwsgi_timer *event_queue_ack_timer(int id) {
}
#endif
inline int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+193 -113
View File
@@ -6,6 +6,14 @@ extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
@@ -37,71 +45,162 @@ int calc_ldap_name(char *name) {
return strlen(name) + counter;
}
void uwsgi_ldap_schema_dump_ldif() {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
lopt = uwsgi.long_options;
int i;
int counter = 30000;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr+= 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry->has_arg = aopt->has_arg;
next:
lopt++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
if (aopt->flag) {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
for(i=0;i<items;i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
uwsgi_log("uWSGI");
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
@@ -112,67 +211,47 @@ void uwsgi_ldap_schema_dump_ldif() {
}
void uwsgi_ldap_schema_dump() {
struct option *aopt, *lopt;
lopt = uwsgi.long_options;
int i;
int counter = 30000;
int items;
while( (aopt = lopt) ) {
if (!aopt->name)
break;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
if (aopt->flag) {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter);
counter++;
}
else {
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val);
}
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (aopt->has_arg) {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
lopt++;
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
lopt = uwsgi.long_options;
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
while( (aopt = lopt) ) {
if (!aopt->name)
break;
for(i=0;i<items;i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGI");
for(i=0;i< (int)strlen(aopt->name);i++) {
if (aopt->name[i] == '-') {
i++;
uwsgi_log("%c", toupper( (int) aopt->name[i]));
}
else {
uwsgi_log("%c", aopt->name[i]);
}
}
uwsgi_log(" $ ");
lopt++;
}
uwsgi_log("uWSGInull ))\n");
@@ -194,8 +273,6 @@ void uwsgi_ldap_config() {
int desired_version = LDAP_VERSION3;
int ret;
struct option *aopt, *lopt;
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
@@ -211,6 +288,8 @@ void uwsgi_ldap_config() {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
@@ -225,10 +304,17 @@ void uwsgi_ldap_config() {
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
@@ -255,9 +341,11 @@ void uwsgi_ldap_config() {
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
if (!uwsgi_attr) {
uwsgi_error("malloc()");
@@ -271,7 +359,7 @@ void uwsgi_ldap_config() {
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_val;
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
if (!uwsgi_val) {
uwsgi_error("malloc()");
@@ -281,29 +369,21 @@ void uwsgi_ldap_config() {
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
lopt = uwsgi.long_options;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(uwsgi_attr, aopt->name)) {
if (aopt->flag) {
*aopt->flag = aopt->val;
add_exported_option(0, (char*) uwsgi_attr);
}
else {
manage_opt(aopt->val, uwsgi_val);
}
}
lopt++;
}
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
free(bervalues);
free(uwsgi_attr);
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
+799
View File
@@ -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
View File
@@ -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;
}
+29
View File
@@ -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));
}
+6 -10
View File
@@ -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));
}
+4
View File
@@ -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__)
-103
View File
@@ -87,106 +87,3 @@ void *simple_loop(void *arg1) {
//never here
return NULL;
}
#ifdef UWSGI_ASYNC
void complex_loop() {
int current_async_timeout = 0;
int i, j;
int interesting_fd;
struct wsgi_request *wsgi_req;
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
current_async_timeout = async_get_timeout();
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, current_async_timeout, uwsgi.async_events, 64);
async_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
interesting_fd = event_queue_interesting_fd(uwsgi.async_events, i);
if ( interesting_fd == uwsgi.sockets[0].fd) {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
// async system is full !!!
goto cycle;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
continue;
}
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
if (uwsgi.numproc > 1) {
/* re-set blocking socket */
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
uwsgi_error("fcntl()");
continue;
}
}
#endif
if (wsgi_req_recv(uwsgi.wsgi_req)) {
continue;
}
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
goto reqclear;
}
}
else if ( interesting_fd == uwsgi.sockets_poll[uwsgi.sockets_cnt].fd) {
// wake up cores waiting for signal
char byte;
if (read(uwsgi.sockets_poll[uwsgi.sockets_cnt].fd, &byte, 1) == 1) {
}
else {
uwsgi_error("read()");
}
for(j=0;j<uwsgi.async_current_max;j++) {
wsgi_req = uwsgi.wsgi_requests[j] ;
if (wsgi_req->sigwait) {
wsgi_req->signal_received = byte;
wsgi_req->sigwait = 0;
}
}
}
else {
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
if (uwsgi.wsgi_req) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
uwsgi.wsgi_req->async_waiting_fd = -1;
uwsgi.wsgi_req->async_waiting_fd_monitored = 0;
uwsgi.wsgi_req->async_timeout = 0;
}
event_queue_del_fd(uwsgi.async_queue, interesting_fd);
}
}
cycle:
uwsgi.wsgi_req = async_loop();
if (uwsgi.wsgi_req == NULL)
continue;
uwsgi.wsgi_req->async_status = UWSGI_OK;
reqclear:
uwsgi_close_request(uwsgi.wsgi_req);
}
}
#endif
+111 -42
View File
@@ -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);
}
}
}
}
+18 -4
View File
@@ -1,13 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
vacuum = true
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
mount = /app1=werkzeug.testapp:test_app
mount = /app2=config:/Users/roberta/uwsgi/my.ini
mount = /app3=pinaxsite/deploy/pinax.wsgi
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+53 -22
View File
@@ -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;
}
+1
View File
@@ -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
View File
@@ -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,
+86
View File
@@ -0,0 +1,86 @@
#include "../python/uwsgi_python.h"
#include <greenlet/greenlet.h>
extern struct uwsgi_server uwsgi;
struct ugreenlet {
int enabled;
PyObject *callable;
PyGreenlet *main;
PyGreenlet **gl;
} ugl;
struct option greenlet_options[] = {
{"greenlet", no_argument, &ugl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
inline static void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
uwsgi.wsgi_req->suspended = 1;
}
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
PyGreenlet_Switch(ugl.main, NULL, NULL);
uwsgi.wsgi_req = wsgi_req;
}
int greenlet_init() {
return 0;
}
void greenlet_init_apps(void) {
if (!ugl.enabled) {
return;
}
PyGreenlet_Import();
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
ugl.main = PyGreenlet_GetCurrent();
ugl.callable = PyCFunction_New(uwsgi_greenlet_request_method, NULL);
uwsgi_log("enabled greenlet engine\n");
uwsgi.schedule_to_main = greenlet_schedule_to_main;
uwsgi.schedule_to_req = greenlet_schedule_to_req;
return;
}
struct uwsgi_plugin greenlet_plugin = {
.name = "greenlet",
.init = greenlet_init,
.init_apps = greenlet_init_apps,
.options = greenlet_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='greenlet'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['greenlet']
+54 -3
View File
@@ -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,
};
+2
View File
@@ -1,5 +1,7 @@
#undef __USE_GNU
#include "../../uwsgi.h"
#define HAS_BOOL 1
#include <EXTERN.h>
#include <perl.h>
#include "XSUB.h"
+9 -2
View File
@@ -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,
+7 -5
View File
@@ -478,11 +478,13 @@ int py_to_erl(PyObject *pobj, ei_x_buff *x) {
ei_x_encode_long(x, PyInt_AsLong(pobj));
}
else if (PyList_Check(pobj)) {
ei_x_encode_list_header(x, PyList_Size(pobj));
for (i = 0; i < PyList_Size(pobj); i++) {
pobj2 = PyList_GetItem(pobj, i);
if (py_to_erl(pobj2, x) < 0) return -1;
}
if (PyList_Size(pobj) > 0) {
ei_x_encode_list_header(x, PyList_Size(pobj));
for (i = 0; i < PyList_Size(pobj); i++) {
pobj2 = PyList_GetItem(pobj, i);
if (py_to_erl(pobj2, x) < 0) return -1;
}
}
ei_x_encode_empty_list(x);
}
else if (PyTuple_Check(pobj)) {
+9
View File
@@ -149,6 +149,14 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->interpreter = up.main_thread;
}
if (wsgi_req->touch_reload_len) {
struct stat trst;
char *touch_reload = uwsgi_strncopy(wsgi_req->touch_reload, wsgi_req->touch_reload_len);
if (!stat(touch_reload, &trst)) {
wi->touch_reload = touch_reload;
wi->touch_reload_mtime = trst.st_mtime;
}
}
wi->callable = up.loaders[loader](arg1);
@@ -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);
}
+91 -34
View File
@@ -35,6 +35,29 @@ struct option uwsgi_python_options[] = {
{0, 0, 0, 0},
};
struct uwsgi_help_item uwsgi_python_help[] = {
{"module <module>" ,"name of python config module"},
{"optimize <n>", "set python optimization level to <n>"},
{"home <path>", "set python home/virtualenv"},
{"pyhome <path>", "set python home/virtualenv"},
{"virtualenv <path>", "set python home/virtualenv"},
{"venv <path>", "set python home/virtualenv"},
{"callable <callable>", "set the callable (default 'application')"},
{"paste <config:/egg:>", "load applications using paste.deploy.loadapp()"},
{"pythonpath <dir>", "add <dir> to PYTHONPATH"},
{"python-path <dir>", "add <dir> to PYTHONPATH"},
{"pp <dir>", "add <dir> to PYTHONPATH"},
{"pyargv <args>", "assign args to python sys.argv"},
{"wsgi-file <file>", "load the <file> wsgi file"},
{"file <file>", "use python file instead of python module for configuration"},
{"eval <code>", "evaluate code for app configuration"},
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
{ 0, 0},
};
/* this routine will be called after each fork to reinitialize the various locks */
void uwsgi_python_pthread_prepare(void) {
pthread_mutex_lock(&up.lock_pyloaders);
@@ -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,
};
-1
View File
@@ -5,7 +5,6 @@ extern struct uwsgi_python up;
int manage_python_response(struct wsgi_request *wsgi_req) {
// use standard WSGI response parse
wsgi_req->switches++;
return uwsgi_response_subhandler_wsgi(wsgi_req);
}
+61 -7
View File
@@ -813,16 +813,16 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_async_sleep(PyObject * self, PyObject * args) {
float timeout;
time_t sec_timeout;
int sec_timeout;
if (!PyArg_ParseTuple(args, "f:async_sleep", &timeout)) {
return NULL;
}
sec_timeout = (time_t) timeout;
sec_timeout = (int) timeout;
if (sec_timeout > 0) {
async_set_timeout(uwsgi.wsgi_req, sec_timeout);
async_add_timeout(uwsgi.wsgi_req, sec_timeout);
}
return PyString_FromString("");
@@ -2087,7 +2087,7 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
goto clear;
}
@@ -2242,7 +2242,7 @@ PyObject *py_uwsgi_suspend(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi.schedule_to_main(wsgi_req);
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
Py_INCREF(Py_True);
return Py_True;
@@ -2528,7 +2528,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
}
if (uwsgi.queue_size) {
uwsgi_log("locking queue\n");
uwsgi_wlock(uwsgi.queue_lock);
if (uwsgi_queue_push(message, msglen)) {
Py_INCREF(Py_True);
@@ -2539,7 +2538,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
res = Py_None;
}
uwsgi_rwunlock(uwsgi.queue_lock);
uwsgi_log("unlocked queue\n");
return res;
}
@@ -2611,6 +2609,56 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
long num = 0;
uint64_t size = 0;
char *message;
PyObject *res, *zero;
uint64_t base;
if (!PyArg_ParseTuple(args, "l:queue_last", &num)) {
return NULL;
}
if (uwsgi.queue_size) {
res = PyList_New(0);
uwsgi_rlock(uwsgi.queue_lock);
if (uwsgi.shared->queue_pos > 0) {
base = uwsgi.shared->queue_pos-1;
}
else {
base = uwsgi.queue_size-1;
}
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
while(num) {
message = uwsgi_queue_get(base, &size);
if (message && size) {
zero = PyString_FromStringAndSize(message, size);
PyList_Append(res, zero);
Py_DECREF(zero);
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
if (base > 0) {
base--;
}
else {
base = uwsgi.queue_size-1;
}
num--;
}
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
char *key;
@@ -2641,6 +2689,11 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
#endif
uwsgi_rlock(uwsgi.cache_lock);
value = uwsgi_cache_get(key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.cache_lock);
Py_INCREF(Py_None);
return Py_None;
}
res = PyString_FromStringAndSize(value, valsize);
#ifdef UWSGI_DEBUG
gettimeofday(&tv2, NULL);
@@ -2671,6 +2724,7 @@ static PyMethodDef uwsgi_cache_methods[] = {
static PyMethodDef uwsgi_queue_methods[] = {
{"queue_get", py_uwsgi_queue_get, METH_VARARGS, ""},
{"queue_last", py_uwsgi_queue_last, METH_VARARGS, ""},
{"queue_push", py_uwsgi_queue_push, METH_VARARGS, ""},
{"queue_pull", py_uwsgi_queue_pull, METH_VARARGS, ""},
{"queue_slot", py_uwsgi_queue_slot, METH_VARARGS, ""},
+6 -22
View File
@@ -1,6 +1,7 @@
#include "../../uwsgi.h"
#include <Python.h>
#include <frameobject.h>
#define MAX_PYTHONPATH 64
#define MAX_PYMODULE_ALIAS 64
@@ -13,10 +14,6 @@
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
#define Py_ssize_t ssize_t
#endif
@@ -110,8 +107,11 @@ struct uwsgi_python {
int ignore_script_name;
int catch_exceptions;
int current_recursion_depth;
struct _frame* current_frame;
int *current_recursion_depth;
struct _frame **current_frame;
int current_main_recursion_depth;
struct _frame *current_main_frame;
void (*swap_ts)(struct wsgi_request *, struct uwsgi_app *);
void (*reset_ts)(struct wsgi_request *, struct uwsgi_app *);
@@ -157,10 +157,6 @@ PyObject *py_eventfd_read(PyObject *, PyObject *);
PyObject *py_eventfd_write(PyObject *, PyObject *);
#ifdef UWSGI_STACKLESS
PyObject *py_uwsgi_stackless(PyObject *, PyObject *);
#endif
int manage_python_response(struct wsgi_request *);
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *, int);
@@ -174,18 +170,6 @@ ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
PyObject *py_uwsgi_write(PyObject *, PyObject *);
PyObject *py_uwsgi_spit(PyObject *, PyObject *);
#ifdef UWSGI_STACKLESS
struct stackless_req {
PyTaskletObject *tasklet;
struct wsgi_request *wsgi_req;
PyChannelObject *channel;
};
struct wsgi_request *find_request_by_tasklet(PyTaskletObject *);
void stackless_init(void);
void stackless_loop(void);
#endif
void init_pyargv(void);
#ifdef UWSGI_WEB3
+6 -4
View File
@@ -20,10 +20,12 @@ else:
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
LIBS.append('-lpython' + uver)
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
+41 -49
View File
@@ -17,9 +17,8 @@ PyObject *uwsgi_Input_iter(PyObject * self) {
PyObject *uwsgi_Input_next(PyObject * self) {
PyErr_SetNone(PyExc_StopIteration);
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input __iter__() is not implemented");
return NULL;
}
static void uwsgi_Input_free(uwsgi_Input *self) {
@@ -29,7 +28,7 @@ static void uwsgi_Input_free(uwsgi_Input *self) {
static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
long len = 0;
size_t remains, chunk_size;
size_t remains;
ssize_t rlen;
char *tmp_buf;
int fd;
@@ -75,27 +74,22 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
return res;
}
chunk_size = remains;
tmp_buf = uwsgi_malloc(remains);
while(remains) {
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
return PyErr_Format(PyExc_ValueError, "error waiting for wsgi.input data");
}
rlen = read(fd, tmp_buf + self->pos, remains);
if (rlen < 0) {
free(tmp_buf);
return PyErr_Format(PyExc_ValueError, "error reading wsgi.input data");
}
if (!rlen) break;
self->pos += rlen;
remains -= rlen;
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
}
res = PyString_FromStringAndSize(tmp_buf, chunk_size);
rlen = read(fd, tmp_buf, remains);
if (rlen < 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
self->pos += rlen;
res = PyString_FromStringAndSize(tmp_buf, rlen);
free(tmp_buf);
return res;
@@ -103,17 +97,19 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
static PyObject *uwsgi_Input_readline(uwsgi_Input *self, PyObject *args) {
return NULL;
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input readline() is not implemented");
}
static PyObject *uwsgi_Input_readlines(uwsgi_Input *self, PyObject *args) {
return NULL;
return PyErr_Format(PyExc_NotImplementedError, "wsgi.input readlines() is not implemented");
}
static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef uwsgi_Input_methods[] = {
@@ -196,12 +192,7 @@ PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd;
wsgi_req->async_waiting_fd_type = ASYNC_IN;
wsgi_req->async_waiting_fd_monitored = 0;
if (timeout > 0) {
wsgi_req->async_timeout = time(NULL) + timeout;
}
async_add_fd_read(wsgi_req, fd, timeout);
}
return PyString_FromString("");
@@ -218,12 +209,7 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
}
if (fd >= 0) {
wsgi_req->async_waiting_fd = fd;
wsgi_req->async_waiting_fd_type = ASYNC_OUT;
wsgi_req->async_waiting_fd_monitored = 0;
if (timeout > 0) {
wsgi_req->async_timeout = time(NULL) + timeout;
}
async_add_fd_write(wsgi_req, fd, timeout);
}
return PyString_FromString("");
@@ -249,13 +235,21 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
if (wsgi_req->async_timeout_expired) {
if (wsgi_req->async_timed_out) {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_True);
wsgi_req->async_timeout_expired = 0;
wsgi_req->async_timed_out = 0;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
}
if (wsgi_req->async_ready_fd) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.ready_fd", PyInt_FromLong(wsgi_req->async_last_ready_fd));
wsgi_req->async_ready_fd = 0;
}
else {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.ready_fd", Py_None);
}
return manage_python_response(wsgi_req);
}
#endif
@@ -268,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
}
+28 -18
View File
@@ -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:
-12
View File
@@ -225,18 +225,6 @@ clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
PyErr_Clear();
#ifdef UWSGI_DEBUG
if (wsgi_req->async_placeholder) {
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
}
if (wsgi_req->async_result) {
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
}
if (wsgi_req->async_app) {
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
}
#endif
UWSGI_RELEASE_GIL
return UWSGI_OK;
}
-3
View File
@@ -94,14 +94,12 @@ VALUE protected_fiber_loop() {
if (!wsgi_req) goto cycle;
uwsgi_log("request passed to fiber core %d\n", wsgi_req->async_id);
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
wsgi_req = find_wsgi_req_by_fd((int)uwsgi.async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
@@ -116,7 +114,6 @@ cycle:
//uwsgi_log("resuming fiber %d %p\n", current, fiber_list[current]);
uwsgi.wsgi_req = uwsgi.wsgi_requests[current];
uwsgi.wsgi_req->switches++;
if (uwsgi.wsgi_req->async_status != UWSGI_ACCEPTING) {
uwsgi_log("passing control to fiber %d\n", current);
rb_fiber_resume(fiber_list[current], 0, NULL);
+84
View File
@@ -0,0 +1,84 @@
#include "../python/uwsgi_python.h"
#include <stackless_api.h>
extern struct uwsgi_server uwsgi;
struct ustackless {
int enabled;
PyObject *callable;
PyTaskletObject **sl;
} usl;
struct option stackless_options[] = {
{"stackless", no_argument, &usl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_stackless_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(usl.sl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_stackless_request_method[] = {{"uwsgi_stackless_request", py_uwsgi_stackless_request, METH_VARARGS, ""}};
inline static void stackless_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
usl.sl[id] = PyTasklet_New(NULL, usl.callable);
PyObject *args = PyTuple_New(0);
PyTasklet_Setup(usl.sl[id], args, NULL);
Py_DECREF(args);
uwsgi.wsgi_req->suspended = 1;
}
PyTasklet_Run(usl.sl[id]);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void stackless_schedule_to_main(struct wsgi_request *wsgi_req) {
PyStackless_Schedule(Py_None, 1);
uwsgi.wsgi_req = wsgi_req;
}
int stackless_init() {
return 0;
}
void stackless_init_apps(void) {
if (!usl.enabled) {
return;
}
usl.sl = uwsgi_malloc( sizeof(PyTaskletObject *) * uwsgi.async );
usl.callable = PyCFunction_New(uwsgi_stackless_request_method, NULL);
uwsgi_log("enabled stackless engine\n");
uwsgi.schedule_to_main = stackless_schedule_to_main;
uwsgi.schedule_to_req = stackless_schedule_to_req;
return;
}
struct uwsgi_plugin stackless_plugin = {
.name = "stackless",
.init = stackless_init,
.init_apps = stackless_init_apps,
.options = stackless_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='stackless'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['stackless']
+41 -274
View File
@@ -12,7 +12,7 @@ struct uwsgi_ugreen {
int ugreen;
int stackpages;
ucontext_t main;
ucontext_t **contexts;
ucontext_t *contexts;
size_t u_stack_size;
} ug;
@@ -27,165 +27,60 @@ struct option ugreen_options[] = {
{ 0, 0, 0, 0 }
};
void u_green_loop(void);
void u_green_write_all(char *data, size_t len) {
struct wsgi_request *wsgi_req;
int i;
ssize_t rlen;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
rlen = write(wsgi_req->poll.fd, data, len);
if (rlen < 0) {
uwsgi_error("write()");
// mark core as plagued
wsgi_req->async_plagued = 1;
}
else {
wsgi_req->response_size += rlen;
}
}
}
void u_green_request() {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
}
void u_green_unpause_all() {
inline static void u_green_schedule_to_req() {
struct wsgi_request *wsgi_req;
int i;
int id = uwsgi.wsgi_req->async_id;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status == UWSGI_PAUSED) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
if (!uwsgi.wsgi_req->suspended) {
ug.contexts[id].uc_link = &ug.main;
makecontext(&ug.contexts[id], u_green_request, 0);
uwsgi.wsgi_req->suspended = 1;
}
}
if (uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->suspend(NULL);
}
swapcontext(&ug.main, &ug.contexts[id] );
static int u_green_blocking() {
struct wsgi_request* wsgi_req;
int i;
if (uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->resume) {
uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->resume(NULL);
}
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
return 0;
}
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
return -1;
}
inline static void u_green_schedule_to_main(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
uwsgi_log("uGreen EXITING TO MAIN\n");
swapcontext(ug.contexts[wsgi_req->async_id], &ug.main);
swapcontext(&ug.contexts[wsgi_req->async_id], &ug.main);
uwsgi_log("uGreen RETURNED FROM MAIN\n");
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
}
}
inline static void u_green_schedule_to_req(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
}
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
uwsgi.wsgi_req = wsgi_req;
uwsgi_log("SWAPCONTEXT to %p\n", ug.contexts[wsgi_req->async_id]);
//wsgi_req->async_switches++;
swapcontext(&ug.main, ug.contexts[wsgi_req->async_id] );
uwsgi_log("RESUMED\n");
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (uwsgi.p[wsgi_req->uh.modifier1]->resume) {
uwsgi.p[wsgi_req->uh.modifier1]->resume(wsgi_req);
}
}
}
void u_green_wait_for_fd(struct wsgi_request *wsgi_req, int fd, int etype, int timeout) {
if (fd < 0) return;
if (async_add(uwsgi.async_queue, fd, etype)) return;
wsgi_req->async_waiting_fd = fd;
wsgi_req->async_waiting_fd_type = etype;
wsgi_req->async_timeout = time(NULL) + timeout;
u_green_schedule_to_main(wsgi_req);
async_del(uwsgi.async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type);
wsgi_req->async_waiting_fd = -1;
wsgi_req->async_timeout = 0;
}
static void u_green_request(struct wsgi_request *wsgi_req, int async_id) {
uwsgi_log("request handler args %p %d\n", wsgi_req, async_id);
for(;;) {
uwsgi_log("accept()\n");
wsgi_req_setup(wsgi_req, async_id);
wsgi_req->async_status = UWSGI_ACCEPTING;
u_green_schedule_to_main(wsgi_req);
if (wsgi_req_accept(wsgi_req)) {
continue;
}
uwsgi_log("REQUEST ACCEPTED\n");
wsgi_req->async_status = UWSGI_OK;
// check here
//u_green_schedule_to_main(wsgi_req);
if (wsgi_req_recv(wsgi_req)) {
continue;
}
while(wsgi_req->async_status == UWSGI_AGAIN) {
u_green_schedule_to_main(wsgi_req);
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
}
u_green_schedule_to_main(wsgi_req);
uwsgi_close_request(wsgi_req);
}
}
int u_green_init() {
struct wsgi_request *wsgi_req;
static int i;
volatile int i;
if (!ug.ugreen) {
return 0;
}
ug.u_stack_size = UGREEN_DEFAULT_STACKSIZE;
@@ -196,168 +91,38 @@ int u_green_init() {
uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi.async, (unsigned long) ug.u_stack_size, (unsigned long) ug.u_stack_size/1024);
ug.contexts = malloc( sizeof(ucontext_t*) * uwsgi.async);
if (!ug.contexts) {
uwsgi_error("malloc()\n");
exit(1);
}
ug.contexts = uwsgi_malloc( sizeof(ucontext_t) * uwsgi.async);
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
ug.contexts[i] = malloc( sizeof(ucontext_t) );
if (!ug.contexts[i]) {
uwsgi_error("malloc()");
exit(1);
}
getcontext(ug.contexts[i]);
ug.contexts[i]->uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
getcontext(&ug.contexts[i]);
if (!ug.contexts[i]->uc_stack.ss_sp) {
ug.contexts[i].uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
if (!ug.contexts[i].uc_stack.ss_sp) {
uwsgi_error("mmap()");
exit(1);
}
// set guard pages for stack
if (mprotect(ug.contexts[i]->uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) {
if (mprotect(ug.contexts[i].uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
if (mprotect(ug.contexts[i]->uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) {
if (mprotect(ug.contexts[i].uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
ug.contexts[i]->uc_stack.ss_size = ug.u_stack_size;
ug.contexts[i].uc_stack.ss_size = ug.u_stack_size;
ug.contexts[i]->uc_link = NULL;
makecontext(ug.contexts[i], (void(*)(void)) u_green_request, 2, wsgi_req, i);
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
uwsgi_log("wsgi_req %d %d %p\n", wsgi_req->async_id, wsgi_req->async_status, ug.contexts[i]);
}
uwsgi_register_loop("ugreen", u_green_loop);
return 0;
}
void u_green_expire_timeouts() {
struct wsgi_request* wsgi_req;
int i;
time_t deadline = time(NULL);
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_timeout > 0) {
if (wsgi_req->async_timeout <= deadline) {
wsgi_req->async_status = UWSGI_AGAIN;
wsgi_req->async_timeout = 0;
}
}
}
}
static int u_green_get_timeout() {
struct wsgi_request* wsgi_req;
int i;
time_t curtime, tdelta = 0;
int ret = 0;
if (!uwsgi.async_running) return 0;
for(i=0;i<uwsgi.async;i++) {
wsgi_req = uwsgi.wsgi_requests[i];
if (wsgi_req->async_timeout > 0) {
if (tdelta <= 0 || tdelta > wsgi_req->async_timeout) {
tdelta = wsgi_req->async_timeout;
}
}
}
curtime = time(NULL);
ret = tdelta - curtime;
if (ret > 0) {
return ret;
}
return 0;
}
void u_green_loop() {
struct wsgi_request *wsgi_req;
int i, current = 0, timeout;
for(i=0;i<uwsgi.async;i++){
wsgi_req = uwsgi.wsgi_requests[i];
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
}
uwsgi.schedule_to_main = u_green_schedule_to_main;
uwsgi.schedule_to_req = u_green_schedule_to_req;
uwsgi_log("FFAR: %p\n", find_first_accepting_wsgi_req());
while(uwsgi.workers[uwsgi.mywid].manage_next_request) {
//uwsgi_log("i am uGreen...\n");
uwsgi.async_running = u_green_blocking();
timeout = u_green_get_timeout();
uwsgi.async_nevents = async_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running, timeout);
u_green_expire_timeouts();
if (uwsgi.async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi.async_nevents;i++) {
uwsgi_log("received I/O event on fd %d\n", uwsgi.async_events[i].ASYNC_FD);
if ( (int) uwsgi.async_events[i].ASYNC_FD == uwsgi.sockets[0].fd) {
wsgi_req = find_first_accepting_wsgi_req();
uwsgi_log("found wsgireq at %p\n", wsgi_req);
if (!wsgi_req) goto cycle;
uwsgi_log("found %d\n", wsgi_req->async_id);
u_green_schedule_to_req(wsgi_req);
uwsgi_log("ooops\n");
}
else {
uwsgi_log("fd ready\n");
wsgi_req = find_wsgi_req_by_fd(uwsgi.async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
u_green_schedule_to_req(wsgi_req);
}
else {
async_del(uwsgi.async_queue, uwsgi.async_events[i].ASYNC_FD, uwsgi.async_events[i].ASYNC_EV);
}
}
}
cycle:
wsgi_req = uwsgi.wsgi_requests[current];
uwsgi_log("schedule %d %d ?\n", current, wsgi_req->async_status);
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_status != UWSGI_PAUSED && wsgi_req->async_waiting_fd == -1 && !wsgi_req->async_timeout) {
uwsgi_log("schedule !\n");
u_green_schedule_to_req(wsgi_req);
}
current++;
if (current >= uwsgi.async) current = 0;
}
return 0;
}
@@ -376,4 +141,6 @@ struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
.init = u_green_init,
.options = ugreen_options,
.manage_opt = uwsgi_ugreen_manage_opt,
};
+257 -22
View File
@@ -16,6 +16,112 @@ static size_t get_content_length(char *buf, uint16_t size) {
return val;
}
void set_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
struct tm *hdtm = gmtime(&t);
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
week[hdtm->tm_wday], hdtm->tm_mday,
months[hdtm->tm_mon], hdtm->tm_year+1900,
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
}
// only RFC 1123 is supported
time_t parse_http_date(char *date, uint16_t len) {
struct tm hdtm;
if (len != 29 && date[3] != ',') return 0;
hdtm.tm_mday = uwsgi_str2_num(date+5);
switch(date[8]) {
case 'J':
if (date[9] == 'a') {
hdtm.tm_mon = 0;
break;
}
if (date[9] == 'u') {
if (date[10] == 'n') {
hdtm.tm_mon = 5;
break;
}
if (date[10] == 'l') {
hdtm.tm_mon = 6;
break;
}
return 0;
}
return 0;
case 'F':
hdtm.tm_mon = 1;
break;
case 'M':
if (date[9] != 'a') return 0;
if (date[10] == 'r') {
hdtm.tm_mon = 2;
break;
}
if (date[10] == 'y') {
hdtm.tm_mon = 4;
break;
}
return 0;
case 'A':
if (date[10] == 'r') {
hdtm.tm_mon = 3;
break;
}
if (date[10] == 'g') {
hdtm.tm_mon = 7;
break;
}
return 0;
case 'S':
hdtm.tm_mon = 8;
break;
case 'O':
hdtm.tm_mon = 9;
break;
case 'N':
hdtm.tm_mon = 10;
case 'D':
hdtm.tm_mon = 11;
break;
default:
return 0;
}
hdtm.tm_year = uwsgi_str4_num(date+12)-1900;
hdtm.tm_hour = uwsgi_str2_num(date+17);
hdtm.tm_min = uwsgi_str2_num(date+20);
hdtm.tm_sec = uwsgi_str2_num(date+23);
return timegm(&hdtm);
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
@@ -346,21 +452,27 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
return 0;
}
// older OSX versions make mess with CMSG_FIRSTHDR
#ifdef __APPLE__
if (!msg.msg_controllen) return 1;
#endif
cmsg = CMSG_FIRSTHDR (&msg);
while(cmsg != NULL) {
if (cmsg->cmsg_len != CMSG_LEN (sizeof (int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) continue;
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type && SCM_RIGHTS) {
// upgrade connection to the new socket
#ifdef UWSGI_DEBUG
uwsgi_log("upgrading fd %d to ", upoll->fd);
uwsgi_log("upgrading fd %d to ", upoll->fd);
#endif
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
#ifdef UWSGI_DEBUG
uwsgi_log("%d\n", upoll->fd);
uwsgi_log("%d\n", upoll->fd);
#endif
}
cmsg = CMSG_NXTHDR (&msg, cmsg);
}
@@ -516,6 +628,18 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->file = ptrbuf;
wsgi_req->file_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
wsgi_req->touch_reload_len = strsize;
}
else if (uwsgi.cache_max_items > 0 && !uwsgi_strncmp("UWSGI_CACHE_GET", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->cache_get = ptrbuf;
wsgi_req->cache_get_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_SETENV", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
char *env_value = memchr(ptrbuf, '=', strsize);
if (env_value) {
@@ -545,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;
}
+21
View File
@@ -19,6 +19,25 @@ char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
}
void uwsgi_queue_fix() {
uint64_t i;
char *value;
uint64_t size;
for(i=0;i< uwsgi.queue_size;i++) {
// valid record ?
value = uwsgi_queue_get(i, &size);
if (value && size) {
uwsgi.shared->queue_pos++;
}
else {
return;
}
}
}
char *uwsgi_queue_pop(uint64_t *size) {
struct uwsgi_queue_item *uqi;
@@ -70,6 +89,8 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
uqi = (struct uwsgi_queue_item *) ptr;
+21 -8
View File
@@ -8,25 +8,38 @@ from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
def patch_bin_path(cmd, conf):
bin_name = conf.get('bin_name')
try:
if not os.path.exists(cmd.install_scripts):
os.makedirs(cmd.install_scripts)
if not os.path.isabs(bin_name):
print('Patching "bin_name" to properly install_scripts dir')
conf.set('bin_name', os.path.join(cmd.install_scripts, conf.get('bin_name')))
except:
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
class uWSGIBuilder(build_ext):
def run(self):
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution for 0.9.6
# hack, hack and still hack. We need to find a solution...
if self.record:
record_file = open(self.record,'w')
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIDistribution(Distribution):
@@ -38,7 +51,7 @@ class uWSGIDistribution(Distribution):
setup(name='uWSGI',
version='0.9.7-dev',
version='0.9.7.2',
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
+20
View File
@@ -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;
+4 -4
View File
@@ -53,7 +53,7 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size) {
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(filename);
uwsgi_unlock(uwsgi.spooler_lock);
return 0;
}
@@ -135,7 +135,7 @@ void spooler() {
nullfd = open("/dev/null", O_RDONLY);
if (nullfd < 0) {
uwsgi_error("open()");
uwsgi_error_open("/dev/null");
exit(1);
}
@@ -164,7 +164,7 @@ void spooler() {
spool_fd = open(dp->d_name, O_RDONLY);
if (spool_fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(dp->d_name);
continue;
}
@@ -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
View File
@@ -1,137 +0,0 @@
#ifdef UWSGI_STACKLESS
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
struct wsgi_request* find_request_by_tasklet(PyTaskletObject *tasklet) {
int i;
for(i=0;i<uwsgi.async;i++) {
if (uwsgi.stackless_table[i]->tasklet == tasklet) {
return uwsgi.stackless_table[i]->wsgi_req;
}
}
return NULL;
}
PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
PyThreadState *ts = PyThreadState_GET();
struct wsgi_request *wsgi_req = find_request_by_tasklet(ts->st.current);
PyObject *zero;
int async_id = wsgi_req->async_id;
//uwsgi_log("i am the tasklet worker\n");
for(;;) {
// wait for request
zero = PyChannel_Receive(uwsgi.workers_channel);
wsgi_req_setup(wsgi_req, async_id);
if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
continue;
}
uwsgi_close_request(&uwsgi, wsgi_req);
}
}
PyMethodDef uwsgi_stackless_worker[] = { {"uwsgi_stackless_worker", py_uwsgi_stackless_worker, METH_VARARGS, ""} };
void stackless_init(struct uwsgi_server *uwsgi) {
int i;
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests;
PyObject *tasklet_worker = PyCFunction_New(uwsgi_stackless_worker, NULL);
uwsgi->workers_channel = PyChannel_New(NULL);
uwsgi->stackless_table = malloc( sizeof(struct stackless_req*) * uwsgi->async);
if (!uwsgi->stackless_table) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->stackless_table[i] = malloc(sizeof(struct stackless_req));
if (!uwsgi->stackless_table[i]) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
uwsgi_log("initializing %d tasklet...", uwsgi->async);
// creating uwsgi->async tasklets
for(i=0;i<uwsgi->async;i++) {
wsgi_req->tasklet = PyTasklet_New(NULL, tasklet_worker);
uwsgi->stackless_table[i]->tasklet = wsgi_req->tasklet;
uwsgi->stackless_table[i]->wsgi_req = wsgi_req;
// useless for now, it will be used for I/O or other messaging
uwsgi->stackless_table[i]->channel = NULL;
wsgi_req->async_id = i;
PyTasklet_Setup(wsgi_req->tasklet, PyTuple_New(0), NULL);
//PyTasklet_Run(wsgi_req->tasklet);
wsgi_req = next_wsgi_req(uwsgi, wsgi_req);
}
uwsgi_log("done\n");
}
void stackless_loop(struct uwsgi_server *uwsgi) {
int i;
PyTaskletObject *int_tasklet;
// tasklets main loop
for(;;) {
//uwsgi->async_running = -1;
//if (PyStackless_GetRunCount() > 0) {
uwsgi->async_running = 0;
//}
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, 0);
if (uwsgi->async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
//pass the connection to the first available tasklet
uwsgi_log("sending new connection...\n");
PyChannel_Send(uwsgi->workers_channel, Py_True);
}
}
/*
if (PyStackless_GetRunCount() > 0) {
PyStackless_Schedule(Py_None, 0);
}
*/
PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
uwsgi_log("done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
uwsgi_log("re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
uwsgi_log("recycle\n");
*/
}
}
#endif
+25 -29
View File
@@ -1,47 +1,43 @@
import socket
import select
import errno
import uwsgi
def send_request(env, client):
client.setblocking(1)
uwsgi.send(client, b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
# test for suspend/resume
uwsgi.suspend()
uwsgi.send(client, b"Host: www.google.it\r\n\r\n")
client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")
while 1:
yield env['x-wsgiorg.fdevent.readable'](client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield uwsgi.wait_fd_read(client, 2)
if env['x-wsgiorg.fdevent.timeout']:
return
buf = uwsgi.recv(client, 4096)
if buf:
yield buf
else:
break
def application(env, start_response):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
c = uwsgi.async_connect('74.125.232.115:80')
#env['x-wsgiorg.fdevent.readable'] = lambda fd,t: ""
#env['x-wsgiorg.fdevent.writable'] = lambda fd,t: ""
# wait for connection
yield uwsgi.wait_fd_write(c, 2)
if env['x-wsgiorg.fdevent.timeout']:
uwsgi.close(c)
raise StopIteration
#yield ""
print "opening socket"
c = s.connect_ex(('www.google.it', 80))
if c == errno.EINPROGRESS:
print "yielding"
yield env['x-wsgiorg.fdevent.writable'](s.fileno(), 10)
print "waiting for fd write"
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
if uwsgi.is_connected(c):
for r in send_request(env, c):
yield r
else:
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"
s.close()
uwsgi.close(c)
+1
View File
@@ -1,4 +1,5 @@
import sys
import uwsgi
content_type = 'image/png'
filename = 'logo_uWSGI.png'
+211 -28
View File
@@ -70,6 +70,12 @@ void daemonize(char *logfile) {
pid_t pid;
int fdin;
// do not daemonize under emperor
if (uwsgi.has_emperor) {
logto(logfile);
return;
}
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
@@ -104,7 +110,7 @@ void daemonize(char *logfile) {
fdin = open("/dev/null", O_RDWR);
if (fdin < 0) {
uwsgi_error("open()");
uwsgi_error_open("/dev/null");
exit(1);
}
@@ -155,7 +161,7 @@ void logto(char *logfile) {
#endif
fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error("open()");
uwsgi_error_open(logfile);
exit(1);
}
#ifdef UWSGI_UDP
@@ -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;
}
+703 -167
View File
File diff suppressed because it is too large Load Diff
+175 -43
View File
@@ -2,11 +2,12 @@
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
#define UWSGI_VERSION "0.9.7-dev"
#define UWSGI_VERSION "0.9.7.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
View File
@@ -71,6 +71,9 @@ def build_uwsgi(uc):
eplc = "-DUWSGI_LOAD_EMBEDDED_PLUGINS=\""
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
epc += "UDEP(%s);" % p
eplc += "ULEP(%s);" % p
epc += "\""
@@ -93,6 +96,10 @@ def build_uwsgi(uc):
print("*** uWSGI compiling embedded plugins ***")
for p in ep:
p = p.rstrip().lstrip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
continue
path = 'plugins/%s' % p
path = path.rstrip('/')
@@ -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")
+1 -1
View File
@@ -358,7 +358,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
xmlfd = open(uwsgi.xml_config, O_RDONLY);
if (xmlfd < 0) {
uwsgi_error("open()");
uwsgi_error_open(uwsgi.xml_config);
exit(1);
}