Compare commits

..
1 Commits
Author SHA1 Message Date
Unbit 41bc23bb40 backports from 1.9.19 2013-10-16 20:58:20 +02:00
193 changed files with 4432 additions and 11091 deletions
+3 -11
View File
@@ -1,16 +1,8 @@
PYTHON := python
all:
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
python uwsgiconfig.py --build
clean:
$(PYTHON) uwsgiconfig.py --clean
python uwsgiconfig.py --clean
check:
$(PYTHON) uwsgiconfig.py --check
plugin.%:
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
%:
$(PYTHON) uwsgiconfig.py --build $@
python uwsgiconfig.py --check
+2 -4
View File
@@ -1,5 +1,3 @@
The uWSGI project
surprise i am empty !
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
For commercial support check: http://unbit.com/
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,zabbix,curl_cron,tornado,tuntap,pty,mongrel2,alarm_curl,router_radius,airbrake
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
inherit = base
+5 -1
View File
@@ -2,18 +2,22 @@
xml = auto
yaml = true
json = auto
zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires, router_metrics, transformation_template, stats_pusher_socket
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
as_shared_library = false
locking = auto
+2 -1
View File
@@ -1,3 +1,4 @@
[uwsgi]
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = gccgo
inherit = base
+1
View File
@@ -1,3 +1,4 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
+4
View File
@@ -2,11 +2,15 @@
xml = false
yaml = false
json = false
zeromq = false
ssl = false
pcre = false
routing = false
matheval = false
debug = false
unbit = false
xml_implementation = none
yaml_implementation = none
malloc_implementation = libc
extras =
plugins =
+5 -2
View File
@@ -1,12 +1,15 @@
[uwsgi]
xml = libxml2
yaml = libyaml
xml = true
yaml = true
json = true
zeromq = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = libyaml
malloc_implementation = libc
extras =
plugins =
+5 -2
View File
@@ -1,12 +1,15 @@
[uwsgi]
xml = expat
yaml = embedded
xml = true
yaml = true
json = false
zeromq = false
ssl = true
pcre = true
routing = true
debug = false
unbit = true
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
-29
View File
@@ -1,29 +0,0 @@
[uwsgi]
xml = expat
yaml = embedded
json = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = /opt/unbit/uwsgi/plugins
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+38 -88
View File
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
/*
This is a general-purpose async loop engine (it expects a coroutine-based approach)
This is a general purpose async loop engine (it expects a coroutine based approach)
You can see it as an hub holding the following structures:
1) the runqueue, cores ready to be run are appended to this list
1) the runqueue, cores ready to be run are appended in this list
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
IMPORTANT: this is not a callback-based engine !!!
IMPORTANT: this is not a callback based engine !!!
*/
@@ -28,6 +28,7 @@ void uwsgi_async_queue_is_full(time_t now) {
}
void uwsgi_async_init() {
int i;
uwsgi.async_queue = event_queue_init();
@@ -39,9 +40,16 @@ void uwsgi_async_init() {
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
// optimization, this array maps file descriptor to requests
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
// a stack of unused cores
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
// fill it with default values
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
// the first available core is the last one
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
@@ -151,7 +159,7 @@ static void async_expire_timeouts(uint64_t now) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
// reset the request
// reset teh request
async_reset_request(wsgi_req);
// push it in the runqueue
runqueue_push(wsgi_req);
@@ -165,11 +173,6 @@ static void async_expire_timeouts(uint64_t now) {
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
@@ -221,47 +224,8 @@ static int async_wait_fd_read(int fd, int timeout) {
return 1;
}
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
return -1;
}
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
// reset already registered fd
async_reset_request(wsgi_req);
return -1;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
if (wsgi_req->async_ready_fd) {
*fd = wsgi_req->async_last_ready_fd;
return 1;
}
return -1;
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return;
}
wsgi_req->async_ready_fd = 0;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
@@ -272,11 +236,6 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
return -1;
}
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
@@ -336,8 +295,9 @@ void async_schedule_to_req(void) {
// a trick to avoid calling routes again
uwsgi.wsgi_req->is_routing = 1;
#endif
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
goto end;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(uwsgi.wsgi_req);
@@ -348,43 +308,29 @@ end:
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
void async_schedule_to_req_green(void) {
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
if (wsgi_req->async_status <= UWSGI_OK) {
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
break;
}
wsgi_req->switches++;
if (uwsgi.schedule_fix) {
uwsgi.schedule_fix(wsgi_req);
}
uwsgi.wsgi_req->switches++;
// switch after each yield
uwsgi.schedule_to_main(wsgi_req);
uwsgi.schedule_to_main(uwsgi.wsgi_req);
}
#ifdef UWSGI_ROUTING
end:
#endif
// re-set the global state
uwsgi.wsgi_req = wsgi_req;
async_reset_request(wsgi_req);
uwsgi_close_request(wsgi_req);
// re-set the global state (routing could have changed it)
uwsgi.wsgi_req = wsgi_req;
wsgi_req->async_status = UWSGI_OK;
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
}
void async_loop() {
@@ -407,13 +353,10 @@ void async_loop() {
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi_async_init();
uwsgi.async_runqueue = NULL;
uwsgi.wait_write_hook = async_wait_fd_write;
uwsgi.wait_read_hook = async_wait_fd_read;
uwsgi.wait_read2_hook = async_wait_fd_read2;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
@@ -522,8 +465,7 @@ void async_loop() {
// remove fd from event poll and fd proto table
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
uwsgi.wsgi_req->async_status = UWSGI_OK;
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
}
@@ -533,7 +475,7 @@ void async_loop() {
continue;
}
// re-add timer
async_add_timeout(uwsgi.wsgi_req, uwsgi.socket_timeout);
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
continue;
}
@@ -569,11 +511,19 @@ void async_loop() {
uwsgi.wsgi_req->switches++;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove from the runqueue
runqueue_remove(current_request);
// 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 the runqueue
runqueue_remove(current_request);
}
current_request = next_request;
}
+6 -19
View File
@@ -64,7 +64,7 @@ int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len)
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret >= 19) {
if (ret <= 0 || ret > 19) {
return -1;
}
return uwsgi_buffer_insert(ub, pos, chunked, ret);
@@ -74,7 +74,7 @@ int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret >= 19) {
if (ret <= 0 || ret > 19) {
return -1;
}
return uwsgi_buffer_append(ub, chunked, ret);
@@ -204,19 +204,6 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
uint8_t buf[8];
buf[0] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[2] = (uint8_t) ((num >> 16) & 0xff);
buf[3] = (uint8_t) ((num >> 24) & 0xff);
buf[4] = (uint8_t) ((num >> 32) & 0xff);
buf[5] = (uint8_t) ((num >> 40) & 0xff);
buf[6] = (uint8_t) ((num >> 48) & 0xff);
buf[7] = (uint8_t) ((num >> 56) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
uint8_t buf[8];
@@ -245,7 +232,7 @@ int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
@@ -268,7 +255,7 @@ int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t ke
int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keylen, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
@@ -280,7 +267,7 @@ int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keyl
int uwsgi_buffer_append_valnum(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, ret)) return -1;
@@ -340,7 +327,7 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
char *ptr = ub->buf;
while (remains > 0) {
int ret = uwsgi_waitfd_write(fd, uwsgi.socket_timeout);
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len > 0) {
+16 -16
View File
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
}
// mark used blocks;
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
// optimize the scan
// optimize teh scan
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
uc->blocks_bitmap_pos = 0;
}
@@ -1432,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
// ok now wait for the response, using the same buffer of the request
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
// try to fix the buffer to maintain size info
ub->pos = rlen;
@@ -1483,7 +1483,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return NULL;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return NULL;
@@ -1495,7 +1495,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
return NULL;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return NULL;
@@ -1526,7 +1526,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
}
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.socket_timeout)) {
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
close(fd);
uwsgi_buffer_destroy(ub);
return NULL;
@@ -1585,7 +1585,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return 0;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return 0;
@@ -1597,7 +1597,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
return 0;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return 0;
@@ -1652,7 +1652,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return -1;
@@ -1670,7 +1670,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
return -1;
}
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.socket_timeout, &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1730,7 +1730,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return -1;
@@ -1742,7 +1742,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
return -1;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1803,7 +1803,7 @@ int uwsgi_cache_magic_clear(char *cache) {
int fd = uwsgi_connect(cache_server, 0, 1);
if (fd < 0) return -1;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return -1;
@@ -1815,7 +1815,7 @@ int uwsgi_cache_magic_clear(char *cache) {
return -1;
}
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
close(fd);
uwsgi_buffer_destroy(ub);
return -1;
@@ -1859,7 +1859,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
goto next;
}
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.socket_timeout)) {
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to write to the cache server\n");
close(fd);
@@ -1867,7 +1867,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
}
size_t rlen = ub->pos;
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.socket_timeout, NULL, NULL)) {
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
close(fd);
@@ -1876,7 +1876,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
uwsgi_hooked_parse(ub->buf, rlen, cache_sync_hook, uc);
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.socket_timeout)) {
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub);
close(fd);
uwsgi_log("[cache-sync] unable to read from the cache server\n");
+1 -1
View File
@@ -20,7 +20,7 @@ extern struct uwsgi_server uwsgi;
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
if (timeout == 0) timeout = uwsgi.socket_timeout;
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int ret = -1;
-5
View File
@@ -2,11 +2,6 @@
extern struct uwsgi_server uwsgi;
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
return poll(NULL, 0, timeout);
}
// in the future we will need to use the best clock source for each os/system
time_t uwsgi_now() {
return uwsgi.clock->seconds();
-170
View File
@@ -493,10 +493,6 @@ add:
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// enable metrics ?
if (op->flags & UWSGI_OPT_METRICS) {
uwsgi.has_metrics = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
@@ -633,169 +629,3 @@ clear:
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
/*
this works as a pipeline
processes = 2
cpu_cores = 8
foobar = %(processes cpu_cores + 2)
translate as:
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
step1 + = step1_apply_func_plus (func token)
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
*/
char *uwsgi_manage_placeholder(char *key) {
enum {
concat = 0,
sum,
sub,
mul,
div,
} state;
state = concat;
char *current_value = NULL;
char *space = strchr(key, ' ');
if (!space) {
return uwsgi_get_exported_opt(key);
}
// let's start the heavy metal here
char *tmp_value = uwsgi_str(key);
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
char *value = NULL;
if (is_a_number(p)) {
value = uwsgi_str(p);
}
else if (!strcmp(p, "+")) {
state = sum;
continue;
}
else if (!strcmp(p, "-")) {
state = sub;
continue;
}
else if (!strcmp(p, "*")) {
state = mul;
continue;
}
else if (!strcmp(p, "/")) {
state = div;
continue;
}
else if (!strcmp(p, "++")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num+1);
}
state = concat;
continue;
}
else if (!strcmp(p, "--")) {
if (current_value) {
int64_t tmp_num = strtoll(current_value, NULL, 10);
free(current_value);
current_value = uwsgi_64bit2str(tmp_num-1);
}
state = concat;
continue;
}
// find the option
else {
char *ov = uwsgi_get_exported_opt(p);
if (!ov) ov = "";
value = uwsgi_str(ov);
}
int64_t arg1n = 0, arg2n = 0;
char *arg1 = "", *arg2 = "";
switch(state) {
case concat:
if (current_value) arg1 = current_value;
if (value) arg2 = value;
char *ret = uwsgi_concat2(arg1, arg2);
if (current_value) free(current_value);
current_value = ret;
break;
case sum:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n + arg2n);
break;
case sub:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n - arg2n);
break;
case mul:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
current_value = uwsgi_64bit2str(arg1n * arg2n);
break;
case div:
if (current_value) arg1n = strtoll(current_value, NULL, 10);
if (value) arg2n = strtoll(value, NULL, 10);
if (current_value) free(current_value);
// avoid division by zero
if (arg2n == 0) {
current_value = uwsgi_64bit2str(0);
}
else {
current_value = uwsgi_64bit2str(arg1n / arg2n);
}
break;
default:
break;
}
// over engineering
if (value)
free(value);
// reset state to concat
state = concat;
}
free(tmp_value);
return current_value;
}
+16 -134
View File
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
External uwsgi daemons
There are 3 kinds of daemons (read: external applications) that can be managed
There are 3 kind of daemons (read: external applications) that can be managed
by uWSGI.
1) dumb daemons (attached with --attach-daemon)
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
and the process is respawned
2) smart daemons with daemonization
you specify a pidfile and a command
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master check - if the pidfile does not exist or if it points to a non-existent pid
the daemon is respawned
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
the daemon is respawned
3) smart daemons without daemonization
same as 2, but the daemonization and pidfile creation are managed by uWSGI
same as 2, but the daemonization and pidfile creation is managed by uWSGI
status:
@@ -55,7 +55,7 @@ void uwsgi_daemons_smart_check() {
if (ud->pid > 0) {
if (!kill(ud->pid, 0)) {
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
kill(-ud->pid, ud->stop_signal);
kill(-ud->pid, SIGTERM);
}
else {
// pid already died
@@ -232,16 +232,16 @@ void uwsgi_detach_daemons() {
if (ud->pid > 0 && !ud->pidfile) {
#endif
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
// try to stop daemon gracefully, kill it if it won't die
// if mercy is not set then wait up to 3 seconds
// try to gracefully stop daemon, kill it if it won't die
// if mercy is not set than wait up to 3 seconds
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
int waitpid_status;
while (!kill(ud->pid, 0)) {
kill(-ud->pid, ud->stop_signal);
kill(-ud->pid, SIGTERM);
sleep(1);
waitpid(-ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
kill(-ud->pid, SIGKILL);
break;
}
@@ -263,8 +263,6 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
// if ud->respawns == 0 then we can end up with throttle < 0
if (throttle <= 0) throttle = 1;
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
@@ -291,20 +289,6 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_close_all_sockets();
uwsgi_close_all_fds();
if (ud->gid) {
if (setgid(ud->gid)) {
uwsgi_error("uwsgi_spawn_daemon()/setgid()");
exit(1);
}
}
if (ud->uid) {
if (setuid(ud->uid)) {
uwsgi_error("uwsgi_spawn_daemon()/setuid()");
exit(1);
}
}
if (ud->daemonize) {
/* refork... */
pid = fork();
@@ -318,7 +302,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_write_pidfile(ud->pidfile);
}
if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
if (!uwsgi.daemons_honour_stdin) {
// /dev/null will became stdin
uwsgi_remap_fd(0, "/dev/null");
}
@@ -339,10 +323,10 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
sleep((unsigned int) throttle);
sleep(throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
uwsgi_exec_command_with_args(ud->command);
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
@@ -361,8 +345,6 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
int daemonize = 0;
int freq = 10;
char *space = NULL;
int stop_signal = SIGTERM;
int reload_signal = 0;
char *command = uwsgi_str(value);
@@ -401,7 +383,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
}
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
@@ -410,7 +392,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
@@ -425,8 +407,6 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi_ud->control = 0;
uwsgi_ud->stop_signal = stop_signal;
uwsgi_ud->reload_signal = reload_signal;
if (!strcmp(opt, "attach-control-daemon")) {
uwsgi_ud->control = 1;
}
@@ -437,101 +417,3 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi.daemons_cnt++;
}
void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
char *d_command = NULL;
char *d_freq = NULL;
char *d_pidfile = NULL;
char *d_control = NULL;
char *d_legion = NULL;
char *d_daemonize = NULL;
char *d_touch = NULL;
char *d_stopsignal = NULL;
char *d_reloadsignal = NULL;
char *d_stdin = NULL;
char *d_uid = NULL;
char *d_gid = NULL;
char *arg = uwsgi_str(value);
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"command", &d_command,
"cmd", &d_command,
"exec", &d_command,
"freq", &d_freq,
"pidfile", &d_pidfile,
"control", &d_control,
"daemonize", &d_daemonize,
"daemon", &d_daemonize,
"touch", &d_touch,
"stopsignal", &d_stopsignal,
"stop_signal", &d_stopsignal,
"reloadsignal", &d_reloadsignal,
"reload_signal", &d_reloadsignal,
"stdin", &d_stdin,
"uid", &d_uid,
"gid", &d_gid,
NULL)) {
uwsgi_log("invalid --%s keyval syntax\n", opt);
exit(1);
}
if (!d_command) {
uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
exit(1);
}
#ifndef UWSGI_SSL
if (d_legion) {
uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
exit(1);
}
#endif
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
while (uwsgi_ud) {
old_ud = uwsgi_ud;
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
uwsgi_ud->command = d_command;
uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
uwsgi_ud->pidfile = d_pidfile;
uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
uwsgi_ud->control = d_control ? 1 : 0;
uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
#ifdef UWSGI_SSL
uwsgi_ud->legion = d_legion;
#endif
if (d_touch) {
size_t i,rlen = 0;
char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
for(i=0;i<rlen;i++) {
uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
}
if (argv) free(argv);
}
uwsgi.daemons_cnt++;
free(arg);
}
+11 -61
View File
@@ -59,12 +59,12 @@ void uwsgi_emperor_blacklist_add(char *id) {
uebi->throttle_level += (uwsgi.emperor_throttle * 1000);
}
else {
uwsgi_log_verbose("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
uwsgi_log("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
uebi->throttle_level = uebi->throttle_level / 2;
}
uebi->attempt++;
if (uebi->attempt == 2) {
uwsgi_log_verbose("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
uwsgi_log("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
}
return;
}
@@ -603,7 +603,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
uwsgi_log("[emperor] %s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
}
uwsgi_log_verbose("[emperor] removed uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] removed uwsgi instance %s\n", c_ui->name);
// put the instance in the blacklist (or update its throttling value)
if (!c_ui->loyal) {
uwsgi_emperor_blacklist_add(c_ui->name);
@@ -632,7 +632,7 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log_verbose("[emperor] stop the uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_curse(struct uwsgi_instance *c_ui) {
@@ -642,7 +642,7 @@ void emperor_curse(struct uwsgi_instance *c_ui) {
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log_verbose("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
uwsgi_log("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
}
@@ -675,12 +675,8 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
c_ui->respawns++;
c_ui->last_mod = mod;
c_ui->last_run = uwsgi_now();
// reset readyness
c_ui->ready = 0;
// reset accepting
c_ui->accepting = 0;
uwsgi_log_verbose("[emperor] reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
@@ -701,12 +697,12 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
gettimeofday(&tv, NULL);
int now = tv.tv_sec;
uint64_t micros = (tv.tv_sec * 1000ULL * 1000ULL) + tv.tv_usec;
uint64_t micros = (tv.tv_sec * 1000 * 1000) + tv.tv_usec;
// blacklist check
struct uwsgi_emperor_blacklist_item *uebi = uwsgi_emperor_blacklist_check(name);
if (uebi) {
uint64_t i_micros = (uebi->last_attempt.tv_sec * 1000ULL * 1000ULL) + uebi->last_attempt.tv_usec + uebi->throttle_level;
uint64_t i_micros = (uebi->last_attempt.tv_sec * 1000 * 1000) + uebi->last_attempt.tv_usec + uebi->throttle_level;
if (i_micros > micros) {
return;
}
@@ -767,9 +763,6 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->uid = uid;
n_ui->gid = gid;
n_ui->last_mod = born;
// start non-ready
n_ui->last_ready = 0;
n_ui->ready = 0;
// start without loyalty
n_ui->last_loyal = 0;
n_ui->loyal = 0;
@@ -981,7 +974,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
#endif
#ifdef UWSGI_CAP
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
int i;
for(i=0;i<=CAP_LAST_CAP;i++) {
@@ -1018,7 +1010,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
}
#endif
#endif
#endif
if (uwsgi.emperor_tyrant) {
@@ -1109,7 +1100,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
struct uwsgi_string_list *uct;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
@@ -1132,12 +1122,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
counter += 2;
}
uwsgi_foreach (uct, uwsgi.vassals_set) {
vassal_argv[counter] = "--set";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
@@ -1559,7 +1543,7 @@ void emperor_loop() {
if (byte == 17) {
ui_current->loyal = 1;
ui_current->last_loyal = uwsgi_now();
uwsgi_log_verbose("[emperor] vassal %s is now loyal\n", ui_current->name);
uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name);
// remove it from the blacklist
uwsgi_emperor_blacklist_remove(ui_current->name);
// TODO post-start hook
@@ -1572,22 +1556,12 @@ void emperor_loop() {
emperor_stop(ui_current);
}
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log_verbose("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
// here we discard socket name as broodlord/zerg cannot be on demand
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
free(zerg_name);
}
else if (byte == 5) {
ui_current->accepting = 1;
ui_current->last_accepting = uwsgi_now();
uwsgi_log_verbose("[emperor] vassal %s is ready to accept requests\n", ui_current->name);
}
else if (byte == 1) {
ui_current->ready = 1;
ui_current->last_ready = uwsgi_now();
uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name);
}
}
}
else {
@@ -1790,16 +1764,8 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_keylong_comma(us, "loyal", (unsigned long long) c_ui->loyal))
goto end0;
if (uwsgi_stats_keylong_comma(us, "ready", (unsigned long long) c_ui->ready))
goto end0;
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) c_ui->accepting))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_loyal", (unsigned long long) c_ui->last_loyal))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_ready", (unsigned long long) c_ui->last_ready))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_accepting", (unsigned long long) c_ui->last_accepting))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_run", (unsigned long long) c_ui->first_run))
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
@@ -1889,7 +1855,7 @@ void emperor_send_stats(int fd) {
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
@@ -2052,14 +2018,12 @@ void uwsgi_master_manage_emperor() {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
uwsgi_hooks_run(uwsgi.hook_emperor_stop, "emperor-stop", 0);
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
uwsgi_hooks_run(uwsgi.hook_emperor_reload, "emperor-reload", 0);
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
@@ -2069,7 +2033,6 @@ void uwsgi_master_manage_emperor() {
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
uwsgi_hooks_run(uwsgi.hook_emperor_lost, "emperor-lost", 0);
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
@@ -2133,16 +2096,3 @@ void uwsgi_master_manage_emperor_proxy() {
close(ep_client);
}
static void emperor_notify_ready() {
if (!uwsgi.has_emperor) return;
char byte = 1;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("emperor_notify_ready()/write()");
}
}
void uwsgi_setup_emperor() {
if (!uwsgi.has_emperor) return;
uwsgi.notify_ready = emperor_notify_ready;
}
-23
View File
@@ -1,30 +1,9 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
struct stat st;
if (!stat(usl->value, &st)) {
int fd = open(usl->value, O_RDONLY);
if (fd >= 0) {
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
return -1;
}
}
}
return 0;
}
// generate internal server error message
void uwsgi_500(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
}
@@ -32,7 +11,6 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
void uwsgi_404(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
}
@@ -40,7 +18,6 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
void uwsgi_403(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
}
-6
View File
@@ -1231,8 +1231,6 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
return syscall(283, __clock_id, __flags);
#elif defined(__i386__)
return syscall(322, __clock_id, __flags);
#elif defined(__arm__)
return syscall(350, __clock_id, __flags);
#else
return -1;
#endif
@@ -1243,10 +1241,6 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
return syscall(286, __ufd, __flags, __utmr, __otmr);
#elif defined(__i386__)
return syscall(325, __ufd, __flags, __utmr, __otmr);
#elif defined(__arm__)
return syscall(353, __ufd, __flags, __utmr, __otmr);
#else
return -1;
#endif
}
#endif
+11 -25
View File
@@ -24,29 +24,16 @@ static char *uwsgi_fifo_by_slot() {
return uwsgi.master_fifo->value;
}
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
static void subscriptions_blocker() {
if (uwsgi.subscriptions_blocked) {
uwsgi_log_verbose("subscriptions re-enabled\n");
uwsgi.subscriptions_blocked = 0;
}
else {
uwsgi.subscriptions_blocked = 1;
uwsgi_log_verbose("subscriptions blocked\n");
}
}
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
/*
@@ -84,7 +71,6 @@ void uwsgi_master_fifo_prepare() {
uwsgi_fifo_table['r'] = grace_them_all;
uwsgi_fifo_table['R'] = reap_them_all;
uwsgi_fifo_table['s'] = stats;
uwsgi_fifo_table['S'] = subscriptions_blocker;
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
@@ -113,7 +99,7 @@ int uwsgi_master_fifo() {
}
int uwsgi_master_fifo_manage(int fd) {
unsigned char cmd;
char cmd;
ssize_t rlen = read(fd, &cmd, 1);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
-1
View File
@@ -38,7 +38,6 @@ void uwsgi_fsmon_setup() {
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
free(copy);
goto next;
}
*space = 0;
-18
View File
@@ -29,8 +29,6 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
ug->num = num;
ug->fullname = fullname;
ug->data = data;
ug->uid = 0;
ug->gid = 0;
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
@@ -92,22 +90,6 @@ void gateway_respawn(int id) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
if (ug->gid) {
uwsgi_log("%s %d setgid() to %d\n", ug->name, ug->num, (int) ug->gid);
if (setgid(ug->gid)) {
uwsgi_error("gateway_respawn()/setgid()");
exit(1);
}
}
if (ug->uid) {
uwsgi_log("%s %d setuid() to %d\n", ug->name, ug->num, (int) ug->uid);
if (setuid(ug->uid)) {
uwsgi_error("gateway_respawn()/setuid()");
exit(1);
}
}
ug->loop(id, ug->data);
// never here !!! (i hope)
exit(1);
+1 -21
View File
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
// Murmur2 hash Copyright (C) Austin Appleby
// adapted from nginx
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t h, k;
uint8_t *ukey = (uint8_t *) key;
@@ -56,23 +56,6 @@ static uint32_t murmur2_hash(char *key, uint64_t keylen) {
return h;
}
static uint32_t random_hash(char *key, uint64_t keylen) {
return (uint32_t) rand();
}
/*
not atomic, avoid its use in multithreaded modes
*/
static uint32_t rr_hash(char *key, uint64_t keylen) {
static uint32_t rr = 0;
uint32_t max_value = uwsgi_str_num(key, keylen);
uint32_t ret = rr;
rr++;
if (rr > max_value) {
rr = 0;
}
return ret;
}
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
@@ -107,7 +90,4 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
void uwsgi_hash_algo_register_all() {
uwsgi_hash_algo_register("djb33x", djb33x_hash);
uwsgi_hash_algo_register("murmur2", murmur2_hash);
uwsgi_hash_algo_register("random", random_hash);
uwsgi_hash_algo_register("rand", random_hash);
uwsgi_hash_algo_register("rr", rr_hash);
}
+3 -305
View File
@@ -55,22 +55,6 @@ static int uwsgi_hook_chdir(char *arg) {
return ret;
}
static int uwsgi_hook_mkdir(char *arg) {
int ret = mkdir(arg, 0777);
if (ret) {
uwsgi_error("uwsgi_hook_mkdir()");
}
return ret;
}
static int uwsgi_hook_putenv(char *arg) {
int ret = putenv(arg);
if (ret) {
uwsgi_error("uwsgi_hook_putenv()");
}
return ret;
}
static int uwsgi_hook_exec(char *arg) {
int ret = uwsgi_run_command_and_wait(NULL, arg);
if (ret != 0) {
@@ -94,263 +78,6 @@ static int uwsgi_hook_print(char *arg) {
return 0;
}
static int uwsgi_hook_unlink(char *arg) {
int ret = unlink(arg);
if (ret) {
uwsgi_error("uwsgi_hook_unlink()/unlink()");
}
return ret;
}
static int uwsgi_hook_writefifo(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
if (errno == ENODEV) return 0;
#ifdef ENXIO
if (errno == ENXIO) return 0;
#endif
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_writefifo()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_write(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_write()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_append(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook append syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
if (write(fd, space+1, l) != (ssize_t) l) {
uwsgi_error("uwsgi_hook_append()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
static int uwsgi_hook_writen(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook writen syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
char *buf = uwsgi_malloc(l + 1);
memcpy(buf, space+1, l);
buf[l] = '\n';
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
uwsgi_error("uwsgi_hook_writen()/write()");
free(buf);
close(fd);
return -1;
}
free(buf);
close(fd);
return 0;
}
static int uwsgi_hook_appendn(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
return -1;
}
*space = ' ';
size_t l = strlen(space+1);
char *buf = uwsgi_malloc(l + 1);
memcpy(buf, space+1, l);
buf[l] = '\n';
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
uwsgi_error("uwsgi_hook_appendn()/write()");
free(buf);
close(fd);
return -1;
}
free(buf);
close(fd);
return 0;
}
static int uwsgi_hook_chmod(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chmod syntax, must be: <file> <mode>\n");
return -1;
}
*space = 0;
int error = 0;
mode_t mask = uwsgi_mode_t(space+1, &error);
if (error) {
uwsgi_log("invalid hook chmod mask: %s\n", space+1);
*space = ' ';
return -1;
}
int ret = chmod(arg, mask);
*space = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chmod()/chmod()");
}
return ret;
}
static int uwsgi_hook_chown(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space = 0;
char *space2 = strchr(space+1, ' ');
if (!space2) {
*space = ' ';
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space2 = 0;
struct passwd *pw = getpwnam(space+1);
if (!pw) {
uwsgi_log("unable to find uid %s\n", space+1);
*space = ' ';
*space2 = ' ';
return -1;
}
struct group *gr = getgrnam(space2+1);
if (!gr) {
uwsgi_log("unable to find gid %s\n", space2+1);
*space = ' ';
*space2 = ' ';
return -1;
}
int ret = chown(arg, pw->pw_uid, gr->gr_gid);
*space = ' ';
*space2 = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chown()/chown)");
}
return ret;
}
static int uwsgi_hook_chown2(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space = 0;
char *space2 = strchr(space+1, ' ');
if (!space2) {
*space = ' ';
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
return -1;
}
*space2 = 0;
if (!is_a_number(space+1)) {
uwsgi_log("invalid hook chown2 syntax, uid must be a number\n");
*space = ' ';
*space2 = ' ';
return -1;
}
if (!is_a_number(space2+1)) {
uwsgi_log("invalid hook chown2 syntax, gid must be a number\n");
*space = ' ';
*space2 = ' ';
return -1;
}
int ret = chown(arg, atoi(space+1), atoi(space2+1));
*space = ' ';
*space2 = ' ';
if (ret) {
uwsgi_error("uwsgi_hook_chown2()/chown)");
}
return ret;
}
static int uwsgi_hook_hostname(char *arg) {
#ifdef __CYGWIN__
return -1;
#else
return sethostname(arg, strlen(arg));
#endif
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
@@ -448,23 +175,8 @@ static int uwsgi_hook_callret(char *arg) {
void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("chdir", uwsgi_hook_chdir);
uwsgi_register_hook("mkdir", uwsgi_hook_mkdir);
uwsgi_register_hook("putenv", uwsgi_hook_putenv);
uwsgi_register_hook("chmod", uwsgi_hook_chmod);
uwsgi_register_hook("chown", uwsgi_hook_chown);
uwsgi_register_hook("chown2", uwsgi_hook_chown2);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("write", uwsgi_hook_write);
uwsgi_register_hook("writen", uwsgi_hook_writen);
uwsgi_register_hook("append", uwsgi_hook_append);
uwsgi_register_hook("appendn", uwsgi_hook_appendn);
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
uwsgi_register_hook("mount", uwsgi_mount_hook);
uwsgi_register_hook("umount", uwsgi_umount_hook);
@@ -474,8 +186,6 @@ void uwsgi_register_base_hooks() {
uwsgi_register_hook("callint", uwsgi_hook_callint);
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
uwsgi_register_hook("hostname", uwsgi_hook_hostname);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
@@ -490,26 +200,14 @@ void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
exit(1);
}
*colon = 0;
int private = 0;
char *action = usl->value;
// private hook ?
if (action[0] == '!') {
action++;
private = 1;
}
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
if (!uh) {
uwsgi_log("hook action not found: %s\n", action);
uwsgi_log("hook not found: %s\n", usl->value);
exit(1);
}
*colon = ':';
if (private) {
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
}
else {
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
}
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
int ret = uh->func(colon+1);
if (fatal && ret != 0) {
+14 -11
View File
@@ -51,7 +51,6 @@ struct http_status_codes hsc[] = {
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{"509", "Bandwidth Limit Exceeded"},
{"", NULL},
};
@@ -117,11 +116,11 @@ void uwsgi_init_default() {
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.socket_timeout = 4;
uwsgi.logging_options.enabled = 1;
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
// a workers hould be running for at least 10 seconds
uwsgi.min_worker_lifetime = 10;
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
uwsgi.shared->spooler_frequency = 30;
@@ -170,8 +169,6 @@ void uwsgi_init_default() {
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
uwsgi_websockets_init();
@@ -196,7 +193,7 @@ void uwsgi_setup_reload() {
uwsgi.reloads++;
//convert reloads to string
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0 && rlen < 10) {
if (rlen > 0) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
@@ -348,6 +345,7 @@ void uwsgi_setup_workers() {
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
@@ -413,7 +411,7 @@ void sanitize_args() {
uwsgi.cores = uwsgi.threads;
}
if (uwsgi.harakiri_options.workers > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
if (!uwsgi.post_buffering) {
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
}
@@ -449,13 +447,18 @@ void sanitize_args() {
}
}
if (uwsgi.max_worker_lifetime > 0 && uwsgi.min_worker_lifetime >= uwsgi.max_worker_lifetime) {
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
exit(1);
}
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
uwsgi.min_worker_lifetime, uwsgi.max_worker_lifetime);
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
exit(1);
}
if (uwsgi.cheaper_rss_limit_soft && uwsgi.logging_options.memory_report != 1 && uwsgi.force_get_memusage != 1) {
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
exit(1);
}
+10 -223
View File
@@ -15,7 +15,7 @@ int uwsgi_waitfd_event(int fd, int timeout, int event) {
struct pollfd upoll;
if (!timeout)
timeout = uwsgi.socket_timeout;
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
timeout = timeout * 1000;
if (timeout < 0)
@@ -270,7 +270,7 @@ static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
exit(1);
}
ptr+=rlen;
@@ -293,7 +293,7 @@ static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
exit(1);
}
ptr+=rlen;
@@ -364,7 +364,6 @@ static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
}
}
}
close(fd);
return buffer;
}
@@ -586,13 +585,11 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
len = recvmsg(fd, &msg, 0);
if (len <= 0) {
uwsgi_error("recvmsg()");
free(msg_control);
return NULL;
}
if (code && code_len > 0) {
if (uwsgi_strncmp(id, code_len, code, code_len)) {
free(msg_control);
return NULL;
}
@@ -608,19 +605,15 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
}
cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) {
free(msg_control);
if (!cmsg)
return NULL;
}
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
free(msg_control);
return NULL;
}
if ((size_t) (cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) > (size_t) (sizeof(int) * (count + 1))) {
uwsgi_log("not enough space for sockets data, consider increasing it\n");
free(msg_control);
return NULL;
}
@@ -762,12 +755,11 @@ int uwsgi_write_true_nb(int fd, char *buf, size_t remains, int timeout) {
int ret;
while(remains > 0) {
errno = 0;
ssize_t len = write(fd, ptr, remains);
if (len > 0) goto written;
if (len == 0) return -1;
if (len < 0) {
if (uwsgi_is_again()) goto wait;
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
return -1;
}
wait:
@@ -918,7 +910,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
}
if (rlen == 0) return -1;
if (rlen < 0) {
if (uwsgi_is_again()) goto wait;
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
}
return -1;
wait:
@@ -950,12 +942,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
}
/*
this is a pretty magic function used for reading a full uwsgi response
this is a pretty magic function used for read a full uwsgi response
it is true non blocking, so you can use it in request plugins
buffer is expected to be at least 4 bytes, rlen is a get/set value
*/
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
if (*rlen < 4) return -1;
char *buf = *buffer;
int ret;
@@ -968,7 +960,7 @@ int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, ui
if (len > 0) goto readok;
if (len == 0) return -1;
if (len < 0) {
if (uwsgi_is_again()) goto wait;
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
return -1;
}
wait:
@@ -986,10 +978,6 @@ readok:
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
uint16_t pktsize = uh->pktsize;
if (modifier1)
*modifier1 = uh->modifier1;
if (modifier2)
*modifier2 = uh->modifier2;
if (pktsize > *rlen) {
char *tmp_buf = realloc(buf, pktsize);
@@ -1010,7 +998,7 @@ readok:
if (len > 0) goto readok2;
if (len == 0) return -1;
if (len < 0) {
if (uwsgi_is_again()) goto wait2;
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
return -1;
}
wait2:
@@ -1222,204 +1210,3 @@ void uwsgi_remap_fd(int fd, char *filename) {
}
}
int uwsgi_is_connected(int fd) {
int soopt;
socklen_t solen = sizeof(int);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
return 0;
}
/* is something bad ? */
if (soopt) return 0;
return 1;
}
int uwsgi_pass_cred(int fd, char *code, size_t code_len) {
#ifdef SCM_CREDENTIALS
struct msghdr cr_msg;
struct cmsghdr *cmsg;
struct iovec cr_iov;
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
cr_iov.iov_base = code;
cr_iov.iov_len = code_len;
cr_msg.msg_name = NULL;
cr_msg.msg_namelen = 0;
cr_msg.msg_iov = &cr_iov;
cr_msg.msg_iovlen = 1;
cr_msg.msg_flags = 0;
cr_msg.msg_control = cr_msg_control;
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
cmsg = CMSG_FIRSTHDR(&cr_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
u->pid = getpid();
u->uid = getuid();
u->gid = getgid();
if (sendmsg(fd, &cr_msg, 0) < 0) {
uwsgi_error("uwsgi_pass_cred()/sendmsg()");
free(cr_msg_control);
return -1;
}
free(cr_msg_control);
return 0;
#else
return -1;
#endif
}
int uwsgi_pass_cred2(int fd, char *code, size_t code_len, struct sockaddr *addr, size_t addr_len) {
#ifdef SCM_CREDENTIALS
struct msghdr cr_msg;
struct cmsghdr *cmsg;
struct iovec cr_iov;
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
cr_iov.iov_base = code;
cr_iov.iov_len = code_len;
cr_msg.msg_name = addr;
cr_msg.msg_namelen = addr_len;
cr_msg.msg_iov = &cr_iov;
cr_msg.msg_iovlen = 1;
cr_msg.msg_flags = 0;
cr_msg.msg_control = cr_msg_control;
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
cmsg = CMSG_FIRSTHDR(&cr_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
u->pid = getpid();
u->uid = getuid();
u->gid = getgid();
if (sendmsg(fd, &cr_msg, 0) < 0) {
uwsgi_error("uwsgi_pass_cred2()/sendmsg()");
free(cr_msg_control);
return -1;
}
free(cr_msg_control);
return 0;
#else
return -1;
#endif
}
int uwsgi_recv_cred(int fd, char *code, size_t code_len, pid_t *pid, uid_t *uid, gid_t *gid) {
#ifdef SCM_CREDENTIALS
struct iovec iov;
int ret = -1;
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
iov.iov_base = uwsgi_malloc(code_len);
iov.iov_len = code_len;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = msg_control;
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
ssize_t len = recvmsg(fd, &msg, 0);
if (len <= 0) {
uwsgi_error("uwsgi_recv_cred()/recvmsg()");
goto clear;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) goto clear;
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
goto clear;
}
if (uwsgi_strncmp(code, code_len, iov.iov_base, iov.iov_len)) goto clear;
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
*pid = u->pid;
*uid = u->uid;
*gid = u->gid;
ret = 0;
clear:
free(msg_control);
free(iov.iov_base);
return ret;
#else
return -1;
#endif
}
ssize_t uwsgi_recv_cred2(int fd, char *buf, size_t buf_len, pid_t *pid, uid_t *uid, gid_t *gid) {
#ifdef SCM_CREDENTIALS
struct iovec iov;
ssize_t ret = -1;
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
iov.iov_base = buf;
iov.iov_len = buf_len;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = msg_control;
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
ssize_t len = recvmsg(fd, &msg, 0);
if (len <= 0) {
uwsgi_error("uwsgi_recv_cred2()/recvmsg()");
goto clear;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) goto clear;
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
goto clear;
}
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
*pid = u->pid;
*uid = u->uid;
*gid = u->gid;
ret = len;
clear:
free(msg_control);
return ret;
#else
return -1;
#endif
}
+4 -82
View File
@@ -4,90 +4,13 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_JSON_YAJL
#include <yajl/yajl_tree.h>
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
char *object_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon + 1;
}
}
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
char errbuf[1024];
yajl_val node = yajl_tree_parse((const char *)json_data, errbuf, sizeof(errbuf));
if (!node) {
uwsgi_log("error parsing JSON data: %s\n", errbuf);
exit(1);
}
const char * path[] = { object_asked, NULL };
yajl_val v = yajl_tree_get(node, path, yajl_t_any);
if (!YAJL_IS_OBJECT(v)) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
size_t i;
for(i=0;i<v->u.object.len;i++) {
char *key = (char *) v->u.object.keys[i];
yajl_val o = v->u.object.values[i];
if (YAJL_IS_STRING(o)) {
add_exported_option(key, YAJL_GET_STRING(o) , 0);
}
else if (YAJL_IS_TRUE(o)) {
add_exported_option(key, strdup("1"), 0);
}
else if (YAJL_IS_FALSE(o) || YAJL_IS_NULL(o)) {
add_exported_option(key, strdup("0"), 0);
}
else if (YAJL_IS_NUMBER(o) || YAJL_IS_INTEGER(o)) {
add_exported_option(key, YAJL_GET_NUMBER(o), 0);
}
else if (YAJL_IS_ARRAY(o)) {
size_t j;
for(j=0;j<o->u.array.len;j++) {
yajl_val a_o = o->u.array.values[j];
if (YAJL_IS_STRING(a_o)) {
add_exported_option(key, YAJL_GET_STRING(a_o) , 0);
}
else if (YAJL_IS_TRUE(a_o)) {
add_exported_option(key, strdup("1"), 0);
}
else if (YAJL_IS_FALSE(a_o) || YAJL_IS_NULL(a_o)) {
add_exported_option(key, strdup("0"), 0);
}
else if (YAJL_IS_NUMBER(a_o) || YAJL_IS_INTEGER(a_o)) {
add_exported_option(key, YAJL_GET_NUMBER(a_o), 0);
}
}
}
}
}
#else
#include <jansson.h>
/*
I really love the jansson library...
*/
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
@@ -188,4 +111,3 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
}
#endif
#endif
-1
View File
@@ -647,7 +647,6 @@ void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
sleep(1);
}
return NULL;
}
+225 -195
View File
@@ -119,36 +119,6 @@ void uwsgi_log_verbose(const char *fmt, ...) {
}
/*
commodity function mainly useful in log rotation
*/
void uwsgi_logfile_write(const char *fmt, ...) {
va_list ap;
char logpkt[4096];
struct timeval tv;
char ctime_storage[26];
gettimeofday(&tv, NULL);
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
#endif
memcpy(logpkt, ctime_storage, 24);
memcpy(logpkt + 24, " - ", 3);
int rlen = 24 + 3;
va_start(ap, fmt);
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
va_end(ap);
// do not check for errors
rlen = write(uwsgi.original_log_fd, logpkt, rlen);
}
static void fix_logpipe_buf(int *fd) {
int so_bufsize;
@@ -241,6 +211,49 @@ void create_logpipe(void) {
}
#ifdef UWSGI_ZEROMQ
// the zeromq logger
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!ul->configured) {
if (!ul->arg) {
uwsgi_log_safe("invalid zeromq syntax\n");
exit(1);
}
void *ctx = uwsgi_zeromq_init();
ul->data = zmq_socket(ctx, ZMQ_PUSH);
if (ul->data == NULL) {
uwsgi_error_safe("zmq_socket()");
exit(1);
}
if (zmq_connect(ul->data, ul->arg) < 0) {
uwsgi_error_safe("zmq_connect()");
exit(1);
}
ul->configured = 1;
}
zmq_msg_t msg;
if (zmq_msg_init_size(&msg, len) == 0) {
memcpy(zmq_msg_data(&msg), message, len);
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
zmq_sendmsg(ul->data, &msg, 0);
#else
zmq_send(ul->data, &msg, 0);
#endif
zmq_msg_close(&msg);
}
return 0;
}
#endif
// log to the specified file or udp address
void logto(char *logfile) {
@@ -485,7 +498,7 @@ void uwsgi_check_logrotate(void) {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
}
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
need_rotation = 1;
}
@@ -506,6 +519,7 @@ void uwsgi_check_logrotate(void) {
}
void uwsgi_log_rotate() {
char message[1024];
if (!uwsgi.logfile) return;
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
@@ -515,21 +529,24 @@ void uwsgi_log_rotate() {
free(ts_str);
need_free = 1;
}
// this will be rawly written to the logfile
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) uwsgi.shared->logsize, rot_name);
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile and dup'it, on dup2 error, exit(1)
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
// this will be written to the original file
uwsgi_error_open(uwsgi.logfile);
exit(1);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
// this could be lost :(
uwsgi_error("uwsgi_log_rotate()/dup2()");
exit(1);
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
@@ -545,7 +562,7 @@ void uwsgi_log_reopen() {
char message[1024];
if (!uwsgi.logfile) return;
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0 && ret < 1024) {
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
@@ -558,10 +575,9 @@ void uwsgi_log_reopen() {
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
return;
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0 && ret < 1024) {
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
@@ -573,7 +589,7 @@ void uwsgi_log_reopen() {
void log_request(struct wsgi_request *wsgi_req) {
int log_it = uwsgi.logging_options.enabled;
int log_it = uwsgi.shared->options[UWSGI_OPTION_LOGGING];
if (wsgi_req->do_not_log)
return;
@@ -583,25 +599,22 @@ void log_request(struct wsgi_request *wsgi_req) {
}
/* conditional logging */
if (uwsgi.logging_options.zero && wsgi_req->response_size == 0) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_ZERO] && wsgi_req->response_size == 0) {
goto logit;
}
if (uwsgi.logging_options.slow && (uint32_t) wsgi_req_time >= uwsgi.logging_options.slow) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW] && (uint32_t) wsgi_req_time >= uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW]) {
goto logit;
}
if (uwsgi.logging_options._4xx && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_4xx] && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
goto logit;
}
if (uwsgi.logging_options._5xx && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_5xx] && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
goto logit;
}
if (uwsgi.logging_options.big && (wsgi_req->response_size >= uwsgi.logging_options.big)) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG] && (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG])) {
goto logit;
}
if (uwsgi.logging_options.sendfile && wsgi_req->via == UWSGI_VIA_SENDFILE) {
goto logit;
}
if (uwsgi.logging_options.ioerror && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
goto logit;
}
@@ -686,7 +699,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
logvecpos++;
}
if (uwsgi.logging_options.memory_report == 1) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
logvec[logvecpos].iov_base = mempkt;
@@ -967,20 +980,6 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
}
}
// var
else if (logchunk->type == 5) {
uint16_t value_len = 0;
char *value = uwsgi_get_var(wsgi_req, logchunk->ptr, logchunk->len, &value_len);
// could be NULL
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = value;
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = (size_t) value_len;
}
// metric
else if (logchunk->type == 4) {
int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
}
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
@@ -1006,6 +1005,10 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
}
}
void uwsgi_logit_lf_strftime(struct wsgi_request *wsgi_req) {
uwsgi_log("lf strftime\n");
}
void uwsgi_build_log_format(char *format) {
int state = 0;
char *ptr = format;
@@ -1129,16 +1132,6 @@ static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
return ret;
}
static ssize_t uwsgi_lf_tmsecs(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_64bit2str(wsgi_req->start_of_request / (int64_t) 1000);
return strlen(*buf);
}
static ssize_t uwsgi_lf_tmicros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_64bit2str(wsgi_req->start_of_request);
return strlen(*buf);
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
return strlen(*buf);
@@ -1214,54 +1207,6 @@ static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
return strlen(*buf);
}
static ssize_t uwsgi_lf_werr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) wsgi_req->write_errors);
return strlen(*buf);
}
static ssize_t uwsgi_lf_rerr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) wsgi_req->read_errors);
return strlen(*buf);
}
static ssize_t uwsgi_lf_ioerr(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((int) (wsgi_req->write_errors + wsgi_req->read_errors));
return strlen(*buf);
}
struct uwsgi_logchunk *uwsgi_register_logchunk(char *name, ssize_t (*func)(struct wsgi_request *, char **), int need_free) {
struct uwsgi_logchunk *old_logchunk = NULL, *logchunk = uwsgi.registered_logchunks;
while(logchunk) {
if (!strcmp(logchunk->name, name)) goto found;
old_logchunk = logchunk;
logchunk = logchunk->next;
}
logchunk = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
logchunk->name = name;
if (old_logchunk) {
old_logchunk->next = logchunk;
}
else {
uwsgi.registered_logchunks = logchunk;
}
found:
logchunk->func = func;
logchunk->free = need_free;
logchunk->type = 3;
return logchunk;
}
struct uwsgi_logchunk *uwsgi_get_logchunk_by_name(char *name, size_t name_len) {
struct uwsgi_logchunk *logchunk = uwsgi.registered_logchunks;
while(logchunk) {
if (!uwsgi_strncmp(name, name_len, logchunk->name, strlen(logchunk->name))) {
return logchunk;
}
logchunk = logchunk->next;
}
return NULL;
}
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
@@ -1282,12 +1227,10 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
}
/*
0 -> raw text
0 -> raw test
1 -> offsetof variable
2 -> logvar
3 -> func
4 -> metric
5 -> request variable
*/
logchunk->type = variable;
@@ -1297,29 +1240,161 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->len = len;
// variable
if (variable) {
struct uwsgi_logchunk *rlc = uwsgi_get_logchunk_by_name(ptr, len);
if (rlc) {
if (rlc->type == 1) {
logchunk->pos = rlc->pos;
logchunk->pos_len = rlc->pos_len;
}
else if (rlc->type == 3) {
logchunk->type = 3;
logchunk->func = rlc->func;
logchunk->free = rlc->free;
}
if (!uwsgi_strncmp(ptr, len, "uri", 3)) {
logchunk->pos = offsetof(struct wsgi_request, uri);
logchunk->pos_len = offsetof(struct wsgi_request, uri_len);
}
// var
else if (!uwsgi_starts_with(ptr, len, "var.", 4)) {
logchunk->type = 5;
logchunk->ptr = ptr+4;
logchunk->len = len-4;
logchunk->free = 0;
else if (!uwsgi_strncmp(ptr, len, "method", 6)) {
logchunk->pos = offsetof(struct wsgi_request, method);
logchunk->pos_len = offsetof(struct wsgi_request, method_len);
}
// metric
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
logchunk->type = 4;
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
else if (!uwsgi_strncmp(ptr, len, "user", 4)) {
logchunk->pos = offsetof(struct wsgi_request, remote_user);
logchunk->pos_len = offsetof(struct wsgi_request, remote_user_len);
}
else if (!uwsgi_strncmp(ptr, len, "addr", 4)) {
logchunk->pos = offsetof(struct wsgi_request, remote_addr);
logchunk->pos_len = offsetof(struct wsgi_request, remote_addr_len);
}
else if (!uwsgi_strncmp(ptr, len, "host", 4)) {
logchunk->pos = offsetof(struct wsgi_request, host);
logchunk->pos_len = offsetof(struct wsgi_request, host_len);
}
else if (!uwsgi_strncmp(ptr, len, "proto", 5)) {
logchunk->pos = offsetof(struct wsgi_request, protocol);
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
}
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
logchunk->pos = offsetof(struct wsgi_request, user_agent);
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
}
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
logchunk->pos = offsetof(struct wsgi_request, referer);
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
}
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_status;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_hsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_size;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_cl;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_micros;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "msecs", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_msecs;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "time", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_time;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ftime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "epoch", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_epoch;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "wid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_wid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "switches", 8)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_switches;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vars", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vars;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "core", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_core;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vsz", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vsz;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rss", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rss;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vszM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vszM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rssM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rssM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pktsize", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pktsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier1", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier1;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier2", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier2;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "headers", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_headers;
logchunk->free = 1;
}
// logvar
@@ -1766,7 +1841,7 @@ void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
/*
// format: foo ${var} bar
msg (the logline)
msgnl (the logline with newline)
msgnl (the logine with newline)
unix (the time_t value)
micros (current microseconds)
strftime (strftime)
@@ -1892,51 +1967,6 @@ end:
return buf;
}
#define r_logchunk(x) uwsgi_register_logchunk(#x, uwsgi_lf_ ## x, 1)
#define r_logchunk_offset(x, y) { struct uwsgi_logchunk *lc = uwsgi_register_logchunk(#x, NULL, 0); lc->pos = offsetof(struct wsgi_request, y); lc->pos_len = offsetof(struct wsgi_request, y ## _len); lc->type = 1; lc->free=0;}
void uwsgi_register_logchunks() {
// offsets
r_logchunk_offset(uri, uri);
r_logchunk_offset(method, method);
r_logchunk_offset(user, remote_user);
r_logchunk_offset(addr, remote_addr);
r_logchunk_offset(host, host);
r_logchunk_offset(proto, protocol);
r_logchunk_offset(uagent, user_agent);
r_logchunk_offset(referer, referer);
// funcs
r_logchunk(status);
r_logchunk(rsize);
r_logchunk(hsize);
r_logchunk(size);
r_logchunk(cl);
r_logchunk(micros);
r_logchunk(msecs);
r_logchunk(tmsecs);
r_logchunk(tmicros);
r_logchunk(time);
r_logchunk(ltime);
r_logchunk(ftime);
r_logchunk(ctime);
r_logchunk(epoch);
r_logchunk(pid);
r_logchunk(wid);
r_logchunk(switches);
r_logchunk(vars);
r_logchunk(core);
r_logchunk(vsz);
r_logchunk(rss);
r_logchunk(vszM);
r_logchunk(rssM);
r_logchunk(pktsize);
r_logchunk(modifier1);
r_logchunk(modifier2);
r_logchunk(headers);
r_logchunk(werr);
r_logchunk(rerr);
r_logchunk(ioerr);
}
void uwsgi_log_encoders_register_embedded() {
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
+138 -178
View File
@@ -2,29 +2,14 @@
extern struct uwsgi_server uwsgi;
void uwsgi_update_load_counters() {
void uwsgi_restore_auto_snapshot(int signum) {
int i;
uint64_t busy_workers = 0;
uint64_t idle_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi_worker_is_busy(i) == 0) {
idle_workers++;
}
else {
busy_workers++;
}
}
}
if (busy_workers >= (uint64_t) uwsgi.numproc) {
ushared->overloaded++;
if (uwsgi.workers[1].snapshot > 0) {
uwsgi.restore_snapshot = 1;
}
else {
uwsgi_log("[WARNING] no snapshot available\n");
}
ushared->busy_workers = busy_workers;
ushared->idle_workers = idle_workers;
}
@@ -47,25 +32,24 @@ void uwsgi_unblock_signal(int signum) {
}
void uwsgi_master_manage_udp(int udp_fd) {
char buf[4096];
struct sockaddr_in udp_client;
char udp_client_addr[16];
int i;
socklen_t udp_len = sizeof(udp_client);
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
uwsgi_error("recvfrom()");
}
else if (rlen > 0) {
memset(udp_client_addr, 0, 16);
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
}
else if (buf[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
}
else {
@@ -73,7 +57,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
int udp_managed = 0;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->manage_udp) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
udp_managed = 1;
break;
}
@@ -82,17 +66,42 @@ void uwsgi_master_manage_udp(int udp_fd) {
// else a simple udp logger
if (!udp_managed) {
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
}
}
}
else {
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
uwsgi_error("inet_ntop()");
}
}
}
void uwsgi_master_restore_snapshot() {
int i, waitpid_status;
uwsgi_log("[snapshot] restoring workers...\n");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].snapshot = 0;
}
else {
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGURG);
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
}
}
uwsgi.restore_snapshot = 0;
}
void suspend_resume_them_all(int signum) {
int i;
@@ -168,34 +177,53 @@ void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
}
}
static void get_tcp_info(struct uwsgi_socket *uwsgi_sock) {
int uwsgi_get_tcp_info(int fd) {
#if defined(__linux__) || defined(__FreeBSD__)
int fd = uwsgi_sock->fd;
struct tcp_info ti;
socklen_t tis = sizeof(struct tcp_info);
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &ti, &tis)) {
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &uwsgi.shared->ti, &tis)) {
// checks for older kernels
#if defined(__linux__)
if (!ti.tcpi_sacked) {
if (!uwsgi.shared->ti.tcpi_sacked) {
#elif defined(__FreeBSD__)
if (!ti.__tcpi_sacked) {
if (!uwsgi.shared->ti.__tcpi_sacked) {
#endif
return;
return 0;
}
#if defined(__linux__)
uwsgi_sock->queue = (uint64_t) ti.tcpi_unacked;
uwsgi_sock->max_queue = (uint64_t) ti.tcpi_sacked;
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.tcpi_sacked;
#elif defined(__FreeBSD__)
uwsgi_sock->queue = (uint64_t) ti.__tcpi_unacked;
uwsgi_sock->max_queue = (uint64_t) ti.__tcpi_sacked;
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.__tcpi_unacked;
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.__tcpi_sacked;
#endif
}
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->load;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if (uwsgi.shared->load >= (uint64_t) uwsgi.vassal_sos_backlog) {
// ask emperor for help
char byte = 30;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
}
else {
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
}
}
}
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return uwsgi.shared->load;
}
#endif
return 0;
}
@@ -208,61 +236,25 @@ static void get_tcp_info(struct uwsgi_socket *uwsgi_sock) {
#ifdef SIOBKLGQ
static void get_linux_unbit_SIOBKLGQ(struct uwsgi_socket *uwsgi_sock) {
int get_linux_unbit_SIOBKLGQ(int fd) {
int fd = uwsgi_sock->fd;
int queue = 0;
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
uwsgi_sock->queue = (uint64_t) queue;
uwsgi_sock->max_queue = (uint64_t) uwsgi.listen_queue;
uwsgi.shared->load = queue;
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = queue;
if (queue >= uwsgi.listen_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
return queue;
}
return 0;
}
#endif
#endif
static void master_check_listen_queue() {
uint64_t backlog = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
get_tcp_info(uwsgi_sock);
}
#ifdef __linux__
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
get_linux_unbit_SIOBKLGQ(uwsgi_sock);
}
#endif
#endif
if (uwsgi_sock->queue > backlog) {
backlog = uwsgi_sock->queue;
}
if (uwsgi_sock->queue > 0 && uwsgi_sock->queue >= uwsgi_sock->max_queue) {
uwsgi_log_verbose("*** uWSGI listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu) ***\n", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
}
uwsgi_sock = uwsgi_sock->next;
}
// TODO load should be something more advanced based on different values
uwsgi.shared->load = backlog;
uwsgi.shared->backlog = backlog;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if (uwsgi.shared->backlog >= (uint64_t) uwsgi.vassal_sos_backlog) {
// ask emperor for help
char byte = 30;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
}
else {
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
}
}
}
}
int master_loop(char **argv, char **environ) {
@@ -307,6 +299,9 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
atexit(uwsgi_master_cleanup_hooks);
@@ -351,7 +346,6 @@ int master_loop(char **argv, char **environ) {
#ifdef UWSGI_SSL
uwsgi_start_legions();
#endif
uwsgi_metrics_start_collector();
uwsgi_add_reload_fds();
@@ -375,18 +369,6 @@ int master_loop(char **argv, char **environ) {
}
}
#ifdef __linux__
if (uwsgi.setns_socket) {
uwsgi.setns_socket_fd = bind_to_unix(uwsgi.setns_socket, uwsgi.listen_queue, 0, 0);
if (uwsgi.setns_socket_fd < 0) exit(1);
if (chmod(uwsgi.setns_socket, S_IRUSR|S_IWUSR)) {
uwsgi_error("[setns-socket] chmod()");
exit(1);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.setns_socket_fd);
}
#endif
if (uwsgi.zerg_server) {
uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0);
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
@@ -500,40 +482,10 @@ int master_loop(char **argv, char **environ) {
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
// daemon touches
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->touch) {
uwsgi_check_touches(ud->touch);
}
ud = ud->next;
}
// fsmon
uwsgi_fsmon_setup();
uwsgi_foreach(usl, uwsgi.signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
*space = ' ';
}
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
char *space = strchr(usl->value, ' ');
if (!space) {
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
exit(1);
}
*space = 0;
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
*space = ' ';
}
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
@@ -587,6 +539,21 @@ int master_loop(char **argv, char **environ) {
// check for daemons (smart and dumb)
uwsgi_daemons_smart_check();
if (uwsgi.respawn_snapshots) {
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
if (uwsgi_respawn_worker(i))
return 0;
}
uwsgi.respawn_snapshots = 0;
}
if (uwsgi.restore_snapshot) {
uwsgi_master_restore_snapshot();
continue;
}
// cheaper management
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (!uwsgi_calc_cheaper())
@@ -615,11 +582,9 @@ int master_loop(char **argv, char **environ) {
if (diedpid == 0) {
/* all processes ok, doing status scan after N seconds */
check_interval = uwsgi.master_interval;
if (!check_interval) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
check_interval = 1;
uwsgi.master_interval = 1;
}
// add unregistered file monitors
@@ -654,14 +619,14 @@ int master_loop(char **argv, char **environ) {
if (ushared->rb_timers_cnt > 0) {
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
if (min_timeout) {
int delta = min_timeout->value - uwsgi_now();
if (delta <= 0) {
if (min_timeout == NULL) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
}
else {
check_interval = min_timeout->value - uwsgi_now();
if (check_interval <= 0) {
expire_rb_timeouts(rb_timers);
}
// if the timer expires before the check_interval, override it
else if (delta < check_interval) {
check_interval = delta;
check_interval = 0;
}
}
}
@@ -675,9 +640,6 @@ int master_loop(char **argv, char **environ) {
}
}
// update load counter
uwsgi_update_load_counters();
// check uwsgi-cron table
if (ushared->cron_cnt) {
@@ -717,25 +679,41 @@ int master_loop(char **argv, char **environ) {
// check for idle
uwsgi_master_check_idle();
check_interval = uwsgi.master_interval;
if (!check_interval) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!check_interval)
check_interval = 1;
uwsgi.master_interval = 1;
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
int tmp_queue = 0;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
}
#ifdef __linux__
#ifdef SIOBKLGQ
else if (uwsgi_sock->family == AF_UNIX) {
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
}
#endif
#endif
if (uwsgi_sock->queue > tmp_queue) {
tmp_queue = uwsgi_sock->queue;
}
uwsgi_sock = uwsgi_sock->next;
}
// fix queue size on multiple sockets
uwsgi.shared->load = tmp_queue;
// check listen_queue status
master_check_listen_queue();
int someone_killed = 0;
// check if some worker has to die (harakiri, evil checks...)
if (uwsgi_master_check_workers_deadline()) someone_killed++;
if (uwsgi_master_check_gateways_deadline()) someone_killed++;
if (uwsgi_master_check_mules_deadline()) someone_killed++;
if (uwsgi_master_check_spoolers_deadline()) someone_killed++;
if (uwsgi_master_check_crons_deadline()) someone_killed++;
uwsgi_master_check_workers_deadline();
// this could trigger a complete exit...
uwsgi_master_check_gateways_deadline();
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
uwsgi_master_check_mountpoints();
#ifdef __linux__
@@ -799,26 +777,8 @@ int master_loop(char **argv, char **environ) {
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
// daemon touches
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid > 0 && ud->touch) {
touched = uwsgi_check_touches(ud->touch);
if (touched) {
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
if (kill(ud->pid, ud->stop_signal)) {
uwsgi_error("[uwsgi-daemon/touch] kill()");
}
}
}
ud = ud->next;
}
}
// allows the KILL signal to be delivered;
if (someone_killed > 0) sleep(1);
continue;
}
+9 -32
View File
@@ -48,8 +48,6 @@ void uwsgi_master_check_chain() {
}
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
// do not curse a worker until the old one is ready
if (uwsgi.workers[i].accepting == 0) break;
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
uwsgi_curse(i, SIGHUP);
break;
@@ -122,8 +120,6 @@ void uwsgi_master_check_idle() {
}
else {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].rss_size = 0;
uwsgi.workers[i].vsz_size = 0;
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
@@ -133,22 +129,19 @@ void uwsgi_master_check_idle() {
}
int uwsgi_master_check_workers_deadline() {
void uwsgi_master_check_workers_deadline() {
int i;
int ret = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
/* first check for harakiri */
if (uwsgi.workers[i].harakiri > 0) {
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
}
}
/* then user-defined harakiri */
if (uwsgi.workers[i].user_harakiri > 0) {
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
ret = 1;
}
}
// then for evil memory checkers
@@ -157,7 +150,6 @@ int uwsgi_master_check_workers_deadline() {
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].vsz_size = 0;
ret = 1;
}
}
if (uwsgi.evil_reload_on_rss) {
@@ -165,17 +157,15 @@ int uwsgi_master_check_workers_deadline() {
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].rss_size = 0;
ret = 1;
}
}
// check if worker was running longer than allowed lifetime
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.max_worker_lifetime > 0) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0) {
uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn;
if (lifetime > uwsgi.max_worker_lifetime && uwsgi.workers[i].manage_next_request == 1) {
if (lifetime > uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] && uwsgi.workers[i].manage_next_request == 1) {
uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime);
uwsgi.workers[i].manage_next_request = 0;
kill(uwsgi.workers[i].pid, SIGWINCH);
ret = 1;
}
}
@@ -184,32 +174,29 @@ int uwsgi_master_check_workers_deadline() {
}
return ret;
}
int uwsgi_master_check_gateways_deadline() {
void uwsgi_master_check_gateways_deadline() {
int i;
int ret = 0;
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways_harakiri[i] > 0) {
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
if (ushared->gateways[i].pid > 0) {
uwsgi_log("*** HARAKIRI ON GATEWAY %s %d (pid: %d) ***\n", ushared->gateways[i].name, ushared->gateways[i].num, ushared->gateways[i].pid);
kill(ushared->gateways[i].pid, SIGKILL);
ret = 1;
}
ushared->gateways_harakiri[i] = 0;
}
}
}
return ret;
}
int uwsgi_master_check_mules_deadline() {
void uwsgi_master_check_mules_deadline() {
int i;
int ret = 0;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
@@ -217,7 +204,6 @@ int uwsgi_master_check_mules_deadline() {
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].harakiri = 0;
ret = 1;
}
}
// user harakiri
@@ -226,32 +212,26 @@ int uwsgi_master_check_mules_deadline() {
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].user_harakiri = 0;
ret = 1;
}
}
}
return ret;
}
int uwsgi_master_check_spoolers_deadline() {
int ret = 0;
void uwsgi_master_check_spoolers_deadline() {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
ret = 1;
}
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->user_harakiri = 0;
ret = 1;
}
uspool = uspool->next;
}
return ret;
}
@@ -334,18 +314,15 @@ int uwsgi_master_check_cron_death(int diedpid) {
return 0;
}
int uwsgi_master_check_crons_deadline() {
int ret = 0;
void uwsgi_master_check_crons_deadline() {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
kill(-uc->pid, SIGKILL);
ret = 1;
}
uc = uc->next;
}
return ret;
}
void uwsgi_master_check_mountpoints() {
-7
View File
@@ -51,12 +51,6 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
#ifdef __linux__
if (uwsgi.setns_socket && uwsgi.setns_socket_fd > -1 && interesting_fd == uwsgi.setns_socket_fd) {
uwsgi_master_manage_setns(uwsgi.setns_socket_fd);
}
#endif
if (uwsgi_fsmon_event(interesting_fd)) {
return 0;
}
@@ -124,7 +118,6 @@ int uwsgi_master_manage_events(int interesting_fd) {
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
if (usl->custom2 > 8) free(tmp);
return 0;
}
usl = usl->next;
+13 -249
View File
@@ -101,7 +101,7 @@ int uwsgi_calc_cheaper(void) {
int i;
static time_t last_check = 0;
int check_interval = uwsgi.master_interval;
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
if (!last_check)
last_check = uwsgi_now();
@@ -186,8 +186,6 @@ int uwsgi_calc_cheaper(void) {
uwsgi_log("worker %d should die...\n", oldest_worker);
#endif
uwsgi.workers[oldest_worker].cheaped = 1;
uwsgi.workers[oldest_worker].rss_size = 0;
uwsgi.workers[oldest_worker].vsz_size = 0;
uwsgi.workers[oldest_worker].manage_next_request = 0;
uwsgi_curse(oldest_worker, SIGWINCH);
}
@@ -332,7 +330,7 @@ int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->backlog;
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
#else
int backlog = 0;
#endif
@@ -385,14 +383,14 @@ void uwsgi_reload(char **argv) {
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
// call atexit user exec
uwsgi_exec_atexit();
uwsgi_log("binary reloading uWSGI...\n");
}
else {
@@ -586,19 +584,6 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
#ifdef __linux__
for(i=0;i<uwsgi.setns_fds_count;i++) {
close(uwsgi.setns_fds[i]);
}
#endif
// fd alarms
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
close(uafd->fd);
uafd = uafd->next;
}
}
@@ -607,8 +592,6 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
// the workers is not accepting (obviously)
uwsgi.workers[wid].accepting = 0;
// we count the respawns before errors...
uwsgi.workers[wid].respawn_count++;
// ... same for update time
@@ -728,9 +711,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
#ifdef __linux__
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->backlog))
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]))
goto end;
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->backlog_errors))
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]))
goto end;
#endif
@@ -888,70 +871,6 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
if (uwsgi.has_metrics) {
if (uwsgi_stats_key(us, "metrics"))
goto end;
if (uwsgi_stats_object_open(us))
goto end;
uwsgi_rlock(uwsgi.metrics_lock);
struct uwsgi_metric *um = uwsgi.metrics;
while(um) {
int64_t um_val = *um->value;
if (uwsgi_stats_key(us, um->name)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_open(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
if (uwsgi_stats_object_close(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
um = um->next;
if (um) {
if (uwsgi_stats_comma(us)) {
uwsgi_rwunlock(uwsgi.metrics_lock);
goto end;
}
}
}
uwsgi_rwunlock(uwsgi.metrics_lock);
if (uwsgi_stats_object_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
if (uwsgi_stats_key(us, "sockets"))
goto end;
@@ -1007,8 +926,6 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
goto end;
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
goto end;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
@@ -1095,7 +1012,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
goto end;
if (*ua->chdir) {
if (ua->chdir) {
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
goto end;
}
@@ -1148,9 +1065,6 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
goto end;
@@ -1468,7 +1382,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
void trigger_harakiri(int i) {
int j;
uwsgi_log_verbose("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
if (uwsgi.harakiri_verbose) {
#ifdef __linux__
int proc_file;
@@ -1516,12 +1430,15 @@ void trigger_harakiri(int i) {
}
}
uwsgi_dump_worker(i, "HARAKIRI");
kill(uwsgi.workers[i].pid, SIGUSR2);
// allow SIGUSR2 to be delivered
sleep(1);
kill(uwsgi.workers[i].pid, SIGKILL);
if (!uwsgi.workers[i].pending_harakiri)
uwsgi.workers[i].harakiri_count++;
uwsgi.workers[i].pending_harakiri++;
}
// to avoid races
}
@@ -1661,8 +1578,6 @@ void uwsgi_go_cheap() {
uwsgi.status.is_cheap = 1;
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
uwsgi.workers[i].rss_size = 0;
uwsgi.workers[i].vsz_size = 0;
if (uwsgi.workers[i].pid == 0)
continue;
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
@@ -1675,154 +1590,3 @@ void uwsgi_go_cheap() {
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
#ifdef __linux__
void uwsgi_setns_preopen() {
struct dirent *de;
DIR *ns = opendir("/proc/self/ns");
if (!ns) {
uwsgi_error("uwsgi_setns_preopen()/opendir()");
exit(1);
}
while ((de = readdir(ns)) != NULL) {
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
struct uwsgi_string_list *usl = NULL;
int found = 0;
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
if (!strcmp(de->d_name, usl->value)) {
found = 1;
break;
}
}
if (found) continue;
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
uwsgi.setns_fds[uwsgi.setns_fds_count] = open(filename, O_RDONLY);
if (uwsgi.setns_fds[uwsgi.setns_fds_count] < 0) {
uwsgi_error_open(filename);
free(filename);
exit(1);
}
free(filename);
uwsgi.setns_fds_count++;
}
closedir(ns);
}
void uwsgi_master_manage_setns(int fd) {
struct sockaddr_un snsun;
socklen_t snsun_len = sizeof(struct sockaddr_un);
int setns_client = accept(fd, (struct sockaddr *) &snsun, &snsun_len);
if (setns_client < 0) {
uwsgi_error("uwsgi_master_manage_setns()/accept()");
return;
}
int i;
int tmp_fds[64];
int *fds = tmp_fds;
int num_fds = 0;
struct msghdr sn_msg;
void *sn_msg_control;
struct iovec sn_iov[2];
struct cmsghdr *cmsg;
DIR *ns = NULL;
if (uwsgi.setns_fds_count) {
fds = uwsgi.setns_fds;
num_fds = uwsgi.setns_fds_count;
goto send;
}
struct dirent *de;
ns = opendir("/proc/self/ns");
if (!ns) {
close(setns_client);
uwsgi_error("uwsgi_master_manage_setns()/opendir()");
return;
}
while ((de = readdir(ns)) != NULL) {
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
struct uwsgi_string_list *usl = NULL;
int found = 0;
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
if (!strcmp(de->d_name, usl->value)) {
found = 1;
break;
}
}
if (found) continue;
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
fds[num_fds] = open(filename, O_RDONLY);
if (fds[num_fds] < 0) {
uwsgi_error_open(filename);
free(filename);
goto clear;
}
free(filename);
num_fds++;
}
send:
sn_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
sn_iov[0].iov_base = "uwsgi-setns";
sn_iov[0].iov_len = 11;
sn_iov[1].iov_base = &num_fds;
sn_iov[1].iov_len = sizeof(int);
sn_msg.msg_name = NULL;
sn_msg.msg_namelen = 0;
sn_msg.msg_iov = sn_iov;
sn_msg.msg_iovlen = 2;
sn_msg.msg_flags = 0;
sn_msg.msg_control = sn_msg_control;
sn_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&sn_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
int *sn_fd_ptr = (int *) CMSG_DATA(cmsg);
for(i=0;i<num_fds;i++) {
sn_fd_ptr[i] = fds[i];
}
if (sendmsg(setns_client, &sn_msg, 0) < 0) {
uwsgi_error("uwsgi_master_manage_setns()/sendmsg()");
}
free(sn_msg_control);
clear:
close(setns_client);
if (ns) {
closedir(ns);
for(i=0;i<num_fds;i++) {
close(fds[i]);
}
}
}
#endif
/*
this is racey, but the worst thing would be printing garbage in the logs...
*/
void uwsgi_dump_worker(int wid, char *msg) {
int i;
uwsgi_log_verbose("%s !!! worker %d status !!!\n", msg, wid);
for(i=0;i<uwsgi.cores;i++) {
struct uwsgi_core *uc = &uwsgi.workers[wid].cores[i];
struct wsgi_request *wsgi_req = &uc->req;
if (uc->in_request) {
uwsgi_log_verbose("%s [core %d] %.*s - %.*s %.*s since %llu\n", msg, i, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) (wsgi_req->start_of_request/(1000*1000)));
}
}
uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
}
+54 -972
View File
File diff suppressed because it is too large Load Diff
+3 -11
View File
@@ -54,9 +54,6 @@ static struct uwsgi_mount_flag umflags[] = {
#ifdef MS_REMOUNT
{"remount", MS_REMOUNT},
#endif
#ifdef MS_NOSUID
{"nosuid", MS_NOSUID},
#endif
#ifdef MS_SYNCHRONOUS
{"sync", MS_SYNCHRONOUS},
#endif
@@ -105,7 +102,7 @@ uint64_t uwsgi_mount_flag(char *mflag) {
return 0;
}
int uwsgi_mount(char *fs, char *what, char *where, char *flags, char *data) {
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
struct iovec iov[6];
#endif
@@ -124,7 +121,7 @@ int uwsgi_mount(char *fs, char *what, char *where, char *flags, char *data) {
free(mflags);
parsed:
#ifdef __linux__
return mount(what, where, fs, mountflags, data);
return mount(what, where, fs, mountflags, NULL);
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
iov[0].iov_base = "fstype";
iov[0].iov_len = 7;
@@ -200,7 +197,6 @@ unmountable:
}
int uwsgi_mount_hook(char *arg) {
char *data = NULL;
char *tmp_arg = uwsgi_str(arg);
char *fs = tmp_arg;
char *what = strchr(fs, ' ');
@@ -212,12 +208,8 @@ int uwsgi_mount_hook(char *arg) {
char *flags = strchr(where, ' ');
if (flags) {
*flags = 0; flags++;
data = strchr(flags, ' ');
if (data) {
*data = 0; data++;
}
}
if (uwsgi_mount(fs, what, where, flags, data)) {
if (uwsgi_mount(fs, what, where, flags)) {
uwsgi_error("uwsgi_mount()");
free(tmp_arg);
return -1;
-1
View File
@@ -77,7 +77,6 @@ void uwsgi_mule(int id) {
}
}
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
uwsgi_mule_run();
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include <uwsgi.h>
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
-112
View File
@@ -1,112 +0,0 @@
#include <uwsgi.h>
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
/*
steps:
mkdir(.uwsgi_plugin_builder)
generate .uwsgi_plugin_builder/uwsgi.h
generate .uwsgi_plugin_builder/uwsgiconfig.py
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
*/
void uwsgi_build_plugin(char *directory) {
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
_exit(1);
}
}
char *dot_h = uwsgi_get_dot_h();
if (!dot_h) {
uwsgi_log("unable to generate uwsgi.h");
_exit(1);
}
if (strlen(dot_h) == 0) {
free(dot_h);
uwsgi_log("invalid uwsgi.h");
_exit(1);
}
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (dot_h_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
free(dot_h);
_exit(1);
}
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *config_py = uwsgi_get_config_py();
if (!config_py) {
uwsgi_log("unable to generate uwsgiconfig.py");
_exit(1);
}
if (strlen(config_py) == 0) {
uwsgi_log("invalid uwsgiconfig.py");
_exit(1);
}
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (config_py_fd < 0) {
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
_exit(1);
}
ssize_t config_py_len = (ssize_t) strlen(config_py);
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
uwsgi_error("uwsgi_build_plugin()/write()");
_exit(1);
}
char *cflags = uwsgi_get_cflags();
if (!cflags) {
uwsgi_log("unable to find cflags\n");
_exit(1);
}
if (strlen(cflags) == 0) {
uwsgi_log("invalid cflags\n");
_exit(1);
}
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
uwsgi_error("uwsgi_build_plugin()/setenv()");
_exit(1);
}
// now run the python script
char *argv[6];
argv[0] = getenv("PYTHON");
if (!argv[0]) argv[0] = "python";
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
argv[2] = "--extra-plugin";
char *space = strchr(directory, ' ');
if (space) {
*space = 0;
argv[3] = directory;
argv[4] = space+1;
argv[5] = NULL;
}
else {
argv[3] = directory;
argv[4] = NULL;
}
execvp(argv[0], argv);
// never here...
_exit(1);
}
+1 -1
View File
@@ -77,7 +77,7 @@ int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t r
char buf[4096];
int ret = snprintf(buf, 4096, "{ \"state\" : \"uploading\", \"received\" : %llu, \"size\" : %llu }\r\n", (unsigned long long) (wsgi_req->post_cl - remains), (unsigned long long) wsgi_req->post_cl);
if (ret <= 0 || ret >= 4096) {
if (ret < 0) {
return -1;
}
+76 -27
View File
@@ -18,6 +18,81 @@ static size_t get_content_length(char *buf, uint16_t size) {
}
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
struct sockaddr_un un_addr;
char *udp_port;
ssize_t ret;
struct uwsgi_header *uh;
udp_port = strchr(host, ':');
if (udp_port) {
udp_port[0] = 0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port + 1));
udp_addr.sin_addr.s_addr = inet_addr(host);
}
else {
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&un_addr, 0, sizeof(struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
// use 102 as the magic number
strncat(un_addr.sun_path, host, 102);
}
if (message) {
uh = (struct uwsgi_header *) message;
}
else {
uh = (struct uwsgi_header *) uwsgi_malloc(4);
}
uh->modifier1 = modifier1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(message_size);
#else
uh->pktsize = message_size;
#endif
uh->modifier2 = modifier2;
if (udp_port) {
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
udp_port[0] = ':';
}
else {
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
if (ret < 0) {
uwsgi_error("send_udp_message()/sendto()");
}
close(fd);
if ((char *) uh != message) {
free(uh);
}
return ret;
}
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
char *ptr = (char *) uh;
@@ -337,12 +412,6 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_ORIGIN", 11)) {
wsgi_req->http_origin = buf;
wsgi_req->http_origin_len = len;
return 0;
}
return 0;
}
@@ -494,7 +563,7 @@ static int uwsgi_proto_check_18(struct wsgi_request *wsgi_req, char *key, char *
static int uwsgi_proto_check_20(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.logging_options.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
if (uwsgi.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
wsgi_req->remote_addr = buf;
wsgi_req->remote_addr_len = len;
return 0;
@@ -520,28 +589,9 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
wsgi_req->if_modified_since_len = len;
return 0;
}
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_KEY", 22)) {
wsgi_req->http_sec_websocket_key = buf;
wsgi_req->http_sec_websocket_key_len = len;
return 0;
}
return 0;
}
static int uwsgi_proto_check_27(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_PROTOCOL", 27)) {
wsgi_req->http_sec_websocket_protocol = buf;
wsgi_req->http_sec_websocket_protocol_len = len;
return 0;
}
return 0;
}
void uwsgi_proto_hooks_setup() {
int i = 0;
for(i=0;i<UWSGI_PROTO_MAX_CHECK;i++) {
@@ -559,7 +609,6 @@ void uwsgi_proto_hooks_setup() {
uwsgi.proto_hooks[18] = uwsgi_proto_check_18;
uwsgi.proto_hooks[20] = uwsgi_proto_check_20;
uwsgi.proto_hooks[22] = uwsgi_proto_check_22;
uwsgi.proto_hooks[27] = uwsgi_proto_check_27;
}
+16 -71
View File
@@ -24,39 +24,6 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
return ret;
}
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
struct pollfd upoll[2];
timeout = timeout * 1000;
upoll[0].fd = fd0;
upoll[0].events = POLLIN;
upoll[0].revents = 0;
upoll[1].fd = fd1;
upoll[1].events = POLLIN;
upoll[1].revents = 0;
int ret = poll(upoll, 2, timeout);
if (ret > 0) {
if (upoll[0].revents & POLLIN) {
*fd = fd0;
return 1;
}
if (upoll[1].revents & POLLIN) {
*fd = fd1;
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
}
return ret;
}
/*
seek()/rewind() language-independent implementations.
*/
@@ -65,16 +32,14 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (wsgi_req->post_file) {
if (pos < 0) {
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_seek()/fseek()");
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_seek()/fseek()");
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
@@ -130,7 +95,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
if (!tmp_buf) {
uwsgi_req_error("consume_body_for_readline()/realloc()");
uwsgi_error("consume_body_for_readline()/realloc()");
return -1;
}
wsgi_req->post_readline_buf = tmp_buf;
@@ -149,7 +114,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_req_error("consume_body_for_readline()/fread()");
uwsgi_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += remains;
@@ -175,7 +140,6 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
if (len == 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
if (len < 0) {
@@ -183,7 +147,6 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
wait:
@@ -196,7 +159,6 @@ wait:
return 0;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
// 0 means timeout
@@ -205,7 +167,6 @@ wait:
return -1;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -243,8 +204,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
wsgi_req->post_readline_buf = malloc(amount);
if (!wsgi_req->post_readline_buf) {
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_readline()/malloc()");
*rlen = -1;
return NULL;
}
@@ -257,7 +217,6 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
if (consume_body_for_readline(wsgi_req)) {
wsgi_req->read_errors++;
*rlen = -1;
return NULL;
}
@@ -313,9 +272,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (avail > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
if (!tmp_buf) {
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
uwsgi_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
wsgi_req->read_errors++;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
@@ -362,8 +320,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (!wsgi_req->post_read_buf) {
wsgi_req->post_read_buf = malloc(remains);
if (!wsgi_req->post_read_buf) {
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_read()/malloc()");
*rlen = -1;
return NULL;
}
@@ -374,8 +331,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
if (!tmp_buf) {
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
return NULL;
}
@@ -392,8 +348,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_req_error("uwsgi_request_body_read()/fread()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_request_body_read()/fread()");
return NULL;
}
*rlen += remains;
@@ -423,7 +378,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
wait:
@@ -435,7 +389,7 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
}else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
@@ -444,7 +398,6 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
return NULL;
}
@@ -456,7 +409,6 @@ wait:
}
*rlen = -1;
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return NULL;
}
@@ -476,8 +428,8 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
char *ptr = wsgi_req->post_buffering_buf;
while (remains > 0) {
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
@@ -495,7 +447,6 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
@@ -511,7 +462,6 @@ wait:
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
return -1;
}
uwsgi_read_timeout(remains);
@@ -532,8 +482,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
return -1;
}
@@ -550,8 +499,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
while (post_remains > 0) {
// during post buffering we need to constantly reset the harakiri
if (uwsgi.harakiri_options.workers > 0) {
inc_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
// we use the already available post buffering buffer to read chunks....
@@ -569,7 +518,6 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
goto wait;
}
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
@@ -583,13 +531,11 @@ wait:
}
else {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
}
goto end;
}
if (ret < 0) {
uwsgi_read_error(remains);
wsgi_req->read_errors++;
goto end;
}
uwsgi_read_timeout(remains);
@@ -597,8 +543,7 @@ wait:
write:
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
wsgi_req->read_errors++;
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
goto end;
}
+52 -103
View File
@@ -582,88 +582,6 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
return 0;
}
// simple math router
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint16_t var_vallen = 0;
char *var_value = uwsgi_get_var(wsgi_req, ur->data, ur->data_len, &var_vallen);
if (!var_value) return UWSGI_ROUTE_BREAK;
int64_t base_value = uwsgi_str_num(var_value, var_vallen);
int64_t value = 1;
if (ur->data2_len) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) return UWSGI_ROUTE_BREAK;
value = uwsgi_str_num(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
}
char out[sizeof(UMAX64_STR)+1];
int64_t total = 0;
switch(ur->custom) {
// -
case 1:
total = base_value - value;
break;
// *
case 2:
total = base_value * value;
break;
// /
case 3:
if (value == 0) total = 0;
else {
total = base_value/value;
}
break;
default:
total = base_value + value;
break;
}
int ret = uwsgi_long2str2n(total, out, sizeof(UMAX64_STR)+1);
if (ret <= 0) return UWSGI_ROUTE_BREAK;
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, out, ret)) {
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_simple_math_plus(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_simple_math_func;
char *comma = strchr(arg, ',');
if (comma) {
ur->data = arg;
ur->data_len = comma - arg;
ur->data2 = comma+1;
ur->data2_len = strlen(ur->data);
}
else {
ur->data = arg;
ur->data_len = strlen(arg);
}
return 0;
}
static int uwsgi_router_simple_math_minus(struct uwsgi_route *ur, char *arg) {
ur->custom = 1;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_multiply(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
ur->custom = 2;
return uwsgi_router_simple_math_plus(ur, arg);
}
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
@@ -705,7 +623,7 @@ static int uwsgi_router_flush(struct uwsgi_route *ur, char *arg) {
static int transform_fixcl(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) ut->chunk->pos);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
wsgi_req->write_errors++;
return -1;
}
@@ -722,6 +640,7 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -962,7 +881,7 @@ static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_r
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (chdir(ub->buf)) {
uwsgi_req_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
@@ -1280,21 +1199,10 @@ static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
char **subject = (char **) (((char *)(wsgi_req))+route->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+route->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, route, *subject, *subject_len, route->data, route->data_len);
if (!ub) {
return UWSGI_ROUTE_BREAK;
}
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
if (route->custom) {
if (uwsgi_buffer_append(ub, "\r\n", 2)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
}
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
@@ -1656,7 +1564,7 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
}
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
ret = uwsgi_num2str(uwsgi.shared->backlog);
ret = uwsgi_num2str(uwsgi.shared->load);
*vallen = strlen(ret);
}
@@ -1721,6 +1629,48 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
return ret;
}
#ifdef UWSGI_MATHEVAL
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
char *ret = NULL;
// avoid crash
if (!wsgi_req->var_cnt) return NULL;
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
int i,j = 0;
char *ptr = vars_buf;
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
names[j] = ptr;
ptr += wsgi_req->hvec[i-1].iov_len;
*ptr++=0;
char *num = ptr;
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
ptr += wsgi_req->hvec[i].iov_len;
*ptr++=0;
values[j] = strtod(num, NULL);
j++;
}
char *expr = ptr;
memcpy(ptr, key, keylen); ptr += keylen;
*ptr++=0;
void *e = evaluator_create(expr);
if (!e) goto end;
double n = evaluator_evaluate(e, j, names, values);
evaluator_destroy(e);
ret = uwsgi_num2str((int)n);
*vallen = strlen(ret);
end:
free(vars_buf);
free(names);
free(values);
return ret;
}
#endif
// register embedded routers
void uwsgi_register_embedded_routers() {
uwsgi_register_router("continue", uwsgi_router_continue);
@@ -1753,11 +1703,6 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
uwsgi_register_router("/", uwsgi_router_simple_math_divide);
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
@@ -1801,6 +1746,10 @@ void uwsgi_register_embedded_routers() {
urv->need_free = 1;
urv = uwsgi_register_route_var("httptime", uwsgi_route_var_httptime);
urv->need_free = 1;
#ifdef UWSGI_MATHEVAL
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
urv->need_free = 1;
#endif
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
urv->need_free = 1;
+10 -38
View File
@@ -59,11 +59,11 @@ already:
return ret;
}
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
struct uwsgi_rpc *urpc = NULL;
uint64_t i;
uint64_t ret = 0;
uint16_t ret = 0;
int pos = (uwsgi.mywid * uwsgi.rpc_max);
@@ -85,15 +85,8 @@ uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
return ret;
}
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
size_t *r = (size_t *) data;
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
*r = uwsgi_str_num(value, vl);
}
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
uint8_t i;
uint16_t ulen;
@@ -104,10 +97,9 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
if (*buffer)
return buffer;
return NULL;
buffer = uwsgi_malloc(UMAX16);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
@@ -117,7 +109,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
return NULL;
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return NULL;
@@ -155,37 +147,17 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
bufptr += ulen;
}
// ok the request is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.socket_timeout)) {
// ok the reuqest is ready, let's send it in non blocking way
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
// ok time to wait for the response in non blocking way
size_t rlen = buffer_size+4;
uint8_t modifier2 = 0;
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.socket_timeout, NULL, &modifier2)) {
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
}
// 64bit response ?
if (modifier2 == 5) {
size_t content_len = 0;
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
if (content_len > rlen) {
char *tmp_buf = realloc(buffer, content_len);
if (!tmp_buf) goto error;
buffer = tmp_buf;
}
rlen = content_len;
// read the raw value from the socket
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.socket_timeout)) {
goto error;
}
}
close(fd);
*len = rlen;
if (*len == 0) {
-366
View File
@@ -1,366 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
This is an high-performance memory area shared by all workers/cores/threads
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
the language object.
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
You can configure multiple areas specifying multiple --sharedarea options
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
*/
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
if (id > uwsgi.sharedareas_cnt-1) return NULL;
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
if (pos > sa->max_pos) return NULL;
return sa;
}
int uwsgi_sharedarea_update(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
sa->updates++;
return 0;
}
int uwsgi_sharedarea_rlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_wlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_wlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_unlock(int id) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
uwsgi_rwunlock(sa->lock);
return 0;
}
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
if (len == 0) len = (sa->max_pos + 1) - pos;
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
uwsgi_rlock(sa->lock);
memcpy(blob, sa->area + pos, len);
sa->hits++;
uwsgi_rwunlock(sa->lock);
return len;
}
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + len > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
memcpy(sa->area + pos, blob, len);
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
return rlen == 8 ? 0 : -1;
}
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
}
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
return rlen == 1 ? 0 : -1;
}
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
}
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
return rlen == 2 ? 0 : -1;
}
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
}
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
return rlen == 4 ? 0 : -1;
}
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
}
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr+=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 1 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int8_t *n_ptr = (int8_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 2 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int16_t *n_ptr = (int16_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int32_t *n_ptr = (int32_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (pos + 4 > sa->max_pos + 1) return -1;
uwsgi_wlock(sa->lock);
int64_t *n_ptr = (int64_t *) (sa->area + pos);
*n_ptr-=amount;
sa->updates++;
uwsgi_rwunlock(sa->lock);
return 0;
}
/*
returns:
0 -> on updates
-1 -> on error
-2 -> on timeout
*/
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
int waiting = 0;
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
if (!sa) return -1;
if (!freq) freq = 100;
uwsgi_rlock(sa->lock);
uint64_t updates = sa->updates;
uwsgi_rwunlock(sa->lock);
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
uwsgi.wait_milliseconds_hook(freq);
waiting += freq;
// lock sa
uwsgi_rlock(sa->lock);
if (sa->updates != updates) {
uwsgi_rwunlock(sa->lock);
return 0;
}
// unlock sa
uwsgi_rwunlock(sa->lock);
}
return -2;
}
int uwsgi_sharedarea_new_id() {
int id = uwsgi.sharedareas_cnt;
uwsgi.sharedareas_cnt++;
if (!uwsgi.sharedareas) {
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
}
else {
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
if (!usa) {
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
exit(1);
}
uwsgi.sharedareas = usa;
}
return id;
}
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
return sa;
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = pages;
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
uwsgi.sharedareas[id]->area = area;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
return announce_sa(uwsgi.sharedareas[id]);
}
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
char *s_pages = NULL;
char *s_file = NULL;
char *s_fd = NULL;
char *s_ptr = NULL;
char *s_size = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"pages", &s_pages,
"file", &s_file,
"fd", &s_fd,
"ptr", &s_ptr,
"size", &s_size,
NULL)) {
uwsgi_log("invalid sharedarea keyval syntax\n");
exit(1);
}
uint64_t len = 0;
int pages = 0;
if (s_size) {
len = uwsgi_n64(s_size);
pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) pages++;
}
if (s_pages) {
pages = atoi(s_pages);
}
char *area = NULL;
struct uwsgi_sharedarea *sa = NULL;
if (s_file) {
}
else if (s_fd) {
}
else if (s_ptr) {
}
if (pages) {
if (!area) {
sa = uwsgi_sharedarea_init(pages);
}
else {
uwsgi_sharedarea_init_ptr(area, len);
}
}
if (s_pages) free(s_pages);
if (s_file) free(s_file);
if (s_fd) free(s_fd);
if (s_ptr) free(s_ptr);
if (s_size) free(s_size);
return sa;
}
void uwsgi_sharedareas_init() {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
char *is_keyval = strchr(usl->value, '=');
if (!is_keyval) {
uwsgi_sharedarea_init(atoi(usl->value));
}
else {
uwsgi_sharedarea_init_keyval(usl->value);
}
}
}
+9 -11
View File
@@ -45,21 +45,21 @@ int uwsgi_signal_handler(uint8_t sig) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
uwsgi.mules[uwsgi.muleid - 1].signals++;
if (uwsgi.harakiri_options.mules > 0) {
set_mule_harakiri(uwsgi.harakiri_options.mules);
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
@@ -78,7 +78,7 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.harakiri_options.spoolers > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
@@ -269,7 +269,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.socket_timeout, 0);
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0)
return -1;
@@ -279,7 +279,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
return -1;
}
int ret = uwsgi_read_response(fd, &uh, uwsgi.socket_timeout, NULL);
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
close(fd);
return ret;
@@ -301,10 +301,8 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
else {
uwsgi_error("uwsgi_signal_send()");
}
uwsgi.shared->unrouted_signals++;
return -1;
}
uwsgi.shared->routed_signals++;
return 0;
}
+14 -55
View File
@@ -23,7 +23,6 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
@@ -72,7 +71,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
uwsgi_debug("SNMP version: %d\n", version);
#endif
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
if (*ptr != SNMP_STRING)
return;
ptr++;
@@ -197,7 +196,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
ptr++;
oidlen = *ptr;
if (oidlen < 11)
if (oidlen != 11)
return;
ptr++;
@@ -209,33 +208,21 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
oid_part[0] = *ptr;
// old-style SNMP metrics
if (oid_part[0] == 1 || oid_part[0] == 2) {
ptr++;
if (oid_part[0] != 1 && oid_part[0] != 2)
return;
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
oid_part[1] = *ptr;
if (oid_part[1] < 1 || oid_part[1] > 100)
return;
ptr++;
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
}
// metrics subsystem
else {
size_t metric_asn_len = oidlen - 9;
char *metric_asn = (char *) ptr;
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
if (!um) return;
uwsgi_rlock(uwsgi.metrics_lock);
int64_t value = *um->value;
uwsgi_rwunlock(uwsgi.metrics_lock);
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
}
// check for null
if (memcmp((char *) ptr, "\x05\x00", 2))
return;
ptr += 2;
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
if (size > 0) {
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
@@ -305,7 +292,6 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
int32_t val32 = (int32_t) snmp_val;
// check for counter, counter64 or gauge
@@ -317,7 +303,6 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
}
else {
tlen = 4;
ptr = (uint8_t *) &val32;
}
buffer[0] = tlen;
@@ -367,32 +352,6 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
}
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint8_t oid_sz;
if (type == UWSGI_METRIC_GAUGE) {
buffer[size - 2] = SNMP_GAUGE;
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
}
else {
buffer[size - 2] = SNMP_COUNTER64;
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
}
if (oid_sz < 1)
return -1;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
+105 -73
View File
@@ -6,22 +6,6 @@ static int connect_to_unix(char *, int, int);
static int connect_to_tcp(char *, int, int, int);
static int connect_to_udp(char *, int);
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
if (!protocol) protocol = "uwsgi";
struct uwsgi_protocol *up = uwsgi.protocols;
while(up) {
if (!strcmp(protocol, up->name)) {
up->func(uwsgi_sock);
return;
}
up = up->next;
}
uwsgi_log("unable to find protocol %s\n", protocol);
exit(1);
}
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
@@ -750,7 +734,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (!uwsgi.no_defer_accept) {
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.socket_timeout, sizeof(int))) {
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
}
// OSX has no SO_ACCEPTFILTER !!!
@@ -1382,7 +1366,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
if (uwsgi_sock->fd_threads && async_id > -1) {
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
}
else if (uwsgi_sock->fd > -1) {
@@ -1869,8 +1853,109 @@ void uwsgi_set_sockets_protocols() {
setup_proto:
if (!requested_protocol) requested_protocol = uwsgi.protocol;
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
}
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && !strcmp("raw", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_raw_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
}
#endif
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
nextsock:
uwsgi_sock = uwsgi_sock->next;
}
@@ -1906,56 +1991,3 @@ int uwsgi_accept(int server_fd) {
}
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
while(up) {
if (!strcmp(name, up->name)) {
goto found;
}
old_up = up;
up = up->next;
}
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
up->name = name;
if (old_up) {
old_up->next = up;
}
else {
uwsgi.protocols = up;
}
found:
up->func = func;
return up;
}
int uwsgi_socket_passcred(int fd) {
#ifdef SO_PASSCRED
int optval = 1;
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
uwsgi_error("uwsgi_socket_passcred()/setsockopt()");
return -1;
}
return 0;
#else
return -1;
#endif
}
void uwsgi_protocols_register() {
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
#ifdef UWSGI_SSL
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
#endif
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
}
+3 -3
View File
@@ -552,11 +552,11 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler) {
time_t now = uwsgi_now();
if (uwsgi.harakiri_options.spoolers > 0) {
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if (uwsgi.harakiri_options.spoolers > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
if (ret == 0)
+1 -31
View File
@@ -132,6 +132,7 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
free(sni_dir_key);
free(sni_dir_client_ca);
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
return SSL_TLSEXT_ERR_OK;
}
done:
@@ -510,41 +511,10 @@ struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *ke
SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca);
if (!ctx) {
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name);
free(name);
return NULL;
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
usl->custom_ptr = ctx;
// mark it as dynamic
usl->custom = 1;
uwsgi_log_verbose("[uwsgi-sni for pid %d] added SSL context for %s\n", (int) getpid(), name);
return usl;
}
void uwsgi_ssl_del_sni_item(char *name, uint16_t name_len) {
struct uwsgi_string_list *usl = NULL, *last_sni = NULL, *sni_item = NULL;
uwsgi_foreach(usl, uwsgi.sni) {
if (!uwsgi_strncmp(usl->value, usl->len, name, name_len) && usl->custom) {
sni_item = usl;
break;
}
last_sni = usl;
}
if (!sni_item) return;
if (last_sni) {
last_sni->next = sni_item->next;
}
else {
uwsgi.sni = sni_item->next;
}
// we are free to destroy it as no more clients are using it
SSL_CTX_free((SSL_CTX *) sni_item->custom_ptr);
free(sni_item->value);
free(sni_item);
uwsgi_log_verbose("[uwsgi-sni for pid %d] destroyed SSL context for %s\n",(int) getpid(), name);
}
+60 -33
View File
@@ -111,7 +111,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -123,7 +123,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -149,7 +149,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -161,7 +161,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -188,7 +188,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -200,7 +200,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -227,7 +227,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":", key);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -239,7 +239,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -254,7 +254,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\"", str);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -266,7 +266,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -287,7 +287,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -299,7 +299,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -325,7 +325,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret <= 0)
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
@@ -337,7 +337,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret <= 0)
if (ret < 0)
return -1;
}
@@ -379,7 +379,7 @@ void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
@@ -440,11 +440,6 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
void *events = event_queue_alloc(1);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
if (nevents < 0) {
if (errno == EINTR) continue;
uwsgi_log_verbose("ending the stats pusher thread...\n");
return;
}
if (nevents > 0) {
int interesting_fd = event_queue_interesting_fd(events, 0);
char buf[4096];
@@ -462,8 +457,7 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
struct uwsgi_stats *us = NULL;
while (uspi) {
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
if (((uspi->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
if (uspi->needs_retry) uspi->retries++;
if ((uspi->last_run + delta) <= now) {
if (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
@@ -476,17 +470,6 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
uspi->pusher->func(uspi, now, us->base, us->pos);
}
uspi->last_run = now;
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
uspi->next_retry = now + uspi->retry_delay;
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
uspi->needs_retry = 0;
uspi->retries = 0;
} else if (uspi->retries) {
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
uspi->retries = 0;
}
}
next:
uspi = uspi->next;
@@ -548,6 +531,50 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
return pusher;
}
struct uwsgi_stats_pusher_file_conf {
char *path;
char *freq;
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
if (!uspi->configured) {
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
if (uspi->arg) {
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
free(uspi);
return;
}
}
if (!uspic->path)
uspic->path = "uwsgi.stats";
if (!uspic->separator)
uspic->separator = "\n\n";
if (uspic->freq)
uspi->freq = atoi(uspic->freq);
uspi->configured = 1;
uspi->data = uspic;
}
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uspic->path);
return;
}
ssize_t rlen = write(fd, json, json_len);
if (rlen != (ssize_t) json_len) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
rlen = write(fd, uspic->separator, strlen(uspic->separator));
if (rlen != (ssize_t) strlen(uspic->separator)) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
close(fd);
}
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
if (us->dirty) return;
+9 -163
View File
@@ -20,51 +20,6 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_SSL
static void uwsgi_subscription_sni_check(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_req *usr) {
if (usr->sni_key_len > 0 && usr->sni_crt_len > 0) {
if (!current_slot->sni_enabled) {
char *sni_key = uwsgi_concat2n(usr->sni_key, usr->sni_key_len, "", 0);
char *sni_crt = uwsgi_concat2n(usr->sni_crt, usr->sni_crt_len, "", 0);
char *sni_ca = NULL;
if (usr->sni_ca_len > 0) {
sni_ca = uwsgi_concat2n(usr->sni_ca, usr->sni_ca_len, "", 0);
}
char *servername = NULL;
char *colon = memchr(current_slot->key, ':', current_slot->keylen);
if (colon) {
servername = uwsgi_concat2n(current_slot->key, colon-current_slot->key, "", 0);
}
else {
servername = uwsgi_concat2n(current_slot->key, current_slot->keylen, "", 0);
}
if (uwsgi_ssl_add_sni_item(servername, sni_crt, sni_key, uwsgi.sni_dir_ciphers , sni_ca)) {
current_slot->sni_enabled = 1;
}
if (sni_key) free(sni_key);
if (sni_crt) free(sni_crt);
if (sni_ca) free(sni_ca);
}
}
}
#endif
int uwsgi_subscription_credentials_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.subscriptions_credentials_check_dir) {
char *filename = uwsgi_concat2n(usl->value, usl->len, slot->key, slot->keylen);
struct stat st;
int ret = stat(filename, &st);
free(filename);
if (ret != 0) continue;
if (st.st_uid != usr->uid) continue;
if (st.st_gid != usr->gid) continue;
// accepted...
return 1;
}
return 0;
}
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
if (keylen > 0xff)
@@ -350,12 +305,6 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
EVP_PKEY_free(node_slot->sign_public_key);
EVP_MD_CTX_destroy(node_slot->sign_ctx);
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
// if there is a SNI context active, destroy it
if (node_slot->sni_enabled) {
uwsgi_ssl_del_sni_item(node_slot->key, node_slot->keylen);
}
#endif
#endif
free(node_slot);
slot[hash_key] = NULL;
@@ -409,11 +358,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
return NULL;
}
#endif
if (uwsgi.subscriptions_credentials_check_dir && !uwsgi_subscription_credentials_check(current_slot, usr)) {
return NULL;
}
node = current_slot->nodes;
while (node) {
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
@@ -444,8 +388,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
return NULL;
}
// check here as we are sure the node will be added
uwsgi_subscription_sni_check(current_slot, usr);
#endif
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
@@ -454,8 +396,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->modifier2 = usr->modifier2;
node->requests = 0;
node->last_requests = 0;
node->tx = 0;
node->rx = 0;
node->transferred = 0;
node->reference = 0;
node->death_mark = 0;
node->failcnt = 0;
@@ -466,9 +407,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
if (!node->weight)
node->weight = 1;
node->wrr = 0;
node->pid = usr->pid;
node->uid = usr->uid;
node->gid = usr->gid;
node->last_check = uwsgi_now();
node->slot = current_slot;
memcpy(node->name, usr->address, usr->address_len);
@@ -526,27 +464,16 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
#endif
current_slot->keylen = usr->keylen;
memcpy(current_slot->key, usr->key, usr->keylen);
if (uwsgi.subscriptions_credentials_check_dir) {
if (!uwsgi_subscription_credentials_check(current_slot, usr)) {
free(current_slot);
return NULL;
}
}
current_slot->key[usr->keylen] = 0;
current_slot->hits = 0;
#ifdef UWSGI_SSL
current_slot->sni_enabled = 0;
uwsgi_subscription_sni_check(current_slot, usr);
#endif
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
current_slot->nodes->slot = current_slot;
current_slot->nodes->len = usr->address_len;
current_slot->nodes->reference = 0;
current_slot->nodes->requests = 0;
current_slot->nodes->last_requests = 0;
current_slot->nodes->tx = 0;
current_slot->nodes->rx = 0;
current_slot->nodes->transferred = 0;
current_slot->nodes->death_mark = 0;
current_slot->nodes->failcnt = 0;
current_slot->nodes->modifier1 = usr->modifier1;
@@ -558,9 +485,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
if (!current_slot->nodes->weight)
current_slot->nodes->weight = 1;
current_slot->nodes->wrr = 0;
current_slot->nodes->pid = usr->pid;
current_slot->nodes->uid = usr->uid;
current_slot->nodes->gid = usr->gid;
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
current_slot->nodes->last_check = uwsgi_now();
@@ -592,64 +516,8 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
static void send_subscription(char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
struct sockaddr_un un_addr;
ssize_t ret;
char *udp_port = strchr(host, ':');
if (udp_port) {
udp_port[0] = 0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("send_subscription()/socket()");
return;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port + 1));
udp_addr.sin_addr.s_addr = inet_addr(host);
}
else {
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("send_subscription()/socket()");
return;
}
memset(&un_addr, 0, sizeof(struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
// use 102 as the magic number
strncat(un_addr.sun_path, host, 102);
}
if (udp_port) {
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
udp_port[0] = ':';
}
else {
if (uwsgi.subscriptions_use_credentials) {
// could be useless as internally the socket could add them automagically
ret = uwsgi_pass_cred2(fd, message, message_size, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
else {
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
}
}
if (ret < 0) {
uwsgi_error("send_subscription()/sendto()");
}
close(fd);
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
if (socket_name == NULL && !uwsgi.sockets)
return;
@@ -692,22 +560,8 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
}
#endif
if (sni_key) {
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, sni_key, strlen(sni_key))) goto end;
}
if (sni_crt) {
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, sni_crt, strlen(sni_crt))) goto end;
}
if (sni_ca) {
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, sni_ca, strlen(sni_ca))) goto end;
}
// add uwsgi header
if (uwsgi_buffer_set_uh(ub, 224, cmd)) goto end;
send_subscription(udp_address, ub->buf, ub->pos);
send_udp_message(224, cmd, udp_address, ub->buf, ub->pos - 4);
end:
uwsgi_buffer_destroy(ub);
}
@@ -825,7 +679,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
modifier1 = NULL;
modifier1_len = 0;
}
@@ -843,7 +697,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
modifier1 = NULL;
modifier1_len = 0;
lines[i] = '\n';
@@ -873,7 +727,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
modifier1_len = strlen(modifier1);
}
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
if (modifier1)
modifier1[-1] = ',';
if (sign)
@@ -898,9 +752,6 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
char *s2_modifier1 = NULL;
char *s2_modifier2 = NULL;
char *s2_check = NULL;
char *s2_sni_key = NULL;
char *s2_sni_crt = NULL;
char *s2_sni_ca = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"server", &s2_server,
@@ -912,9 +763,6 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
"modifier2", &s2_modifier2,
"sign", &s2_sign,
"check", &s2_check,
"sni_key", &s2_sni_key,
"sni_crt", &s2_sni_crt,
"sni_ca", &s2_sni_ca,
NULL)) {
return;
}
@@ -950,7 +798,7 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
modifier2 = atoi(s2_modifier2);
}
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign, s2_sni_key, s2_sni_crt, s2_sni_ca);
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign);
end:
if (s2_server) free(s2_server);
if (s2_key) free(s2_key);
@@ -964,8 +812,6 @@ end:
}
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
if (uwsgi.subscriptions_blocked) return;
// -- subscribe
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while (subscriptions) {
+177 -359
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern char **environ;
#ifdef __BIG_ENDIAN__
uint16_t uwsgi_swap16(uint16_t x) {
@@ -47,7 +48,7 @@ void inc_harakiri(int sec) {
uwsgi.workers[uwsgi.mywid].harakiri += sec;
}
else {
alarm(uwsgi.harakiri_options.workers + sec);
alarm(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] + sec);
}
}
@@ -206,20 +207,17 @@ void uwsgi_set_cgroup() {
if (!uwsgi.cgroup)
return;
if (getuid())
return;
usl = uwsgi.cgroup;
while (usl) {
int mode = strtol(uwsgi.cgroup_dir_mode, 0, 8);
if (mkdir(usl->value, mode)) {
if (errno != EEXIST) {
uwsgi_error("uwsgi_set_cgroup()/mkdir()");
uwsgi_error("mkdir()");
exit(1);
}
if (chmod(usl->value, mode)) {
uwsgi_error("uwsgi_set_cgroup()/chmod()");
uwsgi_error("chmod()");
exit(1);
}
uwsgi_log("using Linux cgroup %s with mode %o\n", usl->value, mode);
@@ -279,41 +277,41 @@ void uwsgi_set_cgroup() {
#endif
#ifdef UWSGI_CAP
void uwsgi_apply_cap(cap_value_t * cap, int caps_count) {
cap_value_t minimal_cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID, CAP_SETPCAP };
void uwsgi_apply_cap(cap_value_t *cap, int caps_count) {
cap_value_t minimal_cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID, CAP_SETPCAP };
cap_t caps = cap_init();
cap_t caps = cap_init();
if (!caps) {
uwsgi_error("cap_init()");
exit(1);
}
cap_clear(caps);
if (!caps) {
uwsgi_error("cap_init()");
exit(1);
}
cap_clear(caps);
cap_set_flag(caps, CAP_EFFECTIVE, 4, minimal_cap_values, CAP_SET);
cap_set_flag(caps, CAP_EFFECTIVE, 4, minimal_cap_values, CAP_SET);
cap_set_flag(caps, CAP_PERMITTED, 4, minimal_cap_values, CAP_SET);
cap_set_flag(caps, CAP_PERMITTED, caps_count, cap, CAP_SET);
cap_set_flag(caps, CAP_PERMITTED, 4, minimal_cap_values, CAP_SET);
cap_set_flag(caps, CAP_PERMITTED, caps_count, cap, CAP_SET);
cap_set_flag(caps, CAP_INHERITABLE, caps_count, cap, CAP_SET);
cap_set_flag(caps, CAP_INHERITABLE, caps_count, cap, CAP_SET);
if (cap_set_proc(caps) < 0) {
uwsgi_error("cap_set_proc()");
exit(1);
}
cap_free(caps);
if (cap_set_proc(caps) < 0) {
uwsgi_error("cap_set_proc()");
exit(1);
}
cap_free(caps);
#ifdef __linux__
#ifdef SECBIT_KEEP_CAPS
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#else
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#endif
#endif
}
@@ -518,7 +516,7 @@ void uwsgi_as_root() {
#endif
#endif
if (in_jail || uwsgi.jailed) {
if (in_jail) {
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.mount_post_jail) {
@@ -588,7 +586,7 @@ void uwsgi_as_root() {
exit(1);
}
#ifdef __linux__
if (uwsgi.logging_options.memory_report) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
}
#endif
@@ -604,10 +602,10 @@ void uwsgi_as_root() {
}
*space = 0;
#if defined(MS_REC) && defined(MS_PRIVATE)
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
uwsgi_error("mount()");
exit(1);
}
if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
uwsgi_error("mount()");
exit(1);
}
#endif
if (chdir(arg)) {
uwsgi_error("pivot_root()/chdir()");
@@ -620,7 +618,7 @@ void uwsgi_as_root() {
uwsgi_error("pivot_root()");
exit(1);
}
if (uwsgi.logging_options.memory_report) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
}
free(arg);
@@ -633,25 +631,25 @@ void uwsgi_as_root() {
#endif
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
if (uwsgi.unshare2 && !uwsgi.reloads) {
if (uwsgi.unshare2 && !uwsgi.reloads) {
if (unshare(uwsgi.unshare2)) {
uwsgi_error("unshare()");
exit(1);
}
else {
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare2);
}
if (unshare(uwsgi.unshare2)) {
uwsgi_error("unshare()");
exit(1);
}
else {
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare2);
}
#ifdef CLONE_NEWUSER
if (uwsgi.unshare2 & CLONE_NEWUSER) {
if (setuid(0)) {
uwsgi_error("uwsgi_as_root()/setuid(0)");
exit(1);
}
}
if (uwsgi.unshare2 & CLONE_NEWUSER) {
if (setuid(0)) {
uwsgi_error("uwsgi_as_root()/setuid(0)");
exit(1);
}
}
#endif
in_jail = 1;
}
in_jail = 1;
}
#endif
if (uwsgi.refork_as_root) {
@@ -727,7 +725,7 @@ void uwsgi_as_root() {
uwsgi_foreach(usl, uwsgi.call_as_root) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
@@ -945,7 +943,7 @@ void uwsgi_as_root() {
uwsgi_foreach(usl, uwsgi.call_as_user) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
exit(1);
}
}
@@ -1028,7 +1026,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
// get memory usage
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
get_memusage(&rss, &vsz);
uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
uwsgi.workers[uwsgi.mywid].rss_size = rss;
@@ -1039,7 +1037,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
uwsgi.workers[uwsgi.mywid].requests++;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].read_errors += wsgi_req->read_errors;
// this is used for MAX_REQUESTS
uwsgi.workers[uwsgi.mywid].delta_requests++;
}
@@ -1075,13 +1072,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
if (!wsgi_req->is_raw && uwsgi.p[wsgi_req->uh->modifier1]->after_request)
uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req);
// after_request custom hooks
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.after_request_hooks) {
void (*func) (struct wsgi_request *) = (void (*)(struct wsgi_request *)) usl->custom_ptr;
func(wsgi_req);
}
if (uwsgi.threads > 1) {
// now the thread can die...
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &tmp_id);
@@ -1108,7 +1098,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
}
// defunct process reaper
if (uwsgi.reaper == 1) {
if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1) {
while (waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0);
}
@@ -1146,9 +1136,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->websocket_buf) {
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
}
if (wsgi_req->websocket_send_buf) {
uwsgi_buffer_destroy(wsgi_req->websocket_send_buf);
}
// reset request
@@ -1160,21 +1147,21 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
// yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
if (uwsgi.max_requests > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.max_requests
&& (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]
&& (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
goodbye_cruel_world();
}
if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
goodbye_cruel_world();
}
if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
goodbye_cruel_world();
}
// after the first request, if i am a vassal, signal Emperor about my loyalty
// ready to accept request, if i am a vassal signal Emperor about my loyalty
if (uwsgi.has_emperor && !uwsgi.loyal) {
uwsgi_log("announcing my loyalty to the Emperor...\n");
char byte = 17;
@@ -1234,7 +1221,7 @@ void uwsgi_linux_ksm_map(void) {
}
// we now have areas
if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
dirty = 1;
}
else {
@@ -1302,7 +1289,7 @@ long uwsgi_num_from_file(char *filename, int quiet) {
// setup for a new request
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_socket *uwsgi_sock) {
wsgi_req->app_id = -1;
wsgi_req->app_id = uwsgi.default_app;
wsgi_req->async_id = async_id;
wsgi_req->sendfile_fd = -1;
@@ -1345,13 +1332,13 @@ int wsgi_req_async_recv(struct wsgi_request *wsgi_req) {
if (event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->fd) < 0)
return -1;
async_add_timeout(wsgi_req, uwsgi.socket_timeout);
async_add_timeout(wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
}
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
return 0;
@@ -1382,8 +1369,8 @@ int wsgi_req_recv(int queue, struct wsgi_request *wsgi_req) {
}
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
#ifdef UWSGI_ROUTING
@@ -1561,7 +1548,15 @@ void parse_sys_envs(char **envs) {
char *earg, *eq_pos;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=", 14) && strncmp(*uenvs, "UWSGI_VASSALS_DIR=", 18) && strncmp(*uenvs, "UWSGI_EMPEROR_FD=", 17) && strncmp(*uenvs, "UWSGI_BROODLORD_NUM=", 20) && strncmp(*uenvs, "UWSGI_EMPEROR_FD_CONFIG=", 24) && strncmp(*uenvs, "UWSGI_EMPEROR_PROXY=", 20) && strncmp(*uenvs, "UWSGI_JAIL_PID=", 15) && strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
if (!strncmp(*uenvs, "UWSGI_", 6) &&
strncmp(*uenvs, "UWSGI_RELOADS=", 14) &&
strncmp(*uenvs, "UWSGI_VASSALS_DIR=", 18) &&
strncmp(*uenvs, "UWSGI_EMPEROR_FD=", 17) &&
strncmp(*uenvs, "UWSGI_BROODLORD_NUM=", 20) &&
strncmp(*uenvs, "UWSGI_EMPEROR_FD_CONFIG=", 24) &&
strncmp(*uenvs, "UWSGI_EMPEROR_PROXY=", 20) &&
strncmp(*uenvs, "UWSGI_JAIL_PID=", 15) &&
strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
earg = uwsgi_malloc(strlen(*uenvs + 6) + 1);
env_to_arg(*uenvs + 6, earg);
eq_pos = strchr(earg, '=');
@@ -1864,7 +1859,7 @@ int uwsgi_num2str2n(int num, char *ptr, int size) {
int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
int ret = snprintf(ptr, size, "%llu", num);
if (ret <= 0 || ret > size)
if (ret < 0)
return 0;
return ret;
}
@@ -1905,6 +1900,33 @@ void uwsgi_unix_signal(int signum, void (*func) (int)) {
}
}
char *uwsgi_get_exported_opt(char *key) {
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
return uwsgi.exported_opts[i]->value;
}
}
return NULL;
}
char *uwsgi_get_optname_by_index(int index) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (op->shortcut == index) {
return op->name;
}
op++;
}
return NULL;
}
int uwsgi_list_has_num(char *list, int num) {
char *list2 = uwsgi_concat2(list, "");
@@ -2772,7 +2794,6 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
{"ns", CLONE_NEWNS},
{"fs", CLONE_NEWNS},
{"mount", CLONE_NEWNS},
{"mnt", CLONE_NEWNS},
#endif
#ifdef CLONE_SYSVSEM
{"sysvsem", CLONE_SYSVSEM},
@@ -2892,7 +2913,7 @@ static int uwsgi_get_cap_id(char *name) {
return -1;
}
int uwsgi_build_cap(char *what, cap_value_t ** cap) {
int uwsgi_build_cap(char *what, cap_value_t **cap) {
int cap_id;
char *caps = uwsgi_str(what);
@@ -3145,180 +3166,45 @@ void escape_json(char *src, size_t len, char *dst) {
*ptr++ = 0;
}
/*
build PATH_INFO from raw_uri
it manages:
percent encoding
dot_segments removal
stop at the first #
*/
void http_url_decode(char *buf, uint16_t * len, char *dst) {
enum {
zero = 0,
percent1,
percent2,
slash,
dot,
dotdot
} status;
uint16_t i, current_new_len, new_len = 0;
uint16_t i;
int percent = 0;
char value[2];
size_t new_len = 0;
char *ptr = dst;
value[0] = '0';
value[1] = '0';
status = zero;
int no_slash = 0;
if (*len > 0 && buf[0] != '/') {
status = slash;
no_slash = 1;
}
for (i = 0; i < *len; i++) {
char c = buf[i];
if (c == '#')
break;
switch (status) {
case zero:
if (c == '%') {
status = percent1;
break;
if (buf[i] == '%') {
if (percent == 0) {
percent = 1;
}
if (c == '/') {
status = slash;
break;
}
*ptr++ = c;
new_len++;
break;
case percent1:
if (c == '%') {
else {
*ptr++ = '%';
new_len++;
status = zero;
break;
percent = 0;
}
value[0] = c;
status = percent2;
break;
case percent2:
value[1] = c;
*ptr++ = hex2num(value);
new_len++;
status = zero;
break;
case slash:
if (c == '.') {
status = dot;
break;
}
// we could be at the first round (in non slash)
if (i > 0 || !no_slash) {
*ptr++ = '/';
new_len++;
}
if (c == '%') {
status = percent1;
break;
}
if (c == '/') {
status = slash;
break;
}
*ptr++ = c;
new_len++;
status = zero;
break;
case dot:
if (c == '.') {
status = dotdot;
break;
}
if (c == '/') {
status = slash;
break;
}
if (i > 1) {
*ptr++ = '/';
new_len++;
}
*ptr++ = '.';
new_len++;
if (c == '%') {
status = percent1;
break;
}
*ptr++ = c;
new_len++;
status = zero;
break;
case dotdot:
// here we need to remove a segment
if (c == '/') {
current_new_len = new_len;
while (current_new_len) {
current_new_len--;
ptr--;
if (dst[current_new_len] == '/') {
break;
}
}
new_len = current_new_len;
status = slash;
break;
}
if (i > 2) {
*ptr++ = '/';
new_len++;
}
*ptr++ = '.';
new_len++;
*ptr++ = '.';
new_len++;
if (c == '%') {
status = percent1;
break;
}
*ptr++ = c;
new_len++;
status = zero;
break;
// over engineering
default:
*ptr++ = c;
new_len++;
break;
}
}
switch (status) {
case slash:
case dot:
*ptr++ = '/';
new_len++;
break;
case dotdot:
current_new_len = new_len;
while (current_new_len) {
if (dst[current_new_len - 1] == '/') {
break;
else {
if (percent == 1) {
value[0] = buf[i];
percent = 2;
}
else if (percent == 2) {
value[1] = buf[i];
*ptr++ = hex2num(value);
percent = 0;
new_len++;
}
else {
*ptr++ = buf[i];
new_len++;
}
current_new_len--;
}
new_len = current_new_len;
break;
default:
break;
}
*len = new_len;
@@ -3369,10 +3255,8 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
}
}
if (!uwsgi.no_default_app) {
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
uwsgi.default_app = id;
}
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
uwsgi.default_app = id;
}
return wi;
@@ -3534,11 +3418,7 @@ int uwsgi_write_intfile(char *filename, int n) {
uwsgi_error_open(filename);
exit(1);
}
if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile)) {
fclose(pidfile);
return -1;
}
if (fclose(pidfile)) {
if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile) || fclose(pidfile)) {
return -1;
}
return 0;
@@ -3578,7 +3458,7 @@ void uwsgi_set_cpu_affinity() {
base_cpu = base_cpu % uwsgi.cpus;
}
ret = snprintf(buf, 4096, "mapping worker %d to CPUs:", uwsgi.mywid);
if (ret < 25 || ret >= 4096) {
if (ret < 25) {
uwsgi_log("unable to initialize cpu affinity !!!\n");
exit(1);
}
@@ -3596,7 +3476,7 @@ void uwsgi_set_cpu_affinity() {
base_cpu = 0;
CPU_SET(base_cpu, &cpuset);
ret = snprintf(buf + pos, 4096 - pos, " %d", base_cpu);
if (ret < 2 || ret >= 4096) {
if (ret < 2) {
uwsgi_log("unable to initialize cpu affinity !!!\n");
exit(1);
}
@@ -3770,6 +3650,26 @@ error:
return NULL;
}
// evaluate a math expression
#ifdef UWSGI_MATHEVAL
double uwsgi_matheval(char *expr) {
#ifdef UWSGI_DEBUG
uwsgi_log("matheval expr = %s\n", expr);
#endif
double ret = 0.0;
void *e = evaluator_create(expr);
if (!e)
return ret;
ret = evaluator_evaluate(e, 0, NULL, NULL);
evaluator_destroy(e);
return ret;
}
char *uwsgi_matheval_str(char *expr) {
double ret = uwsgi_matheval(expr);
return uwsgi_num2str((int) ret);
}
#endif
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
size_t i;
va_list ap;
@@ -3859,7 +3759,7 @@ int uwsgi_send_http_stats(int fd) {
char buf[4096];
int ret = uwsgi_waitfd(fd, uwsgi.socket_timeout);
int ret = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0)
return -1;
@@ -3938,30 +3838,32 @@ char *uwsgi_strip(char *src) {
void uwsgi_uuid(char *buf) {
#ifdef UWSGI_UUID
uuid_t uuid_value;
uuid_generate(uuid_value);
uuid_unparse(uuid_value, buf);
uuid_t uuid_zmq;
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, buf);
#else
int i, r[11];
if (!uwsgi_file_exists("/dev/urandom"))
goto fallback;
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
goto fallback;
for (i = 0; i < 11; i++) {
if (read(fd, &r[i], 4) != 4) {
close(fd);
goto fallback;
}
}
close(fd);
goto done;
int i,r[11];
static int srand_called = 0;
if (!uwsgi_file_exists("/dev/urandom")) goto fallback;
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) goto fallback;
for(i=0;i<11;i++) {
if (read(fd, &r[i], 4) != 4) {
close(fd); goto fallback;
}
}
close(fd);
goto done;
fallback:
for (i = 0; i < 11; i++) {
r[i] = rand();
}
if (!srand_called) {
srand((unsigned int) getpid());
srand_called = 1;
}
for(i=0;i<11;i++) {
r[i] = rand();
}
done:
snprintf(buf, 37, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10]);
snprintf(buf, 37, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10]);
#endif
}
@@ -4325,7 +4227,6 @@ void uwsgi_envdir(char *edir) {
free(content);
}
closedir(d);
}
void uwsgi_envdirs(struct uwsgi_string_list *envdirs) {
@@ -4345,86 +4246,3 @@ void uwsgi_exit(int status) {
// disable macro expansion
(exit) (status);
}
int uwsgi_base128(struct uwsgi_buffer *ub, uint64_t l, int first) {
if (l > 127) {
if (uwsgi_base128(ub, l / 128, 0))
return -1;
}
l %= 128;
if (first) {
if (uwsgi_buffer_u8(ub, (uint8_t) l))
return -1;
}
else {
if (uwsgi_buffer_u8(ub, 0x80 | (uint8_t) l))
return -1;
}
return 0;
}
#ifdef __linux__
void uwsgi_setns(char *path) {
int (*u_setns) (int, int) = (int (*)(int, int)) dlsym(RTLD_DEFAULT, "setns");
if (!u_setns) {
uwsgi_log("your system misses setns() syscall !!!\n");
exit(1);
}
// cound be overwritten
int count = 64;
uwsgi_log("joining namespaces from %s ...\n", path);
for (;;) {
int ns_fd = uwsgi_connect(path, 30, 0);
if (ns_fd < 0) {
uwsgi_error("uwsgi_setns()/uwsgi_connect()");
sleep(1);
continue;
}
int *fds = uwsgi_attach_fd(ns_fd, &count, "uwsgi-setns", 11);
if (fds && count > 0) {
int i;
for (i = 0; i < count; i++) {
if (fds[i] > -1) {
if (u_setns(fds[i], 0) < 0) {
uwsgi_error("uwsgi_setns()/setns()");
exit(1);
}
close(fds[i]);
}
}
free(fds);
break;
}
if (fds)
free(fds);
close(ns_fd);
sleep(1);
}
}
#endif
mode_t uwsgi_mode_t(char *value, int *error) {
mode_t mode = 0;
*error = 0;
if (strlen(value) < 3) {
*error = 1;
return mode;
}
if (strlen(value) == 3) {
mode = (mode << 3) + (value[0] - '0');
mode = (mode << 3) + (value[1] - '0');
mode = (mode << 3) + (value[2] - '0');
}
else {
mode = (mode << 3) + (value[1] - '0');
mode = (mode << 3) + (value[2] - '0');
mode = (mode << 3) + (value[3] - '0');
}
return mode;
}
+204 -347
View File
File diff suppressed because it is too large Load Diff
+14 -87
View File
@@ -10,17 +10,9 @@
extern struct uwsgi_server uwsgi;
static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf;
if (!ub) {
wsgi_req->websocket_send_buf = uwsgi_buffer_new(10 + len);
ub = wsgi_req->websocket_send_buf;
}
else {
// reset the buffer
ub->pos = 0;
}
if (uwsgi_buffer_u8(ub, opcode)) goto error;
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
if (len < 126) {
if (uwsgi_buffer_u8(ub, len)) goto error;
}
@@ -37,6 +29,7 @@ static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_re
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
@@ -66,79 +59,34 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
}
return 0;
}
// pong received, send another ping
// pong received, send anther ping
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
return uwsgi_websockets_ping(wsgi_req);
}
return 0;
}
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode);
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
if (!ub) return -1;
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
static int uwsgi_websocket_send_from_sharedarea_do(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len, uint8_t opcode) {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) return -1;
if (!len) {
len = sa->honour_used ? sa->used-pos : ((sa->max_pos+1)-pos);
}
uwsgi_rlock(sa->lock);
sa->hits++;
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, sa->area, len, opcode);
uwsgi_rwunlock(sa->lock);
if (!ub) return -1;
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return ret;
}
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x81);
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x81);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x82);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x82);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
@@ -367,39 +315,18 @@ ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi
return len;
}
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len, char *proto, uint16_t proto_len) {
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
#ifdef UWSGI_SSL
if (!key_len) {
key = wsgi_req->http_sec_websocket_key;
key_len = wsgi_req->http_sec_websocket_key_len;
}
if (key_len == 0) return -1;
char sha1[20];
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
// if origin was requested or proto_len is specified, send it back
if (wsgi_req->http_origin_len > 0 || origin_len > 0) {
if (!origin_len) {
origin = wsgi_req->http_origin;
origin_len = wsgi_req->http_origin_len;
}
if (origin_len > 0) {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
}
else {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
}
// if protocol was requested or proto_len is specified, send it back
if (wsgi_req->http_sec_websocket_protocol_len > 0 || proto_len > 0) {
if (!proto_len) {
proto = wsgi_req->http_sec_websocket_protocol;
proto_len = wsgi_req->http_sec_websocket_protocol_len;
}
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Protocol", 22, proto, proto_len)) return -1;
}
// generate websockets sha1 and encode it to base64
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
size_t b64_len = 0;
+9 -246
View File
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
wsgi_req->write_errors++;
return -1;
}
@@ -51,7 +51,7 @@ int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t sta
end = cl-1;
}
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
if (ret <= 0 || ret >= (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
wsgi_req->write_errors++;
return -1;
}
@@ -179,7 +179,7 @@ int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, ui
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
}
static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
return UWSGI_OK;
}
@@ -209,20 +209,11 @@ static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
return UWSGI_AGAIN;
}
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
int ret = uwsgi_response_write_headers_do0(wsgi_req);
if (ret != UWSGI_AGAIN) return ret;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_write_headers_do()");
uwsgi_error("uwsgi_response_write_headers_do()");
}
wsgi_req->write_errors++;
return -1;
@@ -230,7 +221,6 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
@@ -248,100 +238,6 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
/*
private function for highly optimized writes (1 single syscall for headers and body)
*/
static int uwsgi_response_writev_headers_and_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct iovec iov[2];
int ret = uwsgi_response_write_headers_do0(wsgi_req);
if (ret != UWSGI_AGAIN) return ret;
iov[0].iov_base = wsgi_req->headers->buf;
iov[0].iov_len = wsgi_req->headers->pos;
iov[1].iov_base = buf;
iov[1].iov_len = len;
size_t iov_len = 2;
for(;;) {
errno = 0;
// no need to use writev if a single iovec remains
if (iov_len == 1) {
buf = iov[0].iov_base;
len = iov[0].iov_len;
// update counters
wsgi_req->headers_size += wsgi_req->headers->pos;
wsgi_req->headers_sent = 1;
wsgi_req->response_size += wsgi_req->write_pos - wsgi_req->headers_size;
wsgi_req->write_pos = 0;
goto fallback;
}
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_headers_and_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_headers_and_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->headers_size += wsgi_req->headers->pos;
wsgi_req->response_size += len;
wsgi_req->headers_sent = 1;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
fallback:
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
// here we use the parent name
uwsgi_req_error("uwsgi_response_write_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
// here we use the parent name
uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
@@ -382,9 +278,6 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
write:
// send headers if not already sent
if (!wsgi_req->headers_sent) {
if (wsgi_req->socket->proto_writev && len > 0 && wsgi_req->headers) {
return uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len);
}
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
@@ -397,11 +290,10 @@ sendbody:
if (len == 0) return UWSGI_OK;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_write_body_do()");
uwsgi_error("uwsgi_response_write_body_do()");
}
wsgi_req->write_errors++;
return -1;
@@ -409,7 +301,6 @@ sendbody:
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
@@ -426,130 +317,6 @@ sendbody:
return UWSGI_OK;
}
int uwsgi_response_writev_body_do(struct wsgi_request *wsgi_req, struct iovec *iov, size_t len) {
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
#ifdef UWSGI_ROUTING
// special case here, we could need to set transformations before
if (!wsgi_req->headers_sent) {
// apply response routes
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_response_routing = 0;
}
#endif
size_t i;
int buffering = 0;
// transformations apply to every vector
for(i=0;i<len;i++) {
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
int t_ret = uwsgi_apply_transformations(wsgi_req, iov[i].iov_base, iov[i].iov_len);
if (t_ret == 0) {
iov[i].iov_base = wsgi_req->transformed_chunk;
iov[i].iov_len = wsgi_req->transformed_chunk_len;
// reset transformation
wsgi_req->transformed_chunk = NULL;
wsgi_req->transformed_chunk_len = 0;
goto write;
}
if (t_ret == 1) {
buffering = 1;
continue;
}
wsgi_req->write_errors++;
return -1;
}
}
if (buffering) return UWSGI_OK;
write:
// send headers if not already sent
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
return -1;
}
sendbody:
if (len == 0) return UWSGI_OK;
// unfortunately vector based I/O cannot be accomplished on all protocols
if (!wsgi_req->socket->proto_writev) goto fallback;
// we use a copy to avoid mess
size_t iov_len = len;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
goto done;
fallback:
for(i=0;i<len;i++) {
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, iov[i].iov_base, iov[i].iov_len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_writev_body_do()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
}
done:
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
}
@@ -582,7 +349,7 @@ sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_req_error("uwsgi_response_sendfile_do()/fstat()");
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
@@ -600,7 +367,7 @@ sendfile:
if (!can_close) {
int tmp_fd = dup(fd);
if (tmp_fd < 0) {
uwsgi_req_error("uwsgi_response_sendfile_do()/dup()");
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
wsgi_req->write_errors++;
return -1;
}
@@ -621,11 +388,10 @@ sendfile:
wsgi_req->via = UWSGI_VIA_SENDFILE;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_response_sendfile_do()");
uwsgi_error("uwsgi_response_sendfile_do()");
}
wsgi_req->write_errors++;
if (can_close) close(fd);
@@ -634,7 +400,6 @@ sendfile:
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
@@ -689,11 +454,10 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
errno = 0;
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_req_error("uwsgi_simple_write()");
uwsgi_error("uwsgi_simple_write()");
}
wsgi_req->write_errors++;
return -1;
@@ -701,7 +465,6 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (ret == UWSGI_OK) {
break;
}
if (!uwsgi_is_again()) continue;
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
+3 -5
View File
@@ -226,7 +226,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
current_depth = depth;
// end the parsing cycle
if (in_uwsgi_section)
goto exit;
return;
}
else if (depth > current_depth && !in_uwsgi_section) {
goto next;
@@ -240,7 +240,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
// skip list and {} defined dict
if (key[0] == '-' || key[0] == '[' || key[0] == '{') {
if (in_uwsgi_section)
goto exit;
return;
goto next;
}
@@ -260,7 +260,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
val = strstr(key, ":\t");
}
if (!val)
goto exit;
return;
// get the right key
val[0] = 0;
// yeah overengeneering....
@@ -282,8 +282,6 @@ next:
if (colon) colon[0] = ':';
exit:
free(yaml);
}
#endif
+6 -5
View File
@@ -1,4 +1,5 @@
import uwsgi
import os
def application(env, start_response):
@@ -14,12 +15,12 @@ def application(env, start_response):
]
)
yield "--%s\r\n" % boundary
yield "--%s\n" % boundary
while 1:
yield "Content-Type: image/jpeg\r\n\r\n"
print os.system('screencapture -t jpg -m -T 1 screenshot.jpg')
f = open('screenshot.jpg')
yield env['wsgi.file_wrapper'](f)
yield "\r\n--%s\r\n" % boundary
uwsgi.sendfile('screenshot.jpg')
yield "--%s\n" % boundary
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
#os.system('screencapture -m -T 1 screenshot.jpg')
+10
View File
@@ -42,6 +42,16 @@ def application(env, start_response):
yield '<h2>dynamic options</h2>'
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
yield '<table border="1">'
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
+11
View File
@@ -47,6 +47,11 @@ def serve_logo(e, sr):
uwsgi.sendfile('logo_uWSGI.png')
return ''
def serve_options(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in range(0,256):
yield "<b>%d</b> = %d<br/>" % (opt, uwsgi.get_option(opt))
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
@@ -56,6 +61,7 @@ routes = {}
routes['/xsendfile'] = xsendfile
routes['/logo'] = serve_logo
routes['/config'] = serve_config
routes['/options'] = serve_options
@postfork
def setprocname():
@@ -113,6 +119,11 @@ def application(env, start_response):
Configuration<br/>
<iframe src="/config"></iframe><br/>
<br/>
Dynamic options<br/>
<iframe src="/options"></iframe><br/>
<br/>
Workers and applications<br/>
<table border="1">
+10
View File
@@ -9,6 +9,12 @@ def serve_logo(e, sr):
sr('200 OK', [('Content-Type', 'image/png')])
return uwsgi.sendfile('logo_uWSGI.png')
def serve_options(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in range(0,256):
body = "{opt} = {optvalue}<br/>".format(opt=opt, optvalue=uwsgi.get_option(opt))
yield bytes(body.encode('ascii'))
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
@@ -19,6 +25,7 @@ routes = {}
routes['/xsendfile'] = xsendfile
routes['/logo'] = serve_logo
routes['/config'] = serve_config
routes['/options'] = serve_options
def application(env, start_response):
@@ -36,6 +43,9 @@ Configuration<br/>
<br/>
Dynamic options<br/>
<iframe src="/options"></iframe><br/>
""".format(version=uwsgi.version.decode('ascii'))
return bytes(body.encode('ascii'))
+1 -11
View File
@@ -52,11 +52,6 @@ int uwsgi_is_a_keep_mount(char *mp) {
}
static int uwsgi_ns_start(void *v_argv) {
uwsgi_start(v_argv);
return uwsgi_run();
}
void linux_namespace_start(void *argv) {
for (;;) {
char stack[PTHREAD_STACK_MIN];
@@ -66,7 +61,7 @@ void linux_namespace_start(void *argv) {
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_ns_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
if (pid == -1) {
uwsgi_error("clone()");
exit(1);
@@ -111,11 +106,6 @@ void linux_namespace_start(void *argv) {
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
exit(1);
}
else if (uwsgi.exit_on_reload && WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 0) {
uwsgi_log("jailed master process exited and exit-on-reload is enabled, shutting down\n");
exit(0);
}
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
}
+46
View File
@@ -0,0 +1,46 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
if (wsgi_req->uh->pktsize != 0 && wsgi_req->uh->pktsize != 4)
return UWSGI_OK;
// write request
if (wsgi_req->uh->pktsize == 4) {
memcpy(&opt_value, wsgi_req->buffer, 4);
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh->modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh->modifier2] = opt_value;
// ACK
wsgi_req->uh->modifier1 = 255;
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->modifier2 = 1;
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
}
// get request
else {
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh->modifier2, uwsgi.shared->options[wsgi_req->uh->modifier2]);
wsgi_req->uh->modifier1 = 10;
wsgi_req->uh->pktsize = 4;
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
uwsgi_response_write_body_do(wsgi_req, (char *) &uwsgi.shared->options[wsgi_req->uh->modifier2], 4);
}
return UWSGI_OK;
}
struct uwsgi_plugin admin_plugin = {
.name = "admin",
.modifier1 = 10,
.request = uwsgi_request_admin,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='admin'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['admin_plugin']
+2 -2
View File
@@ -222,8 +222,8 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
+2 -2
View File
@@ -146,8 +146,8 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+36 -30
View File
@@ -26,6 +26,9 @@ struct uwsgi_carbon {
unsigned long long *last_busyness_values;
unsigned long long *current_busyness_values;
int *was_busy;
int need_retry;
time_t last_update;
time_t next_retry;
int max_retries;
int retry_delay;
char *root_node;
@@ -37,7 +40,6 @@ struct uwsgi_carbon {
int zero_avg;
uint64_t last_requests;
struct uwsgi_stats_pusher *pusher;
int use_metrics;
} u_carbon;
static struct uwsgi_option carbon_options[] = {
@@ -53,7 +55,6 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different)", uwsgi_opt_true, &u_carbon.use_metrics, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -107,7 +108,7 @@ static void carbon_post_init() {
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries < 0) u_carbon.max_retries = 0;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
@@ -152,13 +153,14 @@ static void carbon_post_init() {
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set next update to now()+retry_delay, this way we will have first flush just after start
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
uspi->freq = u_carbon.freq;
uspi->retry_delay = u_carbon.retry_delay;
uspi->max_retries = u_carbon.max_retries;
// no need to generate the json
uspi->raw=1;
}
@@ -183,15 +185,14 @@ static int carbon_write(int fd, char *fmt,...) {
return 1;
}
static int carbon_push_stats(int retry_cycle, time_t now) {
static void carbon_push_stats(int retry_cycle, time_t now) {
struct carbon_server_list *usl = u_carbon.servers_data;
if (!u_carbon.servers_data) return 0;
if (!u_carbon.servers_data) return;
int i;
int fd;
int wok;
char *ip;
char *carbon_address = NULL;
int needs_retry;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
@@ -199,7 +200,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
}
needs_retry = 0;
u_carbon.need_retry = 0;
while(usl) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
@@ -227,7 +228,15 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
needs_retry = 1;
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
carbon_address, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
usl->healthy = 0;
usl->errors++;
free(carbon_address);
@@ -237,8 +246,6 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
if (u_carbon.use_metrics) goto metrics_loop;
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
@@ -281,7 +288,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
total_busyness += worker_busyness;
u_carbon.was_busy[i-1] = 0;
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
// only running workers are counted in total memory stats and if memory-report option is enabled
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
@@ -294,7 +301,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
wok = carbon_write(fd, "%s%s.%s.worker%d.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) now);
if (!wok) goto clear;
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.worker%d.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) now);
if (!wok) goto clear;
@@ -327,7 +334,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
}
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) now);
if (!wok) goto clear;
@@ -373,18 +380,6 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
if (!wok) goto clear;
metrics_loop:
if (u_carbon.use_metrics) {
struct uwsgi_metric *um = uwsgi.metrics;
while(um) {
uwsgi_rlock(uwsgi.metrics_lock);
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
uwsgi_rwunlock(uwsgi.metrics_lock);
if (!wok) goto clear;
um = um->next;
}
}
usl->healthy = 1;
usl->errors = 0;
@@ -395,12 +390,23 @@ clear:
nxt:
usl = usl->next;
}
return needs_retry;
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
if (u_carbon.need_retry)
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
u_carbon.last_update -= u_carbon.timeout;
}
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
uspi->needs_retry = carbon_push_stats(uspi->retries, now);
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
carbon_push_stats(1, now);
}
else {
// update
u_carbon.need_retry = 0;
carbon_push_stats(0, now);
}
}
static void carbon_cleanup() {
+1 -1
View File
@@ -17,7 +17,7 @@ int cheaper_backlog2_algo(int can_spawn) {
int i;
#ifdef __linux__
int backlog = uwsgi.socket_timeout;
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
#else
int backlog = 0;
#endif
+48 -83
View File
@@ -13,13 +13,11 @@ struct uwsgi_cheaper_busyness_global {
uint64_t busyness_max;
uint64_t busyness_min;
uint64_t *last_values;
uint64_t *current_busyness;
uint64_t total_avg_busyness;
int *was_busy;
uint64_t tcheck;
uint64_t last_cheaped; // last time worker was cheaped due to low busyness
uint64_t next_cheap; // timestamp, we can cheap worker after it
uint64_t penalty; // penalty for respawning to fast, it will be added to multiplier
uint64_t penalty; // penelty for respawning to fast, it will be added to multiplier
uint64_t min_multi; //initial multiplier will be stored here
uint64_t cheap_multi; // current multiplier value
int last_action; // 1 - spawn workers ; 2 - cheap worker
@@ -43,7 +41,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_max, 0},
{"cheaper-busyness-min", required_argument, 0,
"set the cheaper busyness low percent limit, below that value worker is considered idle (default 25)",
"set the cheaper busyness low percent limit, belowe that value worker is considered idle (default 25)",
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_min, 0},
{"cheaper-busyness-multiplier", required_argument, 0,
@@ -59,7 +57,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
#ifdef __linux__
{"cheaper-busyness-backlog-alert", required_argument, 0,
"spawn emergency worker(s) if any time listen queue is higher than this value (default 33)",
"spawn emergency worker(s) if anytime listen queue is higher than this value (default 33)",
uwsgi_opt_set_int, &uwsgi_cheaper_busyness_global.backlog_alert, 0},
{"cheaper-busyness-backlog-multiplier", required_argument, 0,
"set cheaper multiplier used for emergency workers (default 3)",
@@ -150,6 +148,46 @@ int cheaper_busyness_algo(int can_spawn) {
// we use microseconds
uint64_t t = uwsgi.cheaper_overload*1000000;
// this happens on the first run, the required memory is allocated
if (!uwsgi_cheaper_busyness_global.last_values) {
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
}
if (!uwsgi_cheaper_busyness_global.was_busy) {
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set defaults
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
#ifdef __linux__
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
#endif
if (!uwsgi_cheaper_busyness_global.min_multi) {
// store initial multiplier so we don't loose its initial value
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
// since this is first run we will print current values
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
#ifdef __linux__
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
#endif
}
// initialize with current time
if (uwsgi_cheaper_busyness_global.tcheck == 0) uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
if (uwsgi_cheaper_busyness_global.next_cheap == 0) set_next_cheap_time();
int active_workers = 0;
uint64_t total_busyness = 0;
uint64_t avg_busyness = 0;
@@ -164,7 +202,7 @@ int cheaper_busyness_algo(int can_spawn) {
}
#ifdef __linux__
int backlog = uwsgi.shared->backlog;
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
#endif
uint64_t now = uwsgi_micros();
@@ -190,21 +228,11 @@ int cheaper_busyness_algo(int can_spawn) {
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
i+1, uwsgi.cheaper_overload, percent);
if (uwsgi.has_metrics) {
// update metrics
uwsgi_wlock(uwsgi.metrics_lock);
uwsgi_cheaper_busyness_global.current_busyness[i] = percent;
uwsgi_rwunlock(uwsgi.metrics_lock);
}
}
uwsgi_cheaper_busyness_global.last_values[i] = uwsgi.workers[i+1].running_time;
}
avg_busyness = (active_workers ? total_busyness / active_workers : 0);
uwsgi_wlock(uwsgi.metrics_lock);
uwsgi_cheaper_busyness_global.total_avg_busyness = avg_busyness;
uwsgi_rwunlock(uwsgi.metrics_lock);
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %ds average busyness of %d worker(s) is at %d%%\n",
(int) uwsgi.cheaper_overload, (int) active_workers, (int) avg_busyness);
@@ -233,7 +261,7 @@ int cheaper_busyness_algo(int can_spawn) {
// worker was cheaped and then spawned back in less than current multiplier*cheaper_overload seconds
// we will increase the multiplier so that next time worker will need to wait longer before being cheaped
uwsgi_cheaper_busyness_global.cheap_multi += uwsgi_cheaper_busyness_global.penalty;
uwsgi_log("[busyness] worker(s) respawned to fast, increasing cheaper multiplier to %llu (+%llu)\n",
uwsgi_log("[busyness] worker(s) respawned to fast, increasing chpeaper multiplier to %llu (+%llu)\n",
uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
} else {
decrease_multi();
@@ -305,7 +333,7 @@ int cheaper_busyness_algo(int can_spawn) {
// time needed to cheap them, than a lot min<busy<max when we do not reset timer
// and then another idle cycle than would trigger cheaping
if (uwsgi_cheaper_busyness_global.verbose)
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), resetting cheaper timer\n",
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), reseting cheaper timer\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi_cheaper_busyness_global.tolerance_counter);
set_next_cheap_time();
} else {
@@ -357,73 +385,10 @@ void uwsgi_cheaper_register_busyness(void) {
uwsgi_register_cheaper_algo("busyness", cheaper_busyness_algo);
}
static int uwsgi_cheaper_busyness_init(void) {
if (!uwsgi.requested_cheaper_algo || strcmp(uwsgi.requested_cheaper_algo, "busyness")) return 0;
// this happens on the first run, the required memory is allocated
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
if (uwsgi.has_metrics) {
// allocate metrics memory
uwsgi_cheaper_busyness_global.current_busyness = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
}
// set defaults
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
#ifdef __linux__
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
#endif
// store initial multiplier so we don't loose that value
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
// since this is first run we will print current values
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
#ifdef __linux__
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
#endif
// register metrics if enabled
if (uwsgi.has_metrics) {
int i;
char buf[4096];
char buf2[4096];
for (i = 0; i < uwsgi.numproc; i++) {
if (snprintf(buf, 4096, "worker.%d.plugin.cheaper_busyness.busyness", i+1) <= 0) {
uwsgi_log("[busyness] unable to register busyness metric for worker %d\n", i+1);
exit(1);
}
if (snprintf(buf2, 4096, "3.%d.100.1", i+1) <= 0) {
uwsgi_log("[busyness] unable to register busyness metric oid for worker %d\n", i+1);
exit(1);
}
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.current_busyness[i], 0, NULL);
}
uwsgi_register_metric("plugin.cheaper_busyness.total_avg_busyness", "4.100.1", UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.total_avg_busyness, 0, NULL);
uwsgi_log("[busyness] metrics registered\n");
}
// initialize timers
uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
set_next_cheap_time();
return 0;
}
struct uwsgi_plugin cheaper_busyness_plugin = {
.name = "cheaper_busyness",
.on_load = uwsgi_cheaper_register_busyness,
.on_load = uwsgi_cheaper_register_busyness,
.options = uwsgi_cheaper_busyness_options,
.init = uwsgi_cheaper_busyness_init
};
+8 -31
View File
@@ -187,12 +187,11 @@ void uwsgi_opt_corerouter_zerg(char *opt, char *value, void *cr) {
close(zerg_fd);
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
free(zerg);
for(j=0;j<count;j++) {
if (zerg[j] == -1) break;
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
ugs->zerg = optarg;
}
}
@@ -272,18 +271,6 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
usr->sign = val;
usr->sign_len = vallen;
}
else if (!uwsgi_strncmp("sni_key", 7, key, keylen)) {
usr->sni_key = val;
usr->sni_key_len = vallen;
}
else if (!uwsgi_strncmp("sni_crt", 7, key, keylen)) {
usr->sni_crt = val;
usr->sni_crt_len = vallen;
}
else if (!uwsgi_strncmp("sni_ca", 6, key, keylen)) {
usr->sni_ca = val;
usr->sni_ca_len = vallen;
}
}
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
@@ -931,13 +918,10 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
uwsgi_log("starting %s in cheap mode\n", ucr->name);
}
for (i = 0; i < ucr->processes; i++) {
struct uwsgi_gateway *ug = register_gateway(ucr->name, uwsgi_corerouter_loop, ucr);
if (ug == NULL) {
if (register_gateway(ucr->name, uwsgi_corerouter_loop, ucr) == NULL) {
uwsgi_log("unable to register the %s gateway\n", ucr->name);
exit(1);
}
ug->uid = ucr->uid;
ug->gid = ucr->gid;
}
}
@@ -1036,9 +1020,6 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
if (uwsgi_stats_keyvaln_comma(us, "key", s_slot->key, s_slot->keylen)) goto end0;
if (uwsgi_stats_keylong_comma(us, "hash", (unsigned long long) s_slot->hash)) goto end0;
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) s_slot->hits)) goto end0;
#ifdef UWSGI_SSL
if (uwsgi_stats_keylong_comma(us, "sni_enabled", (unsigned long long) s_slot->sni_enabled)) goto end0;
#endif
if (uwsgi_stats_key(us , "nodes")) goto end0;
if (uwsgi_stats_list_open(us)) goto end0;
@@ -1052,13 +1033,9 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) s_node->modifier1)) goto end0;
if (uwsgi_stats_keylong_comma(us, "modifier2", (unsigned long long) s_node->modifier2)) goto end0;
if (uwsgi_stats_keylong_comma(us, "last_check", (unsigned long long) s_node->last_check)) goto end0;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) s_node->pid)) goto end0;
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) s_node->uid)) goto end0;
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) s_node->gid)) goto end0;
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) s_node->requests)) goto end0;
if (uwsgi_stats_keylong_comma(us, "last_requests", (unsigned long long) s_node->last_requests)) goto end0;
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->tx)) goto end0;
if (uwsgi_stats_keylong_comma(us, "rx", (unsigned long long) s_node->rx)) goto end0;
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->transferred)) goto end0;
if (uwsgi_stats_keylong_comma(us, "cores", (unsigned long long) s_node->cores)) goto end0;
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) s_node->load)) goto end0;
if (uwsgi_stats_keylong_comma(us, "weight", (unsigned long long) s_node->weight)) goto end0;
@@ -1098,7 +1075,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
size_t remains = us->pos;
off_t pos = 0;
while(remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
-7
View File
@@ -21,7 +21,6 @@
uwsgi_cr_error(peer, f);\
return -1;\
}\
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
peer->out_pos += len;
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
@@ -30,7 +29,6 @@
uwsgi_cr_error(peer, f);\
return -1;\
}\
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
ubuf##_pos += len;
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
@@ -53,7 +51,6 @@
uwsgi_cr_error(peer, f);\
return -1;\
}\
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
peer->in->pos += len;\
#define cr_read_exact(peer, l, f) read(peer->fd, peer->in->buf + peer->in->pos, (l - peer->in->pos));\
@@ -62,7 +59,6 @@
uwsgi_cr_error(peer, f);\
return -1;\
}\
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
peer->in->pos += len;\
#define cr_reset_hooks(peer) if(!peer->session->main_peer->disabled) {\
@@ -262,9 +258,6 @@ struct uwsgi_corerouter {
uint64_t active_sessions;
uid_t uid;
gid_t gid;
};
// a session is started when a client connect to the router
+3 -13
View File
@@ -4,7 +4,7 @@ common functions for various routers (fastrouter, http...)
*/
#include <uwsgi.h>
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -79,9 +79,6 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
}
else {
ugs->fd = bind_to_unix_dgram(ugs->name);
if (ugs->fd < 1 || (uwsgi.subscriptions_use_credentials && uwsgi_socket_passcred(ugs->fd))) {
exit(1);
}
}
uwsgi_socket_nb(ugs->fd);
}
@@ -116,17 +113,10 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
int i;
struct uwsgi_subscribe_req usr;
char bbuf[4096];
ssize_t len = -1;
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
if (uwsgi.subscriptions_use_credentials) {
len = uwsgi_recv_cred2(ugs->fd, bbuf, 4096, &usr.pid, &usr.uid, &usr.gid);
}
else {
len = recv(ugs->fd, bbuf, 4096, 0);
}
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
if (usr.sign_len > 0) {
// calc the base size
+12 -41
View File
@@ -12,8 +12,8 @@ static void uwsgi_opt_setup_coroae(char *opt, char *value, void *null) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
if (uwsgi.socket_timeout < 30) {
uwsgi.socket_timeout = 30;
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
}
// set loop engine
uwsgi.loop = "coroae";
@@ -51,7 +51,7 @@ SV * coroae_coro_new(CV *block) {
XPUSHs(sv_2mortal(newSVpv( "Coro", 4)));
XPUSHs(newRV_inc((SV *)block));
PUTBACK;
call_method("new", G_SCALAR|G_EVAL);
call_method("new", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
@@ -65,33 +65,6 @@ SV * coroae_coro_new(CV *block) {
return newobj;
}
static int coroae_wait_milliseconds(int timeout) {
int ret = -1;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(newSVnv(((double)timeout)/1000.0));
PUTBACK;
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
SV *p_ret = POPs;
if (SvTRUE(p_ret)) {
ret = 0;
}
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
static int coroae_wait_fd_read(int fd, int timeout) {
int ret = 0;
dSP;
@@ -101,7 +74,7 @@ static int coroae_wait_fd_read(int fd, int timeout) {
XPUSHs(newSViv(fd));
XPUSHs(newSViv(timeout));
PUTBACK;
call_pv("Coro::AnyEvent::readable", G_SCALAR|G_EVAL);
call_pv("Coro::AnyEvent::readable", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
@@ -128,14 +101,13 @@ static int coroae_wait_fd_write(int fd, int timeout) {
XPUSHs(sv_2mortal(newSViv(fd)));
XPUSHs(sv_2mortal(newSViv(timeout)));
PUTBACK;
call_pv("Coro::AnyEvent::writable", G_SCALAR|G_EVAL);
call_pv("Coro::AnyEvent::writable", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
}
else {
SV *p_ret = POPs;
if (SvTRUE(p_ret)) {
if (SvTRUE(POPs)) {
ret = 1;
}
}
@@ -164,7 +136,7 @@ XS(XS_coroae_accept_request) {
}
for(;;) {
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
wsgi_req->switches++;
if (ret <= 0) {
@@ -244,8 +216,8 @@ edge:
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
@@ -303,7 +275,7 @@ static SV *coroae_add_watcher(int fd, SV *cb) {
XPUSHs(newRV_inc(cb));
PUTBACK;
call_method( "io", G_SCALAR|G_EVAL);
call_method( "io", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -334,7 +306,7 @@ static SV *coroae_condvar_new() {
XPUSHs(sv_2mortal(newSVpv( "AnyEvent", 8)));
PUTBACK;
call_method( "condvar", G_SCALAR|G_EVAL);
call_method( "condvar", G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -360,7 +332,7 @@ static void coroae_wait_condvar(SV *cv) {
XPUSHs(cv);
PUTBACK;
call_method( "recv", G_DISCARD|G_EVAL);
call_method( "recv", G_DISCARD);
SPAGAIN;
if(SvTRUE(ERRSV)) {
@@ -405,7 +377,6 @@ static void coroae_loop() {
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
uwsgi.wait_write_hook = coroae_wait_fd_write;
uwsgi.wait_read_hook = coroae_wait_fd_read;
uwsgi.wait_milliseconds_hook = coroae_wait_milliseconds;
I_CORO_API("uwsgi::coroae");
+1 -1
View File
@@ -14,7 +14,7 @@ if not coroapi:
NAME='coroae'
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=format', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
LDFLAGS = []
LIBS = []
+1 -1
View File
@@ -10,7 +10,7 @@ static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// use 1 minute as the cron resolution
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
+1 -1
View File
@@ -25,7 +25,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
// the connection object (will be automatically destroyed at each cycle)
mongo::DBClientConnection c;
// set the socket timeout
c.setSoTimeout(uwsgi.socket_timeout);
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// connect
c.connect(uems->address);
+9 -7
View File
@@ -52,7 +52,9 @@ s.send_multipart(['touch','foo.ini',"[uwsgi]\nsocket=:4142"])
*/
#include <uwsgi.h>
#ifdef UWSGI_ZEROMQ
#include "../../uwsgi.h"
#include <zmq.h>
extern struct uwsgi_server uwsgi;
@@ -164,7 +166,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
}
}
// destroy an instance
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) {
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
struct uwsgi_instance *ui = emperor_get(name);
if (!ui) {
uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name);
@@ -213,11 +215,7 @@ static void uwsgi_imperial_monitor_zeromq_event(struct uwsgi_emperor_scanner *ue
// initialize the zmq PULL socket
static void uwsgi_imperial_monitor_zeromq_init(struct uwsgi_emperor_scanner *ues) {
void *context = zmq_init(1);
if (!context) {
uwsgi_error("uwsgi_imperial_monitor_zeromq_init()/zmq_init()");
exit(1);
}
void *context = uwsgi_zeromq_init();
ues->data = zmq_socket(context, ZMQ_PULL);
if (!ues->data) {
@@ -258,3 +256,7 @@ struct uwsgi_plugin emperor_zeromq_plugin = {
.name = "emperor_zeromq",
.on_load = emperor_zeromq_init,
};
#else
#error the uWSGI ZeroMQ imperial monitor requires uWSGI zeromq support
#endif
+441
View File
@@ -0,0 +1,441 @@
#include "../../uwsgi.h"
#include "erlang.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_erlang uerl;
struct uwsgi_option erlang_options[] = {
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void dump_eterm(ei_x_buff *x) {
int etype, esize, arity;
long long num;
char *atom;
int i;
char *binary;
long bin_size;
double fnum;
ei_get_type(x->buff, &x->index, &etype, &esize);
uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize);
switch(etype) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
case ERL_SMALL_BIG_EXT:
case ERL_LARGE_BIG_EXT:
ei_decode_longlong(x->buff, &x->index, &num);
uwsgi_log("num: %lu\n", num);
break;
case ERL_FLOAT_EXT:
ei_decode_double(x->buff, &x->index, &fnum);
uwsgi_log("float: %f\n", fnum);
break;
case ERL_STRING_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, atom);
uwsgi_log("string: %s\n", atom);
free(atom);
break;
case ERL_ATOM_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, atom);
uwsgi_log("atom: %s\n", atom);
free(atom);
break;
case ERL_SMALL_TUPLE_EXT:
case ERL_LARGE_TUPLE_EXT:
ei_decode_tuple_header(x->buff, &x->index, &arity);
for(i=0;i<arity;i++) {
dump_eterm(x);
}
break;
case ERL_LIST_EXT:
case ERL_NIL_EXT:
ei_decode_list_header(x->buff, &x->index, &arity);
if (arity == 0) {
uwsgi_log("nil value\n");
break;
}
for(i=0;i<arity+1;i++) {
dump_eterm(x);
}
break;
case ERL_BINARY_EXT:
binary = uwsgi_malloc(esize);
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
uwsgi_log("binary data of %d bytes\n", bin_size);
free(binary);
break;
default:
uwsgi_log("ignored...\n");
ei_skip_term(x->buff, &x->index);
break;
}
}
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
int etype, esize;
int arity;
char *gen_call;
char *module;
char *call;
char buffer[0xffff];
char *argv[256] ;
uint16_t argvs[256] ;
int argc = 0;
uint16_t ret;
ei_x_buff xr;
erlang_ref eref;
ei_get_type(x->buff, &x->index, &etype, &esize);
#ifdef UWSGI_DEBUG
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
#endif
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
ei_decode_tuple_header(x->buff, &x->index, &arity);
#ifdef UWSGI_DEBUG
uwsgi_log("rpc arity %d\n", arity);
#endif
if (arity != 3) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
gen_call = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, gen_call);
}
else {
ei_decode_string(x->buff, &x->index, gen_call);
}
#ifdef UWSGI_DEBUG
uwsgi_log("gen call = %s\n", gen_call);
#endif
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_SMALL_TUPLE_EXT) return ;
ei_decode_tuple_header(x->buff, &x->index, &arity);
if (arity != 2) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
ei_skip_term(x->buff, &x->index);
ei_get_type(x->buff, &x->index, &etype, &esize);
ei_decode_ref(x->buff, &x->index, &eref);
ei_get_type(x->buff, &x->index, &etype, &esize);
module = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, module);
}
else {
ei_decode_string(x->buff, &x->index, module);
}
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_SMALL_TUPLE_EXT) return ;
ei_decode_tuple_header(x->buff, &x->index, &arity);
#ifdef UWSGI_DEBUG
uwsgi_log("arity: %d\n", arity);
#endif
if (arity != 5) return ;
ei_get_type(x->buff, &x->index, &etype, &esize);
char *method = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, method);
}
else {
ei_decode_string(x->buff, &x->index, method);
}
if (strcmp(method, "call")) return;
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
module = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, module);
}
else {
ei_decode_string(x->buff, &x->index, module);
}
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
call = uwsgi_malloc(esize);
if (etype == ERL_ATOM_EXT) {
ei_decode_atom(x->buff, &x->index, call);
}
else {
ei_decode_string(x->buff, &x->index, call);
}
#ifdef UWSGI_DEBUG
uwsgi_log("RPC %s %s\n", module, call);
#endif
ei_get_type(x->buff, &x->index, &etype, &esize);
if (etype == ERL_ATOM_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
else if (etype == ERL_STRING_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
#ifdef UWSGI_DEBUG
uwsgi_log("buffer: %.*s\n", ret, buffer);
#endif
ei_x_new_with_version(&xr);
ei_x_encode_tuple_header(&xr, 2);
//ei_x_encode_atom(&xr, "rex");
ei_x_encode_ref(&xr, &eref);
ei_x_encode_string_len(&xr, buffer, ret);
uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index));
//uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index));
}
void erlang_loop(int id, void *data) {
ErlConnect econn;
//ErlMessage em;
erlang_msg em;
int fd;
int eversion;
ei_x_buff x, xr;
ei_x_new(&x);
ei_x_new(&xr);
/*
int fd0 = ei_connect(&uerl.cnode, "anothernode@maverick64");
uwsgi_log("fd0: %d\n", fd0);
ei_x_encode_list_header(&x, 0);
ei_rpc_to(&uerl.cnode, fd0, "erlang", "node", x.buff, x.index);
ei_rpc_from(&uerl.cnode, fd0, 10000, &em, &xr);
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
xr.index = 0;
ei_decode_version(xr.buff, &xr.index, &eversion);
uwsgi_log("eversion: %d\n", eversion);
dump_eterm(&xr);
*/
for(;;) {
fd = ei_accept(&uerl.cnode, uerl.fd, &econn);
if (fd >= 0) {
for (;;) {
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
if (em.msgtype == ERL_TICK)
continue;
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
x.index = 0;
ei_decode_version(x.buff, &x.index, &eversion);
#ifdef UWSGI_DEBUG
uwsgi_log("eversion: %d\n", eversion);
#endif
if (!strcmp(em.toname, "rex")) {
uwsgi_erlang_rpc(fd, &em.from, &x);
}
else {
struct uwsgi_erlang_process *uep = uerl.uep;
while(uep) {
if (!strcmp(uep->name, em.toname)) {
if (uep->plugin) {
uep->plugin(uep->func, &x);
}
break;
}
uep = uep->next;
}
if (!uep) {
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
dump_eterm(&x);
}
}
/*
if (em.msgtype) {
dump_erl_obj(em.msg);
erl_free_compound(em.msg);
}
if (em.to) {
uwsgi_log("*** TO ***\n");
dump_erl_obj(em.to);
erl_free_compound(em.to);
}
if (em.from) {
uwsgi_log("*** FROM ***\n");
dump_erl_obj(em.from);
erl_free_compound(em.from);
}
*/
}
else {
break;
}
}
close(fd);
}
}
}
int erlang_init() {
char *host;
struct sockaddr_in sin;
socklen_t slen = sizeof(struct sockaddr_in);
char *ip = NULL;
char *nodename;
struct in_addr addr;
uerl.lock = uwsgi_lock_init("erlang");
if (uerl.name) {
host = strchr(uerl.name, '@');
if (!host) {
if (ei_connect_init(&uerl.cnode, uerl.name, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
else {
nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0);
ip = uwsgi_resolve_ip(host+1);
if (ip) {
#ifdef UWSGI_DEBUG
uwsgi_log("ip: %s\n", ip);
#endif
addr.s_addr = inet_addr(ip);
if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
else {
if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
free(nodename);
}
if (ip) {
uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL);
}
else {
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
}
if (uerl.fd < 0) {
exit(1);
}
if (getsockname(uerl.fd, (struct sockaddr *) &sin, &slen)) {
uwsgi_error("getsockname()");
exit(1);
}
if (ei_publish(&uerl.cnode, ntohs(sin.sin_port)) < 0) {
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
exit(1);
}
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
}
return 0;
}
struct uwsgi_plugin erlang_plugin = {
.name = "erlang",
.options = erlang_options,
.init = erlang_init,
};
+24
View File
@@ -0,0 +1,24 @@
#include <ei.h>
struct uwsgi_erlang_process {
char name[0xff];
void (*plugin)(void *, ei_x_buff *);
void *func;
struct uwsgi_erlang_process *next;
};
struct uwsgi_erlang {
ei_cnode cnode;
char *name;
char *cookie;
int fd;
void *lock;
struct uwsgi_erlang_process *uep;
};
+15
View File
@@ -0,0 +1,15 @@
import os
NAME='erlang'
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
CFLAGS = [ '-I' + includedir ]
LDFLAGS = [ '-L' + libpath ]
LIBS = ['-lei']
GCC_LIST = ['erlang']
+13 -271
View File
@@ -2,7 +2,7 @@
/*
Soon before official Go 1.1, we understood supporting Go in a fork() heavy
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
environment was not blessed by the Go community.
Instead of completely dropping support for Go, we studied how the gccgo project works and we
@@ -16,31 +16,8 @@
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
manages mules, spoolers and workers)
The plugin implements goroutines too.
On startup a goroutine is created for each socket and signals file descriptors.
For every request a new goroutine is created too.
The wsgi_request * structure is attached to the "closure" field of the goroutine (PAY ATTENTION)
even if the loop engine makes use of the async mode, pthreads could be spawned all over the place.
For such a reason a mutex is created avoiding the global wsgi_req structures to be clobbered
Contrary to the standard way Go apps are deployed, the plugin supports loading shared libraries.
While this is a common approach in other environments, the Go community prefers monolithic binaries.
As always, choose the model that best suite for you. Eventually building a single uWSGI binary with your Go
app embedded is pretty easy:
CFLAGS=-DUWSGI_GCCGO_MONOLITHIC UWSGI_ADDITIONAL_SOURCES=t/go/uploadtest.go UWSGI_PROFILE=gccgo make
or you can add the following two directives in a build profile:
cflags = -DUWSGI_GCCGO_MONOLITHIC
additional_sources = t/go/uploadtest.go
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
from your apps are native goroutines)
*/
@@ -48,29 +25,25 @@ extern struct uwsgi_server uwsgi;
struct uwsgi_plugin gccgo_plugin;
struct uwsgi_gccgo{
// 1 if a main is loaded
int initialized;
struct uwsgi_string_list *libs;
char *args;
pthread_mutex_t wsgi_req_lock;
} ugccgo;
/*
shortcut for enabling the "goroutines" loop engine
*/
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
// set loop engine
uwsgi.loop = "goroutines";
}
*/
struct uwsgi_option uwsgi_gccgo_options[] = {
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of max goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -78,46 +51,27 @@ struct uwsgi_option uwsgi_gccgo_options[] = {
// no_split_stack is the key to avoid crashing !!!
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
// initialize runtime
void runtime_check(void);
void runtime_args(int, char **);
void runtime_osinit(void);
void runtime_schedinit(void);
void *__go_go(void *, void *);
void runtime_main(void);
void runtime_mstart(void *);
// spawn a goroutine
void *__go_go(void *, void *);
// api functions exposed
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
// for goroutines
void runtime_netpollinit(void);
void runtime_starttheworld(void);
void *runtime_pollOpen(int) __asm__ ("net.runtime_pollOpen");
void runtime_pollClose(void *) __asm__ ("net.runtime_pollClose");
void runtime_pollUnblock(void *) __asm__ ("net.runtime_pollUnblock");
int runtime_pollWait(void *, int) __asm__ ("net.runtime_pollWait");
void runtime_pollSetDeadline(void *, int64_t, int) __asm__ ("net.runtime_pollSetDeadline");
void runtime_gosched(void);
// the current goroutine
void *runtime_g(void);
// we use the closure field to store the wsgi_req structure
void __go_set_closure(void *);
void *__go_get_closure(void);
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
static void mainstart(void *arg __attribute__((unused))) {
runtime_main();
}
#ifndef UWSGI_GCCGO_MONOLITHIC
void uwsgigo_main_main(void) __asm__ ("main.main");
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
#endif
void (*uwsgigo_hook_init)(void);
void (*uwsgigo_hook_main)(void);
@@ -148,14 +102,6 @@ int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *han
}
static void uwsgi_gccgo_initialize() {
if (uwsgi.threads > 1) {
uwsgi_log("!!! the Go runtime cannot work in multithreaded modes !!!\n");
exit(1);
}
#ifdef UWSGI_GCCGO_MONOLITHIC
uwsgigo_hook_init = dlsym(RTLD_DEFAULT, "__go_init_main");
uwsgigo_hook_main = dlsym(RTLD_DEFAULT, "main.main");
#endif
struct uwsgi_string_list *usl = ugccgo.libs;
while(usl) {
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
@@ -163,16 +109,9 @@ static void uwsgi_gccgo_initialize() {
uwsgi_log("unable to open go shared library: %s\n", dlerror());
exit(1);
}
void *g_init = dlsym(handle, "__go_init_main");
void *g_main = dlsym(handle, "main.main");
if (g_init && g_main) {
uwsgigo_hook_init = g_init;
uwsgigo_hook_main = g_main;
uwsgi_log("[uwsgi-gccgo] loaded %s as main\n", usl->value);
}
else {
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
}
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
uwsgigo_hook_main = dlsym(handle, "main.main");
usl = usl->next;
}
@@ -180,8 +119,6 @@ static void uwsgi_gccgo_initialize() {
return;
}
ugccgo.initialized = 1;
// Go runtime initialization
int argc = 0;
if (ugccgo.args) {
@@ -194,7 +131,7 @@ static void uwsgi_gccgo_initialize() {
}
runtime_check();
if (argc > 0) {
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 2));
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
char *argv_list = uwsgi_str(ugccgo.args);
char *p, *ctx = NULL;
int n = 0;
@@ -208,7 +145,6 @@ static void uwsgi_gccgo_initialize() {
char *argv[2] = {0,0};
runtime_args(0, argv);
}
runtime_osinit();
runtime_schedinit();
__go_go(mainstart, NULL);
@@ -217,10 +153,6 @@ static void uwsgi_gccgo_initialize() {
}
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
if (!ugccgo.initialized) {
uwsgi_log("!!! Go runtime not initialized !!!\n");
goto end;
}
/* Standard GO request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log("Empty GO request. skip.\n");
@@ -238,7 +170,6 @@ static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
i++;
}
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
end:
return UWSGI_OK;
}
@@ -247,204 +178,15 @@ static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
}
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
if (!ugccgo.initialized) return -1;
uwsgigo_signal_handler(handler, signum);
return 0;
}
#define free_req_queue pthread_mutex_lock(&ugccgo.wsgi_req_lock);uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req; pthread_mutex_unlock(&ugccgo.wsgi_req_lock)
static void uwsgi_gccgo_request_goroutine(void *arg) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg;
// map wsgi_req to the goroutine
__go_set_closure(wsgi_req);
int ret,status;
for(;;) {
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
wsgi_req->switches++;
if (ret <= 0) {
goto end;
}
retry:
status = wsgi_req->socket->proto(wsgi_req);
if (status < 0) {
goto end;
}
else if (status == 0) {
break;
}
if (uwsgi_is_again()) continue;
goto retry;
}
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
goto end;
}
wsgi_req->switches++;
// yield
runtime_gosched();
}
end:
uwsgi_close_request(wsgi_req);
free_req_queue;
}
static struct wsgi_request *uwsgi_gccgo_current_wsgi_req(void) {
return (struct wsgi_request *) __go_get_closure();
}
static int uwsgi_gccgo_wait_read_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'r');
int ret = runtime_pollWait(pdesc, 'r');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
static int uwsgi_gccgo_wait_write_hook(int fd, int timeout) {
void *pdesc = runtime_pollOpen(fd);
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
runtime_pollSetDeadline(pdesc, t, 'w');
int ret = runtime_pollWait(pdesc, 'w');
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
if (ret == 0) return 1;
// timeout
if (ret == 2) return 0;
return -1;
}
/*
this goroutine manages signals
*/
static void uwsgi_gccgo_signal_goroutine(void *arg) {
int *fd = (int *) arg;
void *pdesc = runtime_pollOpen(*fd);
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
uwsgi_receive_signal(*fd, "worker", uwsgi.mywid);
if (uwsgi_is_again()) continue;
goto retry;
}
}
static void uwsgi_gccgo_socket_goroutine(void *arg) {
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) arg;
struct wsgi_request *wsgi_req = NULL;
void *pdesc = runtime_pollOpen(uwsgi_sock->fd);
// wait for connection
for(;;) {
runtime_pollWait(pdesc, 'r');
retry:
pthread_mutex_lock(&ugccgo.wsgi_req_lock);
wsgi_req = find_first_available_wsgi_req();
pthread_mutex_unlock(&ugccgo.wsgi_req_lock);
if (wsgi_req == NULL) {
uwsgi_async_queue_is_full(uwsgi_now());
// try rescheduling...
// we do not use runtime_gosched() as we want to call the netpoll loop too
runtime_pollUnblock(pdesc);
runtime_pollClose(pdesc);
pdesc = runtime_pollOpen(uwsgi_sock->fd);
continue;
}
// fill wsgi_request structure
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
free_req_queue;
if (uwsgi_is_again()) continue;
goto retry;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
}
// spawn the new goroutine
__go_go(uwsgi_gccgo_request_goroutine, wsgi_req);
goto retry;
}
}
static void uwsgi_gccgo_loop() {
if (!ugccgo.initialized) {
uwsgi_log("no go.main code loaded !!!\n");
exit(1);
}
// initialize the log protecting the wsgi_req structures
pthread_mutex_init(&ugccgo.wsgi_req_lock, NULL);
// hooks
uwsgi.current_wsgi_req = uwsgi_gccgo_current_wsgi_req;
uwsgi.wait_write_hook = uwsgi_gccgo_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_gccgo_wait_read_hook;
// ininitialize Go I/O loop
runtime_netpollinit();
if (uwsgi.signal_socket > -1) {
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.signal_socket);
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.my_signal_socket);
}
// start a goroutine for each socket
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (!uwsgi_sock->next) {
uwsgi_gccgo_socket_goroutine(uwsgi_sock);
}
else {
__go_go(uwsgi_gccgo_socket_goroutine, uwsgi_sock);
}
uwsgi_sock = uwsgi_sock->next;
}
// never here
}
static void uwsgi_gccgo_on_load() {
uwsgi_register_loop( (char *) "go", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutine", uwsgi_gccgo_loop);
uwsgi_register_loop( (char *) "goroutines", uwsgi_gccgo_loop);
}
struct uwsgi_plugin gccgo_plugin = {
.name = "gccgo",
.modifier1 = 11,
.options = uwsgi_gccgo_options,
.on_load = uwsgi_gccgo_on_load,
//.on_load = uwsgi_gccgo_on_load,
.request = uwsgi_gccgo_request,
.after_request = uwsgi_gccgo_after_request,
.post_fork = uwsgi_gccgo_initialize,
+2 -45
View File
@@ -1,12 +1,5 @@
package uwsgi
/*
this is a very low-level module, full of performance hacks
do not take it as a good example of go coding...
*/
import (
"strings"
"net/http"
@@ -27,27 +20,17 @@ func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
//extern uwsgi_gccgo_helper_register_signal
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
//extern uwsgi_cache_magic_get
func uwsgi_cache_magic_get(*byte, uint16, *uint64, *uint64, *byte) *byte;
//extern __go_byte_array_to_string
func __go_byte_array_to_string(*byte, int) string
//extern free
func free(* byte)
var uwsgi_signals_gc [256]func(uint8)
var uwsgi_env_gc map[interface{}]interface{}
func Env(wsgi_req *interface{}) *map[string]string {
var env map[string]string
env = make(map[string]string)
uwsgi_env_gc[wsgi_req] = &env
return &env
}
func EnvAdd(env *map[string]string, k *byte, kl uint16, v *byte, vl uint16) {
s_k := __go_byte_array_to_string(k, int(kl))
s_v := __go_byte_array_to_string(v, int(vl))
(*env)[ s_k ] = s_v
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
}
type ResponseWriter struct {
@@ -115,13 +98,9 @@ func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
http.DefaultServeMux.ServeHTTP(&w, httpReq)
}
delete(uwsgi_env_gc, wsgi_req)
}
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
if (receiver == "") {
receiver = "worker"
}
var b []byte = []byte(receiver)
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
return false
@@ -130,32 +109,10 @@ func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
return true
}
// get an item from the cache
func CacheGet(key string, cache string) string {
var b_key []byte = []byte(key)
var v_len uint64 = 0
var expires uint64 = 0
var value *byte
if (cache == "") {
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, nil)
} else {
b_cache := []byte(cache)
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, &b_cache[0])
}
ret := __go_byte_array_to_string(value, int(v_len))
free(value)
return ret
}
func SignalHandler(handler func(uint8), signum uint8) {
handler(signum)
}
func Run() {
uwsgi_env_gc = make(map[interface{}]interface{})
uwsgi_takeover()
}
-13
View File
@@ -1,13 +0,0 @@
import os
NAME='gccgo'
CFLAGS = ['-g']
LDFLAGS = []
LIBS = ['-lgo']
GCC_LIST = ['gccgo_plugin', 'uwsgi.go']
def post_build(config):
if os.path.exists('plugins/gccgo/uwsgi.go.o'):
if os.system("objcopy -j .go_export plugins/gccgo/uwsgi.go.o plugins/gccgo/uwsgi.gox") != 0:
os._exit(1)
print("*** uwsgi.gox available in %s/plugins/gccgo ***" % os.getcwd())
+7 -10
View File
@@ -8,8 +8,8 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
if (uwsgi.socket_timeout < 30) {
uwsgi.socket_timeout = 30;
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
}
// set loop engine
uwsgi.loop = "gevent";
@@ -210,8 +210,8 @@ edge:
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.harakiri_options.workers > 0) {
set_harakiri(uwsgi.harakiri_options.workers);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// hack to easily pass wsgi_req pointer to the greenlet
@@ -257,7 +257,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
for(;;) {
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
wsgi_req->switches++;
if (ret <= 0) {
@@ -291,9 +291,7 @@ request:
}
end:
if (greenlet_switch) {
Py_DECREF(greenlet_switch);
}
Py_DECREF(greenlet_switch);
end2:
Py_DECREF(current_greenlet);
@@ -349,7 +347,7 @@ static void gevent_loop() {
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
}
if (uwsgi.socket_timeout < 30) {
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
uwsgi_log("!!! Running gevent with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
}
@@ -361,7 +359,6 @@ static void gevent_loop() {
uwsgi.wait_write_hook = uwsgi_gevent_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_gevent_wait_read_hook;
uwsgi.wait_milliseconds_hook = uwsgi_gevent_wait_milliseconds_hook;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
-1
View File
@@ -2,7 +2,6 @@
int uwsgi_gevent_wait_write_hook(int, int);
int uwsgi_gevent_wait_read_hook(int, int);
int uwsgi_gevent_wait_milliseconds_hook(int);
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
-39
View File
@@ -98,42 +98,3 @@ int uwsgi_gevent_wait_read_hook(int fd, int timeout) {
return 1;
}
int uwsgi_gevent_wait_milliseconds_hook(int timeout) {
PyObject *ret = NULL;
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "f", ((double) timeout)/1000.0);
if (!timer) return -1;
PyObject *current_greenlet = GET_CURRENT_GREENLET;
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
if (!ret) {
Py_DECREF(current); Py_DECREF(current_greenlet);
Py_DECREF(timer);
return -1;
}
Py_DECREF(ret);
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
if (!ret) {
ret = PyObject_CallMethod(timer, "stop", NULL);
if (ret) { Py_DECREF(ret); }
Py_DECREF(current); Py_DECREF(current_greenlet);
Py_DECREF(timer);
return -1;
}
Py_DECREF(ret);
if (ret == timer) {
ret = PyObject_CallMethod(timer, "stop", NULL);
if (ret) { Py_DECREF(ret); }
Py_DECREF(current); Py_DECREF(current_greenlet);
Py_DECREF(timer);
return 0;
}
return -1;
}
+5 -1
View File
@@ -1,6 +1,10 @@
#include <uwsgi.h>
#include <api/glfs.h>
#ifdef UWSGI_MATHEVAL
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
#endif
extern struct uwsgi_server uwsgi;
/*
@@ -200,7 +204,7 @@ static void uwsgi_glusterfs_add_mountpoint(char *arg, size_t arg_len) {
static void uwsgi_glusterfs_setup() {
if (!uglusterfs.timeout) {
uglusterfs.timeout = uwsgi.socket_timeout;
uglusterfs.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
struct uwsgi_string_list *usl = uglusterfs.mountpoints;
+116
View File
@@ -0,0 +1,116 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
void (*uwsgi_go_helper_post_fork_c)();
void (*uwsgi_go_helper_post_init_c)();
void * (*uwsgi_go_helper_env_new_c)(struct wsgi_request *);
void (*uwsgi_go_helper_env_add_c)(void *, char *, int, char *, int);
void (*uwsgi_go_helper_request_c)(void *, struct wsgi_request *);
int (*uwsgi_go_helper_signal_handler_c)(int, void *);
void (*uwsgi_go_helper_run_core_c)(int);
char *(*uwsgi_go_helper_version_c)();
void uwsgi_go_post_fork() {
uwsgi_go_helper_post_fork_c();
}
void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
// set async mode
uwsgi_opt_set_int(opt, value, &uwsgi.async);
// set loop engine
uwsgi.loop = "goroutines";
}
struct uwsgi_option uwsgi_go_options[] = {
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
{0, 0, 0, 0, 0, 0, 0},
};
#define uwsgi_go_get_symbol(x) x ## _c = dlsym(RTLD_DEFAULT, #x);\
if (!x ## _c) {\
uwsgi_log("[uwsgi-go] unable to load " #x " function\n"); exit(1);\
}
static int uwsgi_go_init() {
// build the functions table
uwsgi_go_get_symbol(uwsgi_go_helper_post_fork)
uwsgi_go_get_symbol(uwsgi_go_helper_post_init)
uwsgi_go_get_symbol(uwsgi_go_helper_env_new)
uwsgi_go_get_symbol(uwsgi_go_helper_env_add)
uwsgi_go_get_symbol(uwsgi_go_helper_request)
uwsgi_go_get_symbol(uwsgi_go_helper_signal_handler)
uwsgi_go_get_symbol(uwsgi_go_helper_run_core)
uwsgi_go_get_symbol(uwsgi_go_helper_version)
uwsgi_log("Go version \"%s\" initialized\n", uwsgi_go_helper_version_c());
return 0;
}
static int uwsgi_go_request(struct wsgi_request *wsgi_req) {
/* Standard GO request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log("Empty GO request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
wsgi_req->async_environ = uwsgi_go_helper_env_new_c(wsgi_req);
int i;
for(i=0;i<wsgi_req->var_cnt;i++) {
uwsgi_go_helper_env_add_c(wsgi_req->async_environ, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
i++;
}
uwsgi_go_helper_request_c(wsgi_req->async_environ, wsgi_req);
return UWSGI_OK;
}
static void uwsgi_go_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static int uwsgi_go_signal_handler(uint8_t signum, void *handler) {
return uwsgi_go_helper_signal_handler_c((int)signum, handler);
}
static void goroutines_loop() {
int i;
for (i = 1; i < uwsgi.async; i++) {
uwsgi_go_helper_run_core_c(i);
}
simple_loop_run_int(0);
}
static void uwsgi_go_on_load() {
uwsgi_register_loop("goroutines", goroutines_loop);
}
static void uwsgi_go_call_init_hook() {
if (uwsgi_go_helper_post_init_c) {
uwsgi_go_helper_post_init_c();
}
}
struct uwsgi_plugin go_plugin = {
.name = "go",
.modifier1 = 11,
.request = uwsgi_go_request,
.after_request = uwsgi_go_after_request,
.preinit_apps = uwsgi_go_call_init_hook,
.post_fork = uwsgi_go_post_fork,
.init = uwsgi_go_init,
.signal_handler = uwsgi_go_signal_handler,
.on_load = uwsgi_go_on_load,
.options = uwsgi_go_options,
};
+420
View File
@@ -0,0 +1,420 @@
/*
uWSGI go integration package
*/
package uwsgi
/*
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// commodity functions to simulate argc/argv
static char ** uwsgi_go_helper_create_argv(int len) {
return uwsgi_calloc(sizeof(char *) * len);
}
static void uwsgi_go_helper_set_argv(char **argv, int pos, char *item) {
argv[pos] = item;
}
*/
import "C"
import (
"os"
"net/http"
"net/http/cgi"
"unsafe"
"strings"
"strconv"
"io"
"runtime"
)
// this stores the modifier used by the go plugin (default 11)
var uwsgi_modifier1 int = -1;
// the following to objects are used to implement a sort of GC to avoid request environ and
// signal handlers to be garbage collected
var uwsgi_env_gc = make(map[*C.struct_wsgi_request](*map[string]string))
var uwsgi_signals_gc = make([]*func(int), 256)
var uwsgi_default_request_handler func(http.ResponseWriter, *http.Request) = nil
var uwsgi_default_handler http.Handler = nil
var uwsgi_post_fork_hook func() = nil
var uwsgi_post_init_hook func() = nil
/*
uWSGI api functions
*/
// raise a uWSGI signal
func Signal(signum int) {
if C.uwsgi.master_process == 0 {
return
}
C.uwsgi_signal_send(C.uwsgi.signal_socket, C.uint8_t(signum))
}
// set a user lock
func Lock(num int) {
C.uwsgi_user_lock(C.int(num));
}
// unset a user lock
func Unlock(num int) {
C.uwsgi_user_unlock(C.int(num));
}
// add a timer
func AddTimer(signum int, seconds int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_add_timer(C.uint8_t(signum), C.int(seconds))) == 0 {
return true
}
return false
}
// add a red black timer
func AddRbTimer(signum int, seconds int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_signal_add_rb_timer(C.uint8_t(signum), C.int(seconds), C.int(0))) == 0 {
return true
}
return false
}
// check if a signal is registered
func SignalRegistered(signum int) bool {
if C.uwsgi.master_process == 0 {
return false
}
if int(C.uwsgi_signal_registered(C.uint8_t(signum))) == 0 {
return false
}
return true
}
// register a signal
func RegisterSignal(signum int, who string, handler func(int)) bool {
if C.uwsgi.master_process == 0 {
return false
}
if uwsgi_modifier1 == -1 {
c_go := C.CString("go")
defer C.free(unsafe.Pointer(c_go))
uwsgi_modifier1 = int(C.uwsgi_plugin_modifier1(c_go))
if uwsgi_modifier1 == -1 {
return false
}
}
c_who := C.CString(who)
defer C.free(unsafe.Pointer(c_who))
if int(C.uwsgi_register_signal(C.uint8_t(signum), c_who, unsafe.Pointer(&handler), C.uint8_t(uwsgi_modifier1))) == 0 {
uwsgi_signals_gc[signum] = &handler
return true
}
return false
}
func Alarm(alarm string, msg string) {
a := C.CString(alarm)
defer C.free(unsafe.Pointer(a))
m := C.CString(msg)
defer C.free(unsafe.Pointer(m))
ml := len(msg)
C.uwsgi_alarm_trigger(a, m, C.size_t(ml))
}
// get an item from the cache
func CacheGet(key string, cache string) []byte {
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
var vl C.uint64_t = C.uint64_t(0)
c := (*C.char)(nil)
if len(cache) > 0 {
c = C.CString(cache)
defer C.free(unsafe.Pointer(c))
}
var p []byte
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, (*C.uint64_t)(nil), c)
if c_value != nil {
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
} else {
p = nil
}
return p
}
// remove an intem from the cache
func CacheDel(key string, cache string) bool {
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
c := (*C.char)(nil)
if len(cache) > 0 {
c = C.CString(cache)
defer C.free(unsafe.Pointer(c))
}
if int(C.uwsgi_cache_magic_del(k, C.uint16_t(kl), c)) < 0 {
return false;
}
return true
}
// check if an item exists in the cache
func CacheExists(key string, cache string) bool {
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
c := (*C.char)(nil)
if len(cache) > 0 {
c = C.CString(cache)
defer C.free(unsafe.Pointer(c))
}
if int(C.uwsgi_cache_magic_exists(k, C.uint16_t(kl), c)) == 0 {
return false;
}
return true
}
// put an item in the cache
func CacheSetFlags(key string, p []byte, expires uint64, flags int, cache string) bool {
k := C.CString(key)
defer C.free(unsafe.Pointer(k))
kl := len(key)
v := unsafe.Pointer(&p[0])
vl := len(p)
c := (*C.char)(nil)
if len(cache) > 0 {
c = C.CString(cache)
defer C.free(unsafe.Pointer(c))
}
if int(C.uwsgi_cache_magic_set(k, C.uint16_t(kl), (*C.char)(v), C.uint64_t(vl), C.uint64_t(expires), C.uint64_t(flags), c)) < 0 {
return false;
}
return true
}
func CacheSet(key string, p []byte, expires uint64, cache string) bool {
return CacheSetFlags(key, p, expires, 0, cache);
}
func CacheUpdate(key string, p []byte, expires uint64, cache string) bool {
return CacheSetFlags(key, p, expires, 2, cache);
}
// get the current worker id
func WorkerId() int {
return int(C.uwsgi.mywid)
}
// get the current mule id
func MuleId() int {
return int(C.uwsgi.muleid)
}
// get the current logsize (if available)
func LogSize() int64 {
return int64(C.uwsgi.shared.logsize)
}
func PostFork(hook func()) {
uwsgi_post_fork_hook = hook
}
func PostInit(hook func()) {
uwsgi_post_init_hook = hook
}
func RequestHandler(hook func(http.ResponseWriter, *http.Request)) {
uwsgi_default_request_handler = hook
}
func Handler(handler http.Handler) {
uwsgi_default_handler = handler
}
/*
C -> go and go -> C bridges
*/
//export uwsgi_go_helper_post_fork
func uwsgi_go_helper_post_fork() {
if uwsgi_post_fork_hook != nil {
uwsgi_post_fork_hook()
}
}
//export uwsgi_go_helper_post_init
func uwsgi_go_helper_post_init() {
if uwsgi_post_init_hook != nil {
uwsgi_post_init_hook()
}
}
//export uwsgi_go_helper_env_new
func uwsgi_go_helper_env_new(wsgi_req *C.struct_wsgi_request) *map[string]string {
var env map[string]string
env = make(map[string]string)
// track env to avoid it being garbage collected...
uwsgi_env_gc[wsgi_req] = &env
return &env
}
//export uwsgi_go_helper_env_add
func uwsgi_go_helper_env_add(env *map[string]string, k *C.char, kl C.int, v *C.char, vl C.int) {
var mk string = C.GoStringN(k, kl)
var mv string = C.GoStringN(v, vl)
(*env)[mk] = mv
}
/*
http.* implementations
*/
type ResponseWriter struct {
r *http.Request
wsgi_req *C.struct_wsgi_request
headers http.Header
wroteHeader bool
}
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
if !w.wroteHeader {
w.WriteHeader(http.StatusOK)
}
m := len(p)
C.uwsgi_response_write_body_do(w.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m))
return m+n, err
}
// TODO fix it !!!
func (w *ResponseWriter) WriteHeader(status int) {
codestring := http.StatusText(status)
var tmp_buf string = strconv.Itoa(status) + " " + codestring
c_status := C.CString(tmp_buf)
defer C.free(unsafe.Pointer(c_status))
C.uwsgi_response_prepare_headers(w.wsgi_req, c_status, C.uint16_t(len(tmp_buf)) )
if w.headers.Get("Content-Type") == "" {
w.headers.Set("Content-Type", "text/html; charset=utf-8")
}
for k := range w.headers {
hk_c := C.CString(k)
defer C.free(unsafe.Pointer(hk_c))
for _, v := range w.headers[k] {
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
v = strings.TrimSpace(v)
hv_c := C.CString(v)
defer C.free(unsafe.Pointer(hv_c))
C.uwsgi_response_add_header(w.wsgi_req, hk_c, C.uint16_t(len(k)), hv_c, C.uint16_t(len(v)))
}
}
w.wroteHeader = true
}
func (w *ResponseWriter) Header() http.Header {
return w.headers
}
type BodyReader struct {
wsgi_req *C.struct_wsgi_request
}
// there is no close in request body
func (br *BodyReader) Close() error {
return nil
}
func (br *BodyReader) Read(p []byte) (n int, err error) {
m := len(p)
var rlen C.ssize_t = C.ssize_t(0)
c_body := C.uwsgi_request_body_read(br.wsgi_req, C.ssize_t(m), &rlen)
if (c_body == C.uwsgi.empty) {
err = io.EOF;
return 0, err
} else if (c_body != nil) {
C.memcpy(unsafe.Pointer(&p[0]), unsafe.Pointer(c_body), C.size_t(rlen))
return int(rlen), err
}
err = io.ErrUnexpectedEOF
rlen = 0
return int(rlen), err
}
//export uwsgi_go_helper_request
func uwsgi_go_helper_request(env *map[string]string, wsgi_req *C.struct_wsgi_request) {
httpReq, err := cgi.RequestFromMap(*env)
if err != nil {
} else {
httpReq.Body = &BodyReader{wsgi_req}
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
if uwsgi_default_request_handler != nil {
uwsgi_default_request_handler(&w, httpReq)
} else if uwsgi_default_handler != nil {
uwsgi_default_handler.ServeHTTP(&w, httpReq)
} else {
http.DefaultServeMux.ServeHTTP(&w, httpReq)
}
}
}
//export uwsgi_go_helper_version
func uwsgi_go_helper_version() *C.char {
return C.CString(runtime.Version())
}
//export uwsgi_go_helper_signal_handler
func uwsgi_go_helper_signal_handler(signum int, handler *func(int)) int {
(*handler)(signum)
return 0;
}
//export uwsgi_go_helper_run_core
func uwsgi_go_helper_run_core(core_id int) {
go C.simple_loop_run_int(C.int(core_id))
}
/*
the main function, running the uWSGI server via libuwsgi.so
*/
func Run() {
argc := len(os.Args) + 1
argv := C.uwsgi_go_helper_create_argv(C.int(argc))
for i, s := range os.Args {
C.uwsgi_go_helper_set_argv(argv, C.int(i), C.CString(s))
}
C.uwsgi_init(C.int(argc-1), argv, nil)
}
+28
View File
@@ -0,0 +1,28 @@
import os
NAME='go'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['go_plugin']
def post_build(config):
os.environ['GOPATH'] = 'plugins/go'
cflags = ['-I'+os.getcwd()]
for c in config.cflags:
if not c.startswith('-DUWSGI_BUILD_DATE') and not c.startswith('-DUWSGI_CFLAGS'):
cflags.append(c)
cflags.append('-Wno-implicit-function-declaration')
cflags.append('-Wno-implicit-int')
cflags.append('-Wno-unused-function')
cflags.append('-Wno-unused-variable')
os.environ['CGO_CFLAGS'] = ' '.join(cflags).replace('\\"', '')
base = os.path.dirname(config.get('bin_name'))
if not base:
base = "."
os.environ['CGO_LDFLAGS'] = '-L' + base + ' -L'+os.getcwd() + ' -luwsgi'
if os.system("go install uwsgi") != 0:
os._exit(1)
print("*** uwsgi go module available in $GOPATH %s/plugins/go ***" % os.getcwd())
+1 -1
View File
@@ -90,7 +90,7 @@ ssize_t uwsgi_graylog2_logger(struct uwsgi_logger *ul, char *message, size_t len
int rlen = snprintf(g2c.json_buf, MAX_GELF, "{ \"version\": \"1.0\", \"host\": \"%s\", \"short_message\": \"%.*s\", \"full_message\": \"%.*s\", \"timestamp\": %d, \"level\": 5, \"facility\": \"uWSGI-%s\" }",
g2c.host, truncated, g2c.escaped_buf, (int)g2c.escaped_len, g2c.escaped_buf, (int) uwsgi_now(), UWSGI_VERSION);
if (rlen > 0 && rlen < MAX_GELF) {
if (rlen > 0) {
if (compressBound((uLong) rlen) <= MAX_GELF) {
if (compress((Bytef *) ul->buf, &destLen, (Bytef *) g2c.json_buf, (uLong) rlen) == Z_OK) {
return sendto(ul->fd, ul->buf, destLen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
+4 -40
View File
@@ -16,22 +16,6 @@ static struct uwsgi_option greenlet_options[] = {
{ 0, 0, 0, 0, 0, 0, 0 }
};
struct wsgi_request *uwsgi_greenlet_current_wsgi_req(void) {
struct wsgi_request *wsgi_req = NULL;
PyObject *current_greenlet = (PyObject *)PyGreenlet_GetCurrent();
PyObject *py_wsgi_req = PyObject_GetAttrString(current_greenlet, "uwsgi_wsgi_req");
// not in greenlet
if (!py_wsgi_req) {
uwsgi_log("[BUG] current_wsgi_req NOT FOUND !!!\n");
goto end;
}
wsgi_req = (struct wsgi_request*) PyLong_AsLong(py_wsgi_req);
Py_DECREF(py_wsgi_req);
end:
Py_DECREF(current_greenlet);
return wsgi_req;
}
static void gil_greenlet_get() {
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
}
@@ -42,11 +26,9 @@ static void gil_greenlet_release() {
static PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
async_schedule_to_req_green();
Py_DECREF(ugl.gl[wsgi_req->async_id]);
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
@@ -64,7 +46,6 @@ static void greenlet_schedule_to_req() {
if (!uwsgi.wsgi_req->suspended) {
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
PyObject_SetAttrString((PyObject *)ugl.gl[id], "uwsgi_wsgi_req", PyLong_FromLong((long) uwsgi.wsgi_req));
uwsgi.wsgi_req->suspended = 1;
}
@@ -73,13 +54,7 @@ static void greenlet_schedule_to_req() {
uwsgi.p[modifier1]->suspend(NULL);
}
PyObject *ret = PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (!ret) {
PyErr_Print();
uwsgi_log_verbose("[BUG] unable to switch greenlet !!!\n");
exit(1);
}
Py_DECREF(ret);
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (uwsgi.p[modifier1]->resume) {
uwsgi.p[modifier1]->resume(NULL);
@@ -96,13 +71,7 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
}
PyObject *ret = PyGreenlet_Switch(ugl.main, NULL, NULL);
if (!ret) {
PyErr_Print();
uwsgi_log_verbose("[BUG] unable to switch greenlet !!!\n");
exit(1);
}
Py_DECREF(ret);
PyGreenlet_Switch(ugl.main, NULL, NULL);
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
}
@@ -124,10 +93,7 @@ static void greenlet_init_apps(void) {
up.gil_release = gil_greenlet_release;
}
// map wsgi_req to greenlet object
uwsgi.current_wsgi_req = uwsgi_greenlet_current_wsgi_req;
// blindly call it as the stackless gil engine is already set
// blindy call it as the stackless gil engine is already set
UWSGI_GET_GIL
@@ -135,9 +101,7 @@ static void greenlet_init_apps(void) {
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
ugl.main = PyGreenlet_GetCurrent();
Py_INCREF(ugl.main);
ugl.callable = PyCFunction_New(uwsgi_greenlet_request_method, NULL);
Py_INCREF(ugl.callable);
uwsgi_log("enabled greenlet engine\n");
uwsgi.schedule_to_main = greenlet_schedule_to_main;
+1 -1
View File
@@ -169,7 +169,7 @@ static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, si
ugm->timeout = atoi(ugm->timeout_str);
}
else {
ugm->timeout = uwsgi.socket_timeout;
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
if (ugm->prefix) {
-2
View File
@@ -54,8 +54,6 @@ struct uwsgi_option http_options[] = {
{"http-ss", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0},
{"http-harakiri", required_argument, 0, "enable http router harakiri", uwsgi_opt_set_int, &uhttp.cr.harakiri, 0},
{"http-stud-prefix", required_argument, 0, "expect a stud prefix (1byte family + 4/16 bytes address) on connections from the specified address", uwsgi_opt_add_addr_list, &uhttp.stud_prefix, 0},
{"http-uid", required_argument, 0, "drop http routr privileges to the specified uid", uwsgi_opt_uid, &uhttp.cr.uid, 0 },
{"http-gid", required_argument, 0, "drop http routr privileges to the specified gid", uwsgi_opt_gid, &uhttp.cr.gid, 0 },
{0, 0, 0, 0, 0, 0, 0},
};
+1 -1
View File
@@ -139,7 +139,7 @@ void uwsgi_opt_https2(char *opt, char *value, void *cr) {
#ifdef UWSGI_SPDY
spdyerror:
uwsgi_log("unable to initialize SPDY settings buffers\n");
uwsgi_log("unable to inizialize SPDY settings buffers\n");
exit(1);
#endif
}
+4 -5
View File
@@ -127,7 +127,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_rpc(JNIEnv *env, jclass c, jobject j_arg
char *argv[256];
uint16_t argvs[256];
jobject argvj[256];
uint64_t size = 0;
uint16_t size = 0;
size_t args = uwsgi_jvm_array_len(j_args);
if (args < 2) return NULL;
@@ -1277,7 +1277,7 @@ void uwsgi_jvm_release_bytearray(jobject o, char *str) {
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, o, (jbyte *)str, 0);
}
static uint64_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
jvalue args[1];
jobject str_array = (*ujvm_env)->NewObjectArray(ujvm_env, argc, ujvm.str_class, NULL);
if (!str_array) return 0;
@@ -1294,10 +1294,9 @@ static uint64_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t ar
return 0;
}
size_t rlen = uwsgi_jvm_strlen(ret);
if (rlen > 0) {
*buffer = uwsgi_malloc(rlen);
if (rlen <= 0xffff) {
char *b = uwsgi_jvm_str2c(ret);
memcpy(*buffer, b, rlen);
memcpy(buffer, b, rlen);
uwsgi_jvm_release_chars(ret, b);
uwsgi_jvm_local_unref(ret);
return rlen;
+1 -5
View File
@@ -7,11 +7,7 @@ JVM_INCPATH = None
JVM_LIBPATH = None
operating_system = os.uname()[0].lower()
try:
arch = os.environ['JVM_ARCH']
except:
arch = os.uname()[4].lower()
arch = os.uname()[4].lower()
if arch in ('i686', 'x86', 'x86_32'):
arch = 'i386'
+1 -2
View File
@@ -432,8 +432,7 @@ static uint16_t ldap_passwd_check(struct uwsgi_ldapauth_config *ulc, char *auth)
LDAPMessage *msg, *entry;
// use the minimal amount of memory
char *filter = uwsgi_malloc( strlen(ulc->login_attr) + (colon-auth) + strlen(ulc->filter) + 7);
ret = snprintf(filter, 1024, "(&(%s=%.*s)%s)", ulc->login_attr, (int) (colon-auth), auth, ulc->filter);
if (ret <= 0 || ret >= 1024) {
if (snprintf(filter, 1024, "(&(%s=%.*s)%s)", ulc->login_attr, (int) (colon-auth), auth, ulc->filter) <= 0) {
free(filter);
uwsgi_error("ldap_passwd_check()/sprintfn(filter)");
goto close;

Some files were not shown because too many files have changed in this diff Show More