mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6692276472 | ||
|
|
81c09a9c9c | ||
|
|
6a0a367ec3 | ||
|
|
bdf533d62b | ||
|
|
1aba0bc26c | ||
|
|
aac6e9a365 | ||
|
|
9da732d96c | ||
|
|
328ba43ed2 | ||
|
|
62d3253b02 | ||
|
|
e5ba01e707 | ||
|
|
82c25f7f8c | ||
|
|
8791866ea0 | ||
|
|
8f10b8fece | ||
|
|
0d28d210d4 | ||
|
|
2368a5a050 | ||
|
|
74a9b1b41d | ||
|
|
672c49e8eb | ||
|
|
225db32636 | ||
|
|
01541e4a50 | ||
|
|
357e260b45 | ||
|
|
a2513b1851 | ||
|
|
bbe8604054 | ||
|
|
58a33de7f7 | ||
|
|
ab7abc6a48 | ||
|
|
4986bdf202 | ||
|
|
11aaddac98 | ||
|
|
da9b2b4378 | ||
|
|
9771a98bc6 | ||
|
|
033ee5f4e9 | ||
|
|
1383163627 | ||
|
|
1d31b35c4f | ||
|
|
7b2cc757b2 | ||
|
|
68cddd1c2e | ||
|
|
b2a9fbbc5c | ||
|
|
0fcb13b9f1 | ||
|
|
938a22ce2e | ||
|
|
2df5dbfe52 | ||
|
|
feed0d0faa | ||
|
|
c8373d20a9 | ||
|
|
170267a04a | ||
|
|
bd5969db67 | ||
|
|
02256c013c | ||
|
|
89be9a0d4a | ||
|
|
4e57a6e145 | ||
|
|
784434ef3e | ||
|
|
91273b2301 | ||
|
|
2bcc85a99f | ||
|
|
b7e6da3392 | ||
|
|
d934270a27 | ||
|
|
ed5a268e1f | ||
|
|
95beaa0a86 | ||
|
|
0d3bf93c76 | ||
|
|
50fb43066a | ||
|
|
c33ec8ff56 | ||
|
|
e6afeec8af | ||
|
|
57b9bdb958 | ||
|
|
315bcb72c9 | ||
|
|
6b2460c02f | ||
|
|
35bc999a59 | ||
|
|
f00ad75e45 | ||
|
|
6bfe8e5b41 | ||
|
|
d7e8fd7d06 | ||
|
|
949a0c35d5 | ||
|
|
d193d5572f | ||
|
|
f79f7e44a7 | ||
|
|
26db55aafd | ||
|
|
9d405c6cb2 | ||
|
|
cceee511f2 | ||
|
|
e2024ed2fd | ||
|
|
add7e2ee0e | ||
|
|
0458aa8eb4 | ||
|
|
9ff6be783a | ||
|
|
14c558559b | ||
|
|
92c5dcb6f2 | ||
|
|
ae31f349f7 | ||
|
|
ce2846d04f | ||
|
|
7a6c9a5fe4 | ||
|
|
43c258ad48 | ||
|
|
8ba032adb2 | ||
|
|
1a61dfd4e0 | ||
|
|
8e150e77a8 | ||
|
|
729fa753fa | ||
|
|
bf6c552189 | ||
|
|
e9dc987a95 | ||
|
|
35d9a39100 | ||
|
|
a864c8d6ed | ||
|
|
c2df8a099e | ||
|
|
878e9cb9ba | ||
|
|
3612ea2186 | ||
|
|
81f0f93d96 | ||
|
|
c2d7b65145 | ||
|
|
6274e82cea | ||
|
|
66655c9429 | ||
|
|
f47c8553d5 | ||
|
|
f2802d3332 | ||
|
|
1a173c849f | ||
|
|
57d4cd9fc9 | ||
|
|
f6b9345716 | ||
|
|
792cd01320 | ||
|
|
03bc7d0399 | ||
|
|
ed8f0812d7 | ||
|
|
196dc45d0b | ||
|
|
f8ff906d1b | ||
|
|
bbf1b0eda5 | ||
|
|
6f811a4899 | ||
|
|
c66957d685 | ||
|
|
282b2d5ace | ||
|
|
6a73e3ae05 | ||
|
|
5856d410fd | ||
|
|
08d9de54f0 | ||
|
|
af1f98131a | ||
|
|
9cef49ec57 | ||
|
|
d60c6d50ec | ||
|
|
f3fdec2739 | ||
|
|
1a20f57b73 | ||
|
|
0fc74dac4d | ||
|
|
4117dd91fc | ||
|
|
508ca0df39 | ||
|
|
a50e356beb | ||
|
|
a0b7237083 | ||
|
|
08afa73e69 | ||
|
|
b386317921 | ||
|
|
2043127f22 | ||
|
|
c297a9415b | ||
|
|
f9f9f25a01 | ||
|
|
9001af1beb | ||
|
|
4b03f17186 | ||
|
|
3dbab36b91 | ||
|
|
056c890845 | ||
|
|
4f43cd74ad | ||
|
|
6585b7b13d | ||
|
|
e55048b574 | ||
|
|
570dcde654 | ||
|
|
3cb16ee29b | ||
|
|
bb453da5b5 | ||
|
|
1a93b68664 | ||
|
|
2ce2494a50 | ||
|
|
0a1e451289 | ||
|
|
8ef7819080 | ||
|
|
319ad13af2 | ||
|
|
fe28e90ae3 | ||
|
|
f604a0a533 | ||
|
|
4ab78d42a3 | ||
|
|
c631e7dae6 | ||
|
|
da8e88d638 | ||
|
|
4707d9250d | ||
|
|
d719960411 | ||
|
|
734818c995 | ||
|
|
a35335a820 | ||
|
|
aca4dbfbe7 | ||
|
|
b036029b32 | ||
|
|
52f3e757ed | ||
|
|
c4ce1cf7d8 | ||
|
|
48175d0759 | ||
|
|
2932168db7 |
@@ -44,3 +44,10 @@ a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
|
||||
@@ -1,3 +1,50 @@
|
||||
*** april 2012 ***
|
||||
|
||||
* 1.2 [20120430]
|
||||
|
||||
- PyPy support
|
||||
- Improved gevent support with threads
|
||||
- Python auto-reload subsystem
|
||||
- added --spooler-max-tasks
|
||||
- pthread robust mutexes support in Linux and Solaris
|
||||
- posix semaphores support in FreeBSD9
|
||||
- thread-safe ctime() reporting
|
||||
- interval support in cron subsystem
|
||||
- improved syslog support
|
||||
- better management of disconnected clients
|
||||
- static files serving improvements
|
||||
- another set of multithreading optimizations
|
||||
- minor fixes in the Rack plugin
|
||||
- Upstart socket-activation support
|
||||
|
||||
|
||||
*** march 2012 ***
|
||||
|
||||
* 1.1 [20120317]
|
||||
|
||||
- new options parser subsystem
|
||||
- improved php support
|
||||
- multiple spooler with multiprocessing
|
||||
- segmentation fault and floating point exceptions manager
|
||||
- never-swap option
|
||||
- zergpool plugin
|
||||
- perl/psgi multiple interpreters support
|
||||
- deadlock detector
|
||||
- pluggable cheaper algos
|
||||
- new internal routing susbsystem
|
||||
- preliminary support for config logic
|
||||
- log rotation infrastructure
|
||||
- support for paste loggers
|
||||
- threading improvements
|
||||
- plugins can now mapped to specific modifiers
|
||||
- <app> tag is deprecated (use mount option)
|
||||
- report startup time for apps
|
||||
- reintroduced expat support
|
||||
- reintroduced remote spooler plugin
|
||||
- various fastrouter optimizations
|
||||
- added ruby rvm support
|
||||
|
||||
|
||||
*** december 2011 ***
|
||||
|
||||
* 1.0 [20111230]
|
||||
|
||||
+29
-2
@@ -160,20 +160,35 @@ static int uwsgi_map_location(request_rec *r)
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static void log_err(const char *file, int line, request_rec *r,
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static void log_err(const char *file, int line, int ami, request_rec *r,
|
||||
apr_status_t status, const char *msg)
|
||||
{
|
||||
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, status, r, "uwsgi: %s", msg);
|
||||
#else
|
||||
static void log_err(const char *file, int line, request_rec *r,
|
||||
apr_status_t status, const char *msg)
|
||||
{
|
||||
|
||||
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static void log_debug(const char *file, int line, int ami, request_rec *r, const
|
||||
char *msg)
|
||||
{
|
||||
/*
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
|
||||
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
*/
|
||||
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#else
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
char *msg) {
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* buffered socket implementation (buckets are overkill) */
|
||||
@@ -412,7 +427,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
apr_table_t *t;
|
||||
apr_status_t rv = 0;
|
||||
apr_port_t port = 0;
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
GET_PORT(port, r->useragent_addr);
|
||||
#else
|
||||
GET_PORT(port, r->connection->remote_addr);
|
||||
#endif
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
|
||||
log_debug(APLOG_MARK,r, "sending headers");
|
||||
@@ -430,7 +449,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
|
||||
add_header(t, "REQUEST_METHOD", (char *) r->method);
|
||||
add_header(t, "QUERY_STRING", r->args ? r->args : "");
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
add_header(t, "SERVER_SOFTWARE", ap_get_server_description());
|
||||
#else
|
||||
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
|
||||
#endif
|
||||
add_header(t, "SERVER_ADMIN", r->server->server_admin);
|
||||
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
|
||||
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
|
||||
@@ -438,7 +461,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
add_header(t, "SERVER_PROTOCOL", r->protocol);
|
||||
|
||||
add_header(t, "REQUEST_URI", original_uri(r));
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
add_header(t, "REMOTE_ADDR", r->useragent_ip);
|
||||
#else
|
||||
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
|
||||
#endif
|
||||
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
|
||||
add_header(t, "REMOTE_USER", r->user);
|
||||
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
|
||||
|
||||
+12
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -37,11 +37,18 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
|
||||
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include "apr_strings.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "httpd.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_config.h"
|
||||
#include "http_log.h"
|
||||
#include "util_script.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
@@ -346,7 +353,11 @@ static int uwsgi_handler(request_rec *r) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->useragent_ip, &pkt_size) ;
|
||||
#else
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
#endif
|
||||
|
||||
//
|
||||
if (r->user) {
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
@@ -15,12 +15,12 @@ threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = true
|
||||
pcre = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = libxml2
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
plugins =
|
||||
|
||||
@@ -111,13 +111,14 @@ inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
uint64_t slot = uwsgi.cache_hashtable[hash_key];
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
uint64_t rounds = 0;
|
||||
|
||||
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
|
||||
|
||||
uci = &uwsgi.cache_items[slot];
|
||||
|
||||
// first round
|
||||
if (uci->djbhash != hash) goto cycle;
|
||||
if (uci->djbhash != hash) return 0;
|
||||
if (uci->keysize != keylen) goto cycle;
|
||||
if (memcmp(uci->key, key, keylen)) goto cycle;
|
||||
|
||||
@@ -127,7 +128,20 @@ cycle:
|
||||
while(uci->next) {
|
||||
slot = uci->next;
|
||||
uci = &uwsgi.cache_items[slot];
|
||||
if (uci->djbhash != hash) continue;
|
||||
rounds++;
|
||||
if (rounds > uwsgi.cache_max_items) {
|
||||
uwsgi_log("ALARM !!! cache-loop (and potential deadlock) detected slot = %llu prev = %llu next = %llu\n", uci->next, slot, uci->prev, uci->next);
|
||||
// terrible case: the whole uWSGI stack can deadlock, leaving only the master alive
|
||||
// if the master is avalable, trigger a brutal reload
|
||||
if (uwsgi.master_process) {
|
||||
kill(uwsgi.workers[0].pid, SIGTERM);
|
||||
}
|
||||
// otherwise kill the current worker (could be pretty useless...)
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (uci->djbhash != hash) return 0;
|
||||
if (uci->keysize != keylen) continue;
|
||||
if (!memcmp(uci->key, key, keylen)) return slot;
|
||||
}
|
||||
@@ -154,13 +168,14 @@ char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
|
||||
|
||||
uint64_t index = 0;
|
||||
struct uwsgi_cache_item *uci;
|
||||
int ret = -1;
|
||||
|
||||
index = uwsgi_cache_get_index(key, keylen);
|
||||
if (!index)
|
||||
index = uwsgi_cache_get_index(key, keylen);
|
||||
|
||||
if (index) {
|
||||
uci = &uwsgi.cache_items[index] ;
|
||||
uci->keysize = 0;
|
||||
@@ -177,9 +192,15 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
if (uci->prev) {
|
||||
uwsgi.cache_items[uci->prev].next = uci->next;
|
||||
}
|
||||
else {
|
||||
// set next as the new entry point (could be 0)
|
||||
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = uci->next;
|
||||
}
|
||||
|
||||
if (uci->next) {
|
||||
uwsgi.cache_items[uci->next].prev = uci->prev;
|
||||
}
|
||||
|
||||
if (!uci->prev && !uci->next) {
|
||||
// reset hashtable entry
|
||||
//uwsgi_log("!!! resetted hashtable entry !!!\n");
|
||||
@@ -188,6 +209,7 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
uci->djbhash = 0;
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
uci->expires = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -262,6 +284,9 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
ret = 0;
|
||||
// now put the value in the 16bit hashtable
|
||||
slot = uci->djbhash % 0xffff;
|
||||
// reset values
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
|
||||
if (uwsgi.cache_hashtable[slot] == 0) {
|
||||
uwsgi.cache_hashtable[slot] = index;
|
||||
|
||||
@@ -40,7 +40,7 @@ void cluster_setup() {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure(-1);
|
||||
uwsgi_configure();
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -352,6 +352,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
colon[0] = 0;
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
@@ -368,7 +371,16 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
vassal_argv[2] = name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(name, R_OK|X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
@@ -395,6 +407,10 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<(int)uwsgi.max_fd;i++) {
|
||||
if (n_ui->use_config) {
|
||||
if (i == n_ui->pipe_config[1])
|
||||
continue;
|
||||
}
|
||||
if (i != n_ui->pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
@@ -653,7 +669,9 @@ reconnect:
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
if (!ui_current->config_len) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
|
||||
@@ -421,7 +421,8 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct kevent *ev = (struct kevent *) events;
|
||||
|
||||
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
|
||||
// DO NOT CHECK FOR EOF !!!
|
||||
if ( ev[id].flags & EV_ERROR ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -107,6 +107,7 @@ struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock->fd = -1;
|
||||
uwsgi_sock->shared = 0;
|
||||
uwsgi_sock->name = name;
|
||||
uwsgi_sock->owner = owner;
|
||||
|
||||
|
||||
+18
-2
@@ -1,7 +1,23 @@
|
||||
import uwsgi
|
||||
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
if uwsgi.loop == 'gevent':
|
||||
import gevent
|
||||
|
||||
print uwsgi.version
|
||||
print uwsgi.workers()
|
||||
try:
|
||||
uwsgi.cache_set('foo', "Hello World from cache")
|
||||
except:
|
||||
pass
|
||||
def application(env, start_response):
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep()
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar"
|
||||
yield "foobar<br/>"
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep(3)
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
try:
|
||||
yield uwsgi.cache_get('foo')
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -164,7 +164,9 @@ char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
|
||||
|
||||
free(frame);
|
||||
frame = NULL;
|
||||
free(header);
|
||||
header = NULL;
|
||||
|
||||
char *fullbody = uwsgi_malloc(*msgsize);
|
||||
char *message;
|
||||
|
||||
@@ -17,6 +17,7 @@ static void uwsgi_corerouter_setup_sockets(char *gw_id) {
|
||||
int shared_socket = atoi(ugs->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
ugs->shared = 1;
|
||||
if (ugs->fd == -1) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
exit(1);
|
||||
|
||||
@@ -24,7 +24,7 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
|
||||
if (!uli->next) {
|
||||
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
|
||||
if (rw) {
|
||||
uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
}
|
||||
else {
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
|
||||
@@ -45,7 +45,11 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_MUTEX
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
|
||||
#else
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
|
||||
#endif
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
|
||||
|
||||
@@ -71,6 +75,13 @@ struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
|
||||
uwsgi_log("unable to make the mutex 'robust'\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize mutex\n");
|
||||
exit(1);
|
||||
@@ -78,7 +89,9 @@ struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
#ifndef EOWNERDEAD
|
||||
uli->can_deadlock = 1;
|
||||
#endif
|
||||
|
||||
return uli;
|
||||
}
|
||||
@@ -105,6 +118,27 @@ pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
if (pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr) == EOWNERDEAD) {
|
||||
uwsgi_log("[deadlock-detector] a process holding a robust mutex died. recovering...\n");
|
||||
pthread_mutex_consistent_np((pthread_mutex_t *) uli->lock_ptr);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
|
||||
#endif
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_fast(uli);
|
||||
@@ -132,23 +166,10 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
return uwsgi_lock_fast_init(uli);
|
||||
return uwsgi_lock_fast_init(id);
|
||||
#else
|
||||
|
||||
pthread_rwlockattr_t attr;
|
||||
@@ -159,6 +180,7 @@ struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
uwsgi_log("unable to allocate rwlock structure\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||||
uwsgi_log("unable to share rwlock\n");
|
||||
exit(1);
|
||||
@@ -224,6 +246,47 @@ pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_POSIX_SEM)
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(sem_t)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(sem_t)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "POSIX semaphores"
|
||||
|
||||
#include <semaphore.h>
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
sem_init((sem_t*) uli->lock_ptr, 1, 1);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
sem_wait((sem_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
sem_post((sem_t*) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (sem_trywait((sem_t *) uli->lock_ptr) == 0) {
|
||||
sem_post((sem_t*) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
|
||||
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
|
||||
@@ -296,25 +359,38 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli);
|
||||
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
// used by ftok
|
||||
static int counter = 1;
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
ushort *array;
|
||||
} semu ;
|
||||
int semid;
|
||||
key_t myKey;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
|
||||
int semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0600);
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
semid = semget(myKey, 1, IPC_CREAT|0666);
|
||||
}
|
||||
else {
|
||||
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
|
||||
}
|
||||
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering fo atexit hook in case of problems
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
memcpy(uli->lock_ptr, &semid, sizeof(int));
|
||||
|
||||
semu.val = 1;
|
||||
@@ -377,6 +453,8 @@ void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
|
||||
|
||||
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
|
||||
|
||||
return;
|
||||
|
||||
clear:
|
||||
@@ -403,7 +481,7 @@ void uwsgi_setup_locking() {
|
||||
// use the fastest avaikable locking
|
||||
if (uwsgi.lock_engine) {
|
||||
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_log("lock engine: ipcsem\n");
|
||||
uwsgi_log_initial("lock engine: ipcsem\n");
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
|
||||
@@ -420,7 +498,7 @@ void uwsgi_setup_locking() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
#ifdef UWSGI_IPCSEM_ATEXIT
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
#endif
|
||||
@@ -441,7 +519,7 @@ void uwsgi_setup_locking() {
|
||||
int uwsgi_fcntl_lock(int fd) {
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
@@ -457,7 +535,7 @@ int uwsgi_fcntl_is_locked(int fd) {
|
||||
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
@@ -113,7 +113,7 @@ void uwsgi_check_logrotate(void) {
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// optimize this (please)
|
||||
char *time_request;
|
||||
char time_request[26];
|
||||
time_t microseconds, microseconds2;
|
||||
int rlen;
|
||||
int app_req = -1;
|
||||
@@ -136,6 +136,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
char *msg4 = " via offload() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
@@ -159,8 +160,15 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
else if (wsgi_req->status == -30) {
|
||||
via = msg4;
|
||||
}
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
#ifdef __sun__
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request);
|
||||
#endif
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
|
||||
@@ -263,6 +271,13 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(UWSGI_NEW_OPENBSD)
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc), &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
*vsz = (kproc->p_vm_dsize + kproc->p_vm_ssize + kproc->p_vm_tsize) * uwsgi.page_size;
|
||||
*rss = kproc->p_vm_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kinfo_proc2 *kproc2;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ void *simple_loop(void *arg1) {
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
@@ -120,7 +120,6 @@ void *zeromq_loop(void *arg1) {
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
|
||||
uwsgi.zeromq_recv_flag = 0;
|
||||
zmq_pollitem_t zmq_poll_items[3];
|
||||
char uwsgi_signal;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
|
||||
@@ -135,7 +134,7 @@ void *zeromq_loop(void *arg1) {
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
@@ -188,38 +187,12 @@ void *zeromq_loop(void *arg1) {
|
||||
}
|
||||
|
||||
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.signal_socket, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.my_signal_socket, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,39 @@ void *logger_thread_loop(void *noarg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *cache_sweeper_loop(void *noarg) {
|
||||
|
||||
int i;
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
if (!uwsgi.cache_expire_freq) uwsgi.cache_expire_freq = 3;
|
||||
|
||||
// remove expired cache items TODO use rb_tree timeouts
|
||||
for(;;) {
|
||||
sleep(uwsgi.cache_expire_freq);
|
||||
uint64_t freed_items = 0;
|
||||
// skip the first slot
|
||||
for (i = 1; i < (int) uwsgi.cache_max_items; i++) {
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi.cache_items[i].expires) {
|
||||
if (uwsgi.cache_items[i].expires < (uint64_t) uwsgi.current_time) {
|
||||
uwsgi_cache_del(NULL, 0, i);
|
||||
freed_items++;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
}
|
||||
if (uwsgi.cache_report_freed_items && freed_items > 0) {
|
||||
uwsgi_log("freed %llu cache items\n", (unsigned long long) freed_items);
|
||||
}
|
||||
};
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
|
||||
int subfile_size;
|
||||
@@ -230,6 +263,29 @@ void get_linux_tcp_info(int fd) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <linux/sockios.h>
|
||||
|
||||
#ifdef UNBIT
|
||||
#define SIOBKLGQ 0x8908
|
||||
#endif
|
||||
|
||||
#ifdef SIOBKLGQ
|
||||
|
||||
void get_linux_unbit_SIOBKLGQ(int fd) {
|
||||
|
||||
int queue = 0;
|
||||
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -256,6 +312,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uint64_t last_request_count = 0;
|
||||
|
||||
pthread_t logger_thread;
|
||||
pthread_t cache_sweeper;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
struct sockaddr_in udp_client;
|
||||
@@ -351,6 +408,16 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) {
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, NULL)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("unable to run the cache sweeper !!!\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("cache sweeper thread enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi.wsgi_req->buffer = uwsgi.async_buf[0];
|
||||
|
||||
@@ -579,7 +646,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.gp[i]->master_cycle();
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_cycle) {
|
||||
uwsgi.p[i]->master_cycle();
|
||||
}
|
||||
@@ -918,7 +985,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
// loop the various udp manager until one returns true
|
||||
udp_managed = 0;
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
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, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
udp_managed = 1;
|
||||
@@ -1166,19 +1233,6 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// remove expired cache items TODO use rb_tree timeouts
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi.cache_items[i].expires) {
|
||||
if (uwsgi.cache_items[i].expires < (uint64_t) uwsgi.current_time) {
|
||||
uwsgi_cache_del(uwsgi.cache_items[i].key, uwsgi.cache_items[i].keysize);
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
}
|
||||
}
|
||||
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
check_interval = 1;
|
||||
@@ -1191,6 +1245,11 @@ int master_loop(char **argv, char **environ) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
get_linux_tcp_info(uwsgi_sock->fd);
|
||||
}
|
||||
#ifdef SIOBKLGQ
|
||||
else if (uwsgi_sock->family == AF_UNIX) {
|
||||
get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
|
||||
}
|
||||
#endif
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
#endif
|
||||
@@ -1535,11 +1594,19 @@ nextlock:
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
|
||||
+78
-27
@@ -8,6 +8,18 @@ void worker_wakeup() {
|
||||
int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
static time_t last_check = 0;
|
||||
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
|
||||
if (!last_check) last_check = time(NULL);
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (!check_interval)
|
||||
check_interval = 1;
|
||||
|
||||
if ( (now - last_check) < check_interval) return 1;
|
||||
|
||||
last_check = now;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
|
||||
@@ -178,7 +190,7 @@ int uwsgi_cheaper_algo_backlog(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->ti.tcpi_unacked;
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
@@ -371,7 +383,10 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
ugs = ugs->next;
|
||||
continue;
|
||||
}
|
||||
close(ugs->fd);
|
||||
// do not close shared sockets !!!
|
||||
if (!ugs->shared) {
|
||||
close(ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
// fix the communication pipe
|
||||
@@ -475,7 +490,7 @@ int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
@@ -530,20 +545,36 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
uc_month = ucron->month;
|
||||
uc_week = ucron->week;
|
||||
|
||||
if (ucron->minute == -1)
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
if (ucron->hour == -1)
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (ucron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (ucron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day != -1 && ucron->week != -1) {
|
||||
if (ucron->day >= 0 && ucron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
@@ -587,8 +618,10 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (current_cron) {
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
uc_minute = current_cron->minute;
|
||||
uc_hour = current_cron->hour;
|
||||
@@ -596,20 +629,36 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
uc_month = current_cron->month;
|
||||
uc_week = current_cron->week;
|
||||
|
||||
if (current_cron->minute == -1)
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
if (current_cron->hour == -1)
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (current_cron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (current_cron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (current_cron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (current_cron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (current_cron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (current_cron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day != -1 && current_cron->week != -1) {
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
@@ -668,7 +717,8 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
#ifdef __linux__
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
|
||||
stats_send_llu("\"listen_queue_errors\": %llu,\n", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]);
|
||||
#endif
|
||||
|
||||
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
|
||||
@@ -722,6 +772,7 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
|
||||
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
|
||||
stats_send_llu("\"static_offload_threads\": %llu, ", uwsgi.workers[i + 1].static_offload_threads);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output, "\"status\": \"cheap\", ");
|
||||
|
||||
@@ -48,13 +48,13 @@ void uwsgi_mule(int id) {
|
||||
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
@@ -62,7 +62,7 @@ void uwsgi_mule(int id) {
|
||||
|
||||
|
||||
if (uwsgi.mules[id-1].patch) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
|
||||
// never here
|
||||
@@ -184,7 +184,7 @@ void uwsgi_mule_handler() {
|
||||
}
|
||||
else {
|
||||
int i,found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->mule_msg) {
|
||||
if (uwsgi.p[i]->mule_msg(message, len)) {
|
||||
found = 1;
|
||||
|
||||
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
|
||||
static int plugin_already_loaded(const char *plugin) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -50,6 +50,8 @@ static int plugin_already_loaded(const char *plugin) {
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
char *plugin_abs_path = NULL;
|
||||
char *plugin_filename = NULL;
|
||||
|
||||
int need_free = 0;
|
||||
char *plugin_name = plugin;
|
||||
@@ -79,35 +81,43 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
if (strchr(plugin_name, '/')) {
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
goto end;
|
||||
}
|
||||
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
|
||||
plugin_symbol_name_start++;
|
||||
plugin_abs_path = plugin_name;
|
||||
goto success;
|
||||
}
|
||||
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
char *plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
|
||||
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (plugin_handle) {
|
||||
free(plugin_filename);
|
||||
break;
|
||||
plugin_abs_path = plugin_filename;
|
||||
//free(plugin_filename);
|
||||
goto success;
|
||||
}
|
||||
free(plugin_filename);
|
||||
plugin_filename = NULL;
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
if (!plugin_handle) {
|
||||
char *plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
|
||||
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
free(plugin_filename);
|
||||
plugin_abs_path = plugin_filename;
|
||||
//free(plugin_filename);
|
||||
}
|
||||
|
||||
success:
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
|
||||
@@ -116,7 +126,7 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
// is it a link ?
|
||||
memset(linkpath_buf, 0, 1024);
|
||||
memset(linkpath, 0, 1024);
|
||||
if ((linkpath_size = readlink(plugin_name, linkpath_buf, 1023)) > 0) {
|
||||
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
|
||||
do {
|
||||
linkpath_buf[linkpath_size] = '\0';
|
||||
strncpy(linkpath, linkpath_buf, linkpath_size+1);
|
||||
@@ -145,6 +155,8 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
@@ -154,11 +166,13 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (has_option) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_option *op = up->options;
|
||||
int found = 0;
|
||||
while (op && op->name) {
|
||||
if (!strcmp(has_option, op->name)) {
|
||||
@@ -173,6 +187,8 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
@@ -186,18 +202,75 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
|
||||
if (up->on_load)
|
||||
up->on_load();
|
||||
return plugin_handle;
|
||||
}
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
|
||||
end:
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_try_autoload(char *option) {
|
||||
DIR *d;
|
||||
struct dirent *dp;
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
d = opendir(pdir->value);
|
||||
if (d) {
|
||||
while ((dp = readdir(d)) != NULL) {
|
||||
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
|
||||
char *filename = uwsgi_concat3(pdir->value, "/", dp->d_name);
|
||||
if (uwsgi_load_plugin(-1, filename, option)) {
|
||||
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
|
||||
free(filename);
|
||||
closedir(d);
|
||||
// add new options
|
||||
build_options();
|
||||
return 1;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
d = opendir(UWSGI_PLUGIN_DIR);
|
||||
if (!d) return 0;
|
||||
|
||||
while((dp = readdir(d)) != NULL) {
|
||||
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
|
||||
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
|
||||
if (uwsgi_load_plugin(-1, filename, option)) {
|
||||
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
|
||||
free(filename);
|
||||
closedir(d);
|
||||
// add new options
|
||||
build_options();
|
||||
return 1;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -63,7 +63,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
case 2:
|
||||
// del
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
||||
@@ -7,6 +7,7 @@ struct uwsgi_carbon {
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
int no_workers;
|
||||
} u_carbon;
|
||||
|
||||
struct uwsgi_option carbon_options[] = {
|
||||
@@ -14,6 +15,7 @@ struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
|
||||
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
|
||||
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
|
||||
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -73,6 +75,8 @@ void carbon_master_cycle() {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
if (u_carbon.no_workers) goto gmetrics;
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
|
||||
@@ -109,6 +113,8 @@ void carbon_master_cycle() {
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
|
||||
gmetrics:
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
@@ -12,6 +12,7 @@ struct uwsgi_cgi {
|
||||
struct uwsgi_string_list *unset;
|
||||
struct uwsgi_string_list *loadlib;
|
||||
int optimize;
|
||||
int from_docroot;
|
||||
int has_mountpoints;
|
||||
struct uwsgi_dyn_dict *default_cgi;
|
||||
int path_info;
|
||||
@@ -45,6 +46,8 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
{"cgi-map-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
|
||||
{"cgi-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
|
||||
|
||||
{"cgi-from-docroot", no_argument, 0, "blindly enable cgi in DOCUMENT_ROOT", uwsgi_opt_true, &uc.from_docroot, 0},
|
||||
|
||||
{"cgi-buffer-size", required_argument, 0, "set cgi buffer size", uwsgi_opt_set_64bit, &uc.buffer_size, 0},
|
||||
{"cgi-timeout", required_argument, 0, "set cgi script timeout", uwsgi_opt_set_int, &uc.timeout, 0},
|
||||
|
||||
@@ -500,16 +503,24 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *docroot = NULL;
|
||||
|
||||
// check for file availability (and 'runnability')
|
||||
if (uc.from_docroot) {
|
||||
docroot = wsgi_req->document_root;
|
||||
docroot_len = wsgi_req->document_root_len;
|
||||
}
|
||||
else {
|
||||
docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
if (docroot)
|
||||
docroot_len = strlen(docroot);
|
||||
}
|
||||
|
||||
char *docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
|
||||
if (docroot == NULL) {
|
||||
if (docroot == NULL || docroot_len == 0) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
docroot_len = strlen(docroot);
|
||||
memcpy(full_path, docroot, docroot_len);
|
||||
|
||||
if (!is_a_file) {
|
||||
|
||||
@@ -17,7 +17,7 @@ int cheaper_backlog2_algo(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->ti.tcpi_unacked;
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
@@ -207,6 +207,18 @@ void close_session(struct fastrouter_session *fr_session) {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ufr.subscriptions && fr_session->un && fr_session->un->len > 0) {
|
||||
// decrease reference count
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[1] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
fr_session->un->reference--;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[2] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (fr_session->instance_failed) {
|
||||
|
||||
if (fr_session->soopt) {
|
||||
@@ -227,14 +239,7 @@ void close_session(struct fastrouter_session *fr_session) {
|
||||
|
||||
// now check for dead nodes
|
||||
if (ufr.subscriptions && fr_session->un && fr_session->un->len > 0) {
|
||||
// decrease reference count
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[1] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
fr_session->un->reference--;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[2] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
|
||||
if (fr_session->un->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len, fr_session->instance_address);
|
||||
|
||||
@@ -498,8 +503,8 @@ void fastrouter_loop(int id) {
|
||||
|
||||
ufr.mapper = uwsgi_fr_map_use_void;
|
||||
|
||||
if (ufr.use_cache) {
|
||||
ufr.mapper = uwsgi_fr_map_use_cache;
|
||||
if (ufr.use_cache) {
|
||||
ufr.mapper = uwsgi_fr_map_use_cache;
|
||||
}
|
||||
else if (ufr.pattern) {
|
||||
ufr.mapper = uwsgi_fr_map_use_pattern;
|
||||
@@ -511,8 +516,8 @@ void fastrouter_loop(int id) {
|
||||
ufr.mapper = uwsgi_fr_map_use_base;
|
||||
}
|
||||
else if (ufr.code_string_code && ufr.code_string_function) {
|
||||
ufr.mapper = uwsgi_fr_map_use_cache;
|
||||
}
|
||||
ufr.mapper = uwsgi_fr_map_use_cs;
|
||||
}
|
||||
else if (ufr.to_socket) {
|
||||
ufr.mapper = uwsgi_fr_map_use_to;
|
||||
}
|
||||
@@ -538,7 +543,7 @@ void fastrouter_loop(int id) {
|
||||
else {
|
||||
delta = min_timeout->key - time(NULL);
|
||||
if (delta <= 0) {
|
||||
expire_timeouts(ufr.timeouts, ufr.fr_table);
|
||||
expire_timeouts();
|
||||
delta = 0;
|
||||
}
|
||||
}
|
||||
@@ -554,7 +559,7 @@ void fastrouter_loop(int id) {
|
||||
}
|
||||
|
||||
if (nevents == 0) {
|
||||
expire_timeouts(ufr.timeouts, ufr.fr_table);
|
||||
expire_timeouts();
|
||||
}
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
@@ -577,6 +582,10 @@ void fastrouter_loop(int id) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef __linux__
|
||||
uwsgi_socket_b(new_connection);
|
||||
#endif
|
||||
|
||||
ufr.fr_table[new_connection] = alloc_fr_session();
|
||||
ufr.fr_table[new_connection]->fd = new_connection;
|
||||
ufr.fr_table[new_connection]->instance_fd = -1;
|
||||
|
||||
+27
-29
@@ -5,7 +5,7 @@ extern struct uwsgi_python up;
|
||||
|
||||
#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)
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req
|
||||
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
|
||||
if (ret) { Py_DECREF(ret); }\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
@@ -24,36 +24,30 @@ struct uwsgi_gevent {
|
||||
} ugevent;
|
||||
|
||||
|
||||
struct wsgi_request *uwsgi_gevent_current_wsgi_req(void) {
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *py_wsgi_req = PyObject_GetAttrString(current_greenlet, "uwsgi_wsgi_req");
|
||||
return (struct wsgi_request*) PyLong_AsLong(py_wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int signal_socket;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:uwsgi_gevent_signal_handler", &signal_socket)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (read(signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
// close the socket to end the mess...from now on the worker is alone (no master)
|
||||
else close(signal_socket);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(signal_socket, "worker", uwsgi.mywid);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// the following twi functions are called whenever an event is available in the signal queue
|
||||
// they both trigger the same function
|
||||
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
|
||||
@@ -90,7 +84,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
|
||||
@@ -107,7 +100,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
|
||||
uwsgi_close_request(wsgi_req);
|
||||
free_req_queue;
|
||||
goto clear;
|
||||
}
|
||||
@@ -150,10 +142,10 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
int status ;
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
// another hack to retrieve the current wsgi_req;
|
||||
PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);
|
||||
PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// create a watcher for request socket
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) goto clear1;
|
||||
@@ -167,9 +159,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
|
||||
if (!ret) goto clear_and_stop;
|
||||
|
||||
// do not forget to overwrite this pointer each time !!!
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// we can safely decref here as watcher and timer has got a +1 for start() method
|
||||
Py_DECREF(ret);
|
||||
if (ret == timer) {
|
||||
@@ -177,7 +166,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (ret == watcher) {
|
||||
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto clear_and_stop;
|
||||
@@ -196,11 +184,11 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
// switch after each yield
|
||||
GEVENT_SWITCH;
|
||||
}
|
||||
@@ -220,8 +208,6 @@ clear1:
|
||||
Py_DECREF(current_greenlet);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
free_req_queue;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -239,6 +225,17 @@ PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler"
|
||||
|
||||
void gevent_loop() {
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ..then reset GIL subsystem as noop (gevent IO will take care of it...)
|
||||
up.gil_get = gil_fake_get;
|
||||
up.gil_release = gil_fake_release;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
@@ -246,6 +243,7 @@ void gevent_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
|
||||
|
||||
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
|
||||
if (!gevent_dict) uwsgi_pyexit;
|
||||
|
||||
+6
-5
@@ -592,6 +592,9 @@ void http_loop(int id) {
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
#ifndef __linux__
|
||||
uwsgi_socket_b(new_connection);
|
||||
#endif
|
||||
|
||||
uhttp_table[new_connection] = alloc_uhttp_session();
|
||||
uhttp_table[new_connection]->fd = new_connection;
|
||||
@@ -892,10 +895,9 @@ void http_loop(int id) {
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(uhttp_session->fd, bbuf, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
ssize_t s_len = send(uhttp_session->fd, bbuf, len, 0);
|
||||
if (s_len <= 0) {
|
||||
if (s_len < 0)
|
||||
uwsgi_error("send()");
|
||||
close(uhttp_session->fd);
|
||||
close(uhttp_session->instance_fd);
|
||||
@@ -910,7 +912,6 @@ void http_loop(int id) {
|
||||
// body from client
|
||||
else if (interesting_fd == uhttp_session->fd) {
|
||||
|
||||
//uwsgi_log("receiving body...\n");
|
||||
len = recv(uhttp_session->fd, bbuf, UMAX16, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
|
||||
|
||||
@@ -16,7 +16,7 @@ struct uwsgi_lua {
|
||||
|
||||
struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &uwsgi.ulua.filename, 0},
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -630,7 +630,6 @@ char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_
|
||||
#endif
|
||||
|
||||
if (lua_pcall(L, 1, 1, 0) != 0) {
|
||||
uwsgi_log("CAZZO\n");
|
||||
uwsgi_log("error running function `f': %s",
|
||||
lua_tostring(L, -1));
|
||||
return NULL;
|
||||
|
||||
@@ -28,7 +28,10 @@ int nagios() {
|
||||
|
||||
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers %s\n", strerror(errno));
|
||||
if (errno == EPERM || errno == EACCES) {
|
||||
exit(3);
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int uwsgi_request_notfound(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[3];
|
||||
|
||||
if (wsgi_req->protocol_len > 0) {
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = "HTTP/1.0";
|
||||
iov[0].iov_len = 8;
|
||||
}
|
||||
|
||||
iov[1].iov_base = " 404 Not Found\r\n";
|
||||
iov[1].iov_len = 16;
|
||||
|
||||
iov[2].iov_base = "Content-Type: text/plain\r\n\r\n";
|
||||
iov[2].iov_len = 28;
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 3);
|
||||
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Not Found", 9);
|
||||
wsgi_req->status = 404;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin notfound_plugin = {
|
||||
|
||||
.name = "notfound",
|
||||
.request = uwsgi_request_notfound,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='notfound'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['notfound']
|
||||
+47
-17
@@ -20,9 +20,11 @@ struct uwsgi_php {
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *set;
|
||||
struct uwsgi_string_list *append_config;
|
||||
char *docroot;
|
||||
char *app;
|
||||
size_t ini_size;
|
||||
int dump_config;
|
||||
char *server_software;
|
||||
size_t server_software_len;
|
||||
} uphp;
|
||||
@@ -32,11 +34,12 @@ void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
|
||||
uwsgi_sapi_module.php_ini_ignore = 1;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_option uwsgi_php_options[] = {
|
||||
|
||||
{"php-ini", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-config", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-ini-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
|
||||
{"php-config-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
|
||||
{"php-set", required_argument, 0, "set a php config directive", uwsgi_opt_add_string_list, &uphp.set, 0},
|
||||
{"php-index", required_argument, 0, "list the php index files", uwsgi_opt_add_string_list, &uphp.index, 0},
|
||||
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
|
||||
@@ -44,6 +47,7 @@ struct uwsgi_option uwsgi_php_options[] = {
|
||||
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
|
||||
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
|
||||
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
|
||||
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -90,12 +94,11 @@ static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
{
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
|
||||
if (len != (ssize_t) str_length) {
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
php_handle_aborted_connection();
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->response_size += len;
|
||||
return str_length;
|
||||
}
|
||||
|
||||
@@ -295,19 +298,23 @@ static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
|
||||
|
||||
void uwsgi_php_append_config(char *filename) {
|
||||
int file_size = 0;
|
||||
char *file_content = uwsgi_open_and_read(filename, &file_size, 1, NULL);
|
||||
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + file_size);
|
||||
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, file_content, file_size);
|
||||
uphp.ini_size += file_size-1;
|
||||
free(file_content);
|
||||
}
|
||||
|
||||
void uwsgi_php_set(char *opt) {
|
||||
|
||||
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + strlen(opt)+2);
|
||||
if (uphp.ini_size == 0) {
|
||||
memcpy(uwsgi_sapi_module.ini_entries, opt, strlen(opt));
|
||||
}
|
||||
else {
|
||||
memcpy(uwsgi_sapi_module.ini_entries + (uphp.ini_size -1), opt, strlen(opt));
|
||||
}
|
||||
uphp.ini_size += strlen(opt)+2;
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size-2] = '\n';
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = 0;
|
||||
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, opt, strlen(opt));
|
||||
|
||||
uphp.ini_size += strlen(opt)+1;
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = '\n';
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
|
||||
}
|
||||
|
||||
// future implementation...
|
||||
@@ -343,7 +350,7 @@ PHP_FUNCTION(uwsgi_cache_del) {
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
if (uwsgi_cache_del(key, keylen, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
@@ -615,15 +622,26 @@ int uwsgi_php_init(void) {
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
struct uwsgi_string_list *pset = uphp.set;
|
||||
struct uwsgi_string_list *append_config = uphp.append_config;
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
|
||||
// applying custom options
|
||||
while(append_config) {
|
||||
uwsgi_php_append_config(append_config->value);
|
||||
append_config = append_config->next;
|
||||
}
|
||||
while(pset) {
|
||||
uwsgi_php_set(pset->value);
|
||||
pset = pset->next;
|
||||
}
|
||||
|
||||
if (uphp.dump_config) {
|
||||
uwsgi_log("--- PHP custom config ---\n\n");
|
||||
uwsgi_log("%s\n", uwsgi_sapi_module.ini_entries);
|
||||
uwsgi_log("--- end of PHP custom config ---\n");
|
||||
}
|
||||
|
||||
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
|
||||
|
||||
// filling http status codes
|
||||
@@ -711,13 +729,24 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uphp.docroot) {
|
||||
wsgi_req->document_root = uphp.docroot;
|
||||
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
|
||||
}
|
||||
// fallback to cwd
|
||||
else if (!wsgi_req->document_root_len) {
|
||||
wsgi_req->document_root = uwsgi.cwd;
|
||||
wsgi_req->document_root_len = strlen(uwsgi.cwd);
|
||||
}
|
||||
else {
|
||||
// explode DOCUMENT_ROOT (both for security and sanity checks)
|
||||
// this memory will be cleared on request end
|
||||
char *sanitized_docroot = ecalloc(1, PATH_MAX+1);
|
||||
if (!uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, sanitized_docroot)) {
|
||||
efree(sanitized_docroot);
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->document_root = sanitized_docroot;
|
||||
}
|
||||
|
||||
// fix document_root_len
|
||||
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
|
||||
|
||||
if (uphp.app) {
|
||||
strcpy(real_filename, uphp.app);
|
||||
@@ -841,7 +870,8 @@ secure2:
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("php filename = %s %.*s\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name);
|
||||
uwsgi_log("php filename = %s script_name = %.*s (%d) document_root = %.*s (%d)\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->script_name_len,
|
||||
wsgi_req->document_root_len, wsgi_req->document_root, wsgi_req->document_root_len);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ struct uwsgi_perl {
|
||||
char *embedding[3];
|
||||
|
||||
// check for Devel::StackTrace
|
||||
int no_die_catch;
|
||||
int stacktrace_available;
|
||||
|
||||
// this is a pointer to the main list of interpreters (required for signals, rpc....);
|
||||
|
||||
@@ -384,10 +384,12 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
if (!SvTRUE(ERRSV)) {
|
||||
uperl.stacktrace_available = 1;
|
||||
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
|
||||
if (!uperl.no_die_catch) {
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
if (!SvTRUE(ERRSV)) {
|
||||
uperl.stacktrace_available = 1;
|
||||
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
|
||||
}
|
||||
}
|
||||
|
||||
SV *dollar_zero = get_sv("0", GV_ADD);
|
||||
|
||||
@@ -12,6 +12,7 @@ struct uwsgi_perl uperl;
|
||||
struct uwsgi_option uwsgi_perl_options[] = {
|
||||
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
|
||||
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
@@ -471,19 +472,13 @@ int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
// taken from Torsten Foertsch AfterFork.xs
|
||||
void uwsgi_perl_post_fork() {
|
||||
/*
|
||||
GV *tmpgv;
|
||||
|
||||
PL_ppid = (IV)getppid();
|
||||
hv_clear(PL_pidstatus);
|
||||
|
||||
tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
|
||||
GV *tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
|
||||
if (tmpgv) {
|
||||
SvREADONLY_off(GvSV(tmpgv));
|
||||
sv_setiv(GvSV(tmpgv), (IV)getpid());
|
||||
SvREADONLY_on(GvSV(tmpgv));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
int uwsgi_perl_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
@@ -126,9 +126,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
vi = (i*2)+base;
|
||||
wsgi_req->hvec[vi].iov_base = "\r\n"; wsgi_req->hvec[vi].iov_len = 2;
|
||||
|
||||
if ( !(wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1)) ) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1);
|
||||
|
||||
hitem = av_fetch(response, 2, 0);
|
||||
|
||||
|
||||
@@ -76,13 +76,21 @@ XS(XS_wait_fd_write) {
|
||||
|
||||
#endif
|
||||
|
||||
XS(XS_signal) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
uwsgi_signal_send(uwsgi.signal_socket, SvIV(ST(0)));
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_reload) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
psgi_check_args(0);
|
||||
|
||||
uwsgi_log("SENDING HUP TO %d\n", (int) uwsgi.workers[0].pid);
|
||||
if (kill(uwsgi.workers[0].pid, SIGHUP)) {
|
||||
uwsgi_error("kill()");
|
||||
XSRETURN_NO;
|
||||
@@ -104,7 +112,9 @@ XS(XS_cache_set) {
|
||||
key = SvPV(ST(0), keylen);
|
||||
val = SvPV(ST(1), vallen);
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
uwsgi_cache_set(key, (uint16_t) keylen, val, (uint64_t) vallen, 0, 0);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
@@ -123,13 +133,16 @@ XS(XS_cache_get) {
|
||||
|
||||
key = SvPV(ST(0), keylen);
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
val = uwsgi_cache_get(key, (uint16_t) keylen, &vallen);
|
||||
|
||||
if (!val)
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
|
||||
ST(0) = newSVpv(val, vallen);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
sv_2mortal(ST(0));
|
||||
|
||||
XSRETURN(1);
|
||||
@@ -215,5 +228,6 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(log);
|
||||
psgi_xs(async_connect);
|
||||
psgi_xs(suspend);
|
||||
psgi_xs(signal);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import os,sys
|
||||
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='pypy'
|
||||
GCC_LIST = ['../python/python_plugin', '../python/pyutils', '../python/pyloader', '../python/wsgi_handlers', '../python/wsgi_headers', '../python/wsgi_subhandler',
|
||||
'../python/web3_subhandler', '../python/pump_subhandler','../python/gil', '../python/uwsgi_pymodule', '../python/profiler', '../python/symimporter']
|
||||
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
|
||||
CFLAGS.append('-DUWSGI_PYPY')
|
||||
|
||||
LIBS = ['-lpypy-c']
|
||||
LDFLAGS = []
|
||||
@@ -3,14 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
void gil_real_get() {}
|
||||
void gil_real_release() {}
|
||||
#else
|
||||
|
||||
void gil_real_get() {
|
||||
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
|
||||
#ifndef PYTHREE
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
PyEval_AcquireLock();
|
||||
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
|
||||
#else
|
||||
@@ -22,7 +17,7 @@ void gil_real_get() {
|
||||
|
||||
void gil_real_release() {
|
||||
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
|
||||
#ifndef PYTHREE
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
|
||||
PyEval_ReleaseLock();
|
||||
#else
|
||||
@@ -31,7 +26,6 @@ void gil_real_release() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void gil_fake_get() {}
|
||||
void gil_fake_release() {}
|
||||
|
||||
@@ -16,15 +16,27 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
|
||||
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
static uint64_t last_ts = 0;
|
||||
uint64_t now = uwsgi_micros();
|
||||
uint64_t delta = 0;
|
||||
|
||||
switch(what) {
|
||||
case PyTrace_CALL:
|
||||
uwsgi_log("[uWSGI Python profiler] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
if (last_ts == 0) delta = 0;
|
||||
else delta = now - last_ts;
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
(unsigned long long) delta,
|
||||
PyString_AsString(frame->f_code->co_filename),
|
||||
PyFrame_GetLineNumber(frame),
|
||||
PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount, frame->f_code->co_stacksize);
|
||||
break;
|
||||
case PyTrace_C_CALL:
|
||||
uwsgi_log("[uWSGI Python profiler] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
if (last_ts == 0) delta = 0;
|
||||
else delta = now - last_ts;
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
(unsigned long long) delta,
|
||||
PyString_AsString(frame->f_code->co_filename),
|
||||
PyFrame_GetLineNumber(frame),
|
||||
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
|
||||
@@ -34,3 +46,26 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
static uint64_t last_ts = 0;
|
||||
uint64_t now = uwsgi_micros();
|
||||
uint64_t delta = 0;
|
||||
|
||||
if (what == PyTrace_LINE) {
|
||||
if (last_ts == 0) {
|
||||
delta = 0;
|
||||
}
|
||||
else {
|
||||
delta = now - last_ts;
|
||||
}
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,8 +185,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
struct http_status_codes *http_sc;
|
||||
char sc[4];
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
|
||||
@@ -339,7 +337,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -371,22 +368,14 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +425,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
doh:
|
||||
free(mountpoint);
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (interpreter == NULL && id) {
|
||||
Py_EndInterpreter(wi->interpreter);
|
||||
@@ -481,9 +482,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
|
||||
PyObject *tmp_callable;
|
||||
PyObject *applications;
|
||||
#ifndef UWSGI_PYPY
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
#endif
|
||||
|
||||
char *module = (char *) arg1;
|
||||
|
||||
@@ -506,11 +505,8 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
applications = PyDict_GetItemString(uwsgi_dict, "applications");
|
||||
if (applications && PyDict_Check(applications)) return applications;
|
||||
#endif
|
||||
|
||||
|
||||
applications = PyDict_GetItemString(wsgi_dict, "applications");
|
||||
if (applications && PyDict_Check(applications)) return applications;
|
||||
@@ -714,8 +710,10 @@ PyObject *uwsgi_paste_loader(void *arg1) {
|
||||
|
||||
PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
|
||||
return NULL;
|
||||
#else
|
||||
char *code = (char *) arg1;
|
||||
|
||||
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
|
||||
@@ -771,8 +769,6 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
}
|
||||
|
||||
return wsgi_eval_callable;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+206
-35
@@ -108,8 +108,6 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &up.catch_exceptions, 0},
|
||||
{"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &up.ignore_script_name, 0},
|
||||
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
|
||||
#ifndef UWSGI_PYPY
|
||||
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
|
||||
@@ -121,6 +119,14 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
{"py-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
|
||||
{"py-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
|
||||
{"python-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
|
||||
{"python-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
|
||||
{"py-auto-reload-ignore", required_argument, 0, "ignore the specified module during auto-reload scan (can be specified multiple times)", uwsgi_opt_add_string_list, &up.auto_reload_ignore, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -144,12 +150,16 @@ int uwsgi_python_init() {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
char *pyversion = strchr(Py_GetVersion(), '\n');
|
||||
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
if (!pyversion) {
|
||||
uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
|
||||
}
|
||||
else {
|
||||
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
}
|
||||
#else
|
||||
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
if (up.home != NULL) {
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wpyhome;
|
||||
@@ -168,22 +178,25 @@ int uwsgi_python_init() {
|
||||
uwsgi_log("Set PythonHome to %s\n", up.home);
|
||||
}
|
||||
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t pname[6];
|
||||
mbstowcs(pname, "uWSGI", 6);
|
||||
Py_SetProgramName(pname);
|
||||
#else
|
||||
|
||||
Py_SetProgramName("uWSGI");
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
Py_OptimizeFlag = up.optimize;
|
||||
#endif
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
|
||||
#endif
|
||||
if (!uwsgi.has_threads) {
|
||||
uwsgi_log("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
|
||||
}
|
||||
|
||||
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
|
||||
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
|
||||
@@ -206,7 +219,6 @@ int uwsgi_python_init() {
|
||||
|
||||
void uwsgi_python_reset_random_seed() {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
PyObject *random_module, *random_dict, *random_seed;
|
||||
|
||||
// reinitialize the random seed (thanks Jonas Borgström)
|
||||
@@ -217,6 +229,9 @@ void uwsgi_python_reset_random_seed() {
|
||||
random_seed = PyDict_GetItemString(random_dict, "seed");
|
||||
if (random_seed) {
|
||||
PyObject *random_args = PyTuple_New(1);
|
||||
#ifdef UWSGI_PYPY
|
||||
Py_INCREF(Py_None);
|
||||
#endif
|
||||
// pass no args
|
||||
PyTuple_SetItem(random_args, 0, Py_None);
|
||||
PyEval_CallObject(random_seed, random_args);
|
||||
@@ -226,7 +241,6 @@ void uwsgi_python_reset_random_seed() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +284,7 @@ void uwsgi_python_atexit() {
|
||||
PyObject *module = PyImport_ImportModule("atexit");
|
||||
Py_XDECREF(module);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
if (uwsgi.has_threads) {
|
||||
if (!PyImport_AddModule("dummy_threading"))
|
||||
PyErr_Clear();
|
||||
}
|
||||
@@ -288,7 +302,6 @@ void uwsgi_python_post_fork() {
|
||||
|
||||
uwsgi_python_reset_random_seed();
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
// call the post_fork_hook
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
@@ -300,7 +313,16 @@ void uwsgi_python_post_fork() {
|
||||
}
|
||||
PyErr_Clear();
|
||||
#endif
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
#ifdef UWSGI_THREADING
|
||||
if (up.auto_reload) {
|
||||
// spawn the reloader thread
|
||||
pthread_t par_tid;
|
||||
pthread_create(&par_tid, NULL, uwsgi_python_autoreloader_thread, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
@@ -308,7 +330,10 @@ UWSGI_RELEASE_GIL
|
||||
|
||||
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_PYPY
|
||||
uwsgi_log("import by filename is currently not supported on PyPy !!!\n");
|
||||
return NULL;
|
||||
#else
|
||||
FILE *pyfile;
|
||||
struct _node *py_file_node = NULL;
|
||||
PyObject *py_compiled_node, *py_file_module;
|
||||
@@ -376,6 +401,14 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_a_package) {
|
||||
py_file_module = PyImport_AddModule(name);
|
||||
if (py_file_module) {
|
||||
PyModule_AddObject(py_file_module, "__path__", Py_BuildValue("[O]", PyString_FromString(filename)));
|
||||
}
|
||||
free(real_filename);
|
||||
}
|
||||
|
||||
py_file_module = PyImport_ExecCodeModule(name, py_compiled_node);
|
||||
if (!py_file_module) {
|
||||
PyErr_Print();
|
||||
@@ -384,17 +417,7 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
|
||||
Py_DECREF(py_compiled_node);
|
||||
|
||||
if (is_a_package) {
|
||||
PyObject *py_file_module_dict = PyModule_GetDict(py_file_module);
|
||||
if (py_file_module_dict) {
|
||||
PyDict_SetItemString(py_file_module_dict, "__path__", Py_BuildValue("[O]", PyString_FromString(filename)));
|
||||
}
|
||||
free(real_filename);
|
||||
}
|
||||
|
||||
return py_file_module;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -450,7 +473,7 @@ void init_uwsgi_vars() {
|
||||
char *value = strchr(uppma->value, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("invalid pymodule-alias syntax\n");
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
value[0] = 0;
|
||||
if (!strchr(value + 1, '/')) {
|
||||
@@ -475,6 +498,7 @@ void init_uwsgi_vars() {
|
||||
// reset original value
|
||||
value[0] = '=';
|
||||
|
||||
next:
|
||||
uppma = uppma->next;
|
||||
}
|
||||
|
||||
@@ -538,6 +562,7 @@ void init_uwsgi_embedded_module() {
|
||||
// just for safety
|
||||
Py_INCREF(up.embedded_dict);
|
||||
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
@@ -639,6 +664,9 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyDict_SetItemString(up.embedded_dict, "loop", Py_None);
|
||||
}
|
||||
|
||||
PyObject *py_opt_dict = PyDict_New();
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
@@ -912,18 +940,14 @@ void uwsgi_python_preinit_apps() {
|
||||
|
||||
init_pyargv();
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
init_uwsgi_embedded_module();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
uwsgi_init_symbol_import();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (up.test_module != NULL) {
|
||||
@@ -955,13 +979,13 @@ void uwsgi_python_init_apps() {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
// prepare for stack suspend/resume
|
||||
if (uwsgi.async > 1) {
|
||||
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
|
||||
#ifndef UWSGI_PYPY
|
||||
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// setup app loaders
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
@@ -997,7 +1021,7 @@ void uwsgi_python_init_apps() {
|
||||
char *value = strchr(uppa->value, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("invalid pymodule-alias syntax\n");
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
value[0] = 0;
|
||||
if (!strchr(value + 1, '/')) {
|
||||
@@ -1022,6 +1046,7 @@ void uwsgi_python_init_apps() {
|
||||
// reset original value
|
||||
value[0] = '=';
|
||||
|
||||
next:
|
||||
uppa = uppa->next;
|
||||
}
|
||||
|
||||
@@ -1053,13 +1078,16 @@ void uwsgi_python_init_apps() {
|
||||
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
|
||||
}
|
||||
|
||||
if (uwsgi.profiler) {
|
||||
#ifndef UWSGI_PYPY
|
||||
if (uwsgi.profiler) {
|
||||
if (!strcmp(uwsgi.profiler, "pycall")) {
|
||||
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(uwsgi.profiler, "pyline")) {
|
||||
PyEval_SetTrace(uwsgi_python_tracer, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
@@ -1167,6 +1195,141 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
int uwsgi_check_python_mtime(PyObject *times_dict, char *filename) {
|
||||
struct stat st;
|
||||
|
||||
PyObject *py_mtime = PyDict_GetItemString(times_dict, filename);
|
||||
if (!py_mtime) {
|
||||
if (stat(filename, &st)) {
|
||||
return 0;
|
||||
}
|
||||
PyDict_SetItemString(times_dict, filename, PyLong_FromLong(st.st_mtime));
|
||||
}
|
||||
// the record is already tracked;
|
||||
else {
|
||||
long mtime = PyLong_AsLong(py_mtime);
|
||||
|
||||
if (stat(filename, &st)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((long) st.st_mtime != mtime) {
|
||||
uwsgi_log("[uwsgi-python-reloader] module/file %s has been modified\n", filename);
|
||||
kill(uwsgi.workers[0].pid, SIGHUP);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void *uwsgi_python_autoreloader_thread(void *foobar) {
|
||||
|
||||
PyObject *modules;
|
||||
|
||||
// block signals on this thread
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
#ifndef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
PyThreadState *pts = PyThreadState_New(up.main_thread->interp);
|
||||
pthread_setspecific(up.upt_save_key, (void *) pts);
|
||||
pthread_setspecific(up.upt_gil_key, (void *) pts);
|
||||
UWSGI_GET_GIL;
|
||||
PyObject *threading_module = PyImport_ImportModule("threading");
|
||||
if (threading_module) {
|
||||
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
|
||||
if (threading_module_dict) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
|
||||
#else
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
|
||||
#endif
|
||||
if (threading_current) {
|
||||
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
|
||||
if (!current_thread) {
|
||||
// ignore the error
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
PyObject_SetAttrString(current_thread, "name", PyString_FromString("uWSGIAutoReloader"));
|
||||
Py_INCREF(current_thread);
|
||||
modules = PyImport_GetModuleDict();
|
||||
goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
cycle:
|
||||
if (uwsgi.mywid == 1) {
|
||||
uwsgi_log("Python auto-reloader enabled\n");
|
||||
}
|
||||
PyObject *times_dict = PyDict_New();
|
||||
char *filename;
|
||||
for(;;) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
sleep(up.auto_reload);
|
||||
UWSGI_GET_GIL;
|
||||
// do not start monitoring til the first app is loaded (required for lazy mode)
|
||||
if (uwsgi_apps_cnt == 0) continue;
|
||||
#ifdef UWSGI_PYTHON_OLD
|
||||
int pos = 0;
|
||||
#else
|
||||
Py_ssize_t pos = 0;
|
||||
#endif
|
||||
PyObject *mod_name, *mod;
|
||||
while (PyDict_Next(modules, &pos, &mod_name, &mod)) {
|
||||
int found = 0;
|
||||
struct uwsgi_string_list *usl = up.auto_reload_ignore;
|
||||
while(usl) {
|
||||
if (!strcmp(usl->value, PyString_AsString(mod_name))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (found) continue;
|
||||
if (!PyObject_HasAttrString(mod, "__file__")) continue;
|
||||
PyObject *mod_file = PyObject_GetAttrString(mod, "__file__");
|
||||
if (!mod_file) continue;
|
||||
#ifdef PYTHREE
|
||||
PyObject *zero = PyUnicode_AsUTF8String(mod_file);
|
||||
char *mod_filename = PyString_AsString(zero);
|
||||
#else
|
||||
char *mod_filename = PyString_AsString(mod_file);
|
||||
#endif
|
||||
if (!mod_filename) {
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
char *ext = strrchr(mod_filename, '.');
|
||||
if (ext && (!strcmp(ext+1, "pyc") || !strcmp(ext+1, "pyd") || !strcmp(ext+1, "pyo"))) {
|
||||
filename = uwsgi_concat2n(mod_filename, strlen(mod_filename)-1, "", 0);
|
||||
}
|
||||
else {
|
||||
filename = uwsgi_concat2(mod_filename, "");
|
||||
}
|
||||
if (uwsgi_check_python_mtime(times_dict, filename)) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
}
|
||||
free(filename);
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
|
||||
|
||||
@@ -1406,6 +1569,7 @@ void uwsgi_python_hijack(void) {
|
||||
|
||||
// the pyshell will be execute only in the first worker
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
FILE *pyfile;
|
||||
if (up.pyrun) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
@@ -1419,8 +1583,8 @@ void uwsgi_python_hijack(void) {
|
||||
// could be never executed
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 0;
|
||||
return;
|
||||
@@ -1439,6 +1603,8 @@ void uwsgi_python_hijack(void) {
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
PyImport_ImportModule("readline");
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
|
||||
if (up.pyshell_oneshot) {
|
||||
@@ -1448,9 +1614,9 @@ void uwsgi_python_hijack(void) {
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_python_mule(char *opt) {
|
||||
@@ -1495,9 +1661,14 @@ int uwsgi_python_mule_msg(char *message, size_t len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin python_plugin = {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
struct uwsgi_plugin python_plugin = {
|
||||
.name = "python",
|
||||
#else
|
||||
struct uwsgi_plugin pypy_plugin = {
|
||||
.name = "pypy",
|
||||
#endif
|
||||
.alias = "python",
|
||||
.modifier1 = 0,
|
||||
.init = uwsgi_python_init,
|
||||
|
||||
@@ -8,20 +8,106 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
|
||||
return uwsgi_response_subhandler_wsgi(wsgi_req);
|
||||
}
|
||||
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
||||
char *uwsgi_python_get_exception_type(PyObject *exc) {
|
||||
char *class_name = NULL;
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
if (PyClass_Check(exc)) {
|
||||
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *pyret;
|
||||
if (class_name) {
|
||||
char *dot = strrchr(class_name, '.');
|
||||
if (dot) class_name = dot+1;
|
||||
|
||||
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
|
||||
if (module_name) {
|
||||
char *mod_name = PyString_AsString(module_name);
|
||||
if (mod_name && strcmp(mod_name, "exceptions") ) {
|
||||
char *ret = uwsgi_concat3(mod_name, ".", class_name);
|
||||
Py_DECREF(module_name);
|
||||
return ret;
|
||||
}
|
||||
Py_DECREF(module_name);
|
||||
return uwsgi_str(class_name);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_value(PyObject *value) {
|
||||
return PyString_AsString( PyObject_Str(value) );
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_repr(PyObject *exc, PyObject *value) {
|
||||
char *exc_type = uwsgi_python_get_exception_type(exc);
|
||||
char *exc_value = uwsgi_python_get_exception_value(value);
|
||||
|
||||
if (exc_type && exc_value) {
|
||||
return uwsgi_concat3(exc_type, ": ", exc_value);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_python_manage_exceptions(void) {
|
||||
PyObject *type = NULL;
|
||||
PyObject *value = NULL;
|
||||
PyObject *traceback = NULL;
|
||||
|
||||
char *exc_type = NULL;
|
||||
char *exc_value = NULL;
|
||||
char *exc_repr = NULL;
|
||||
|
||||
PyErr_Fetch(&type, &value, &traceback);
|
||||
PyErr_NormalizeException(&type, &value, &traceback);
|
||||
|
||||
if (uwsgi.reload_on_exception_type) {
|
||||
exc_type = uwsgi_python_get_exception_type(type);
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_value) {
|
||||
exc_value = uwsgi_python_get_exception_value(value);
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_repr) {
|
||||
exc_repr = uwsgi_python_get_exception_repr(type, value);
|
||||
}
|
||||
|
||||
int ret = uwsgi_manage_exception(exc_type, exc_value, exc_repr);
|
||||
|
||||
// free memory allocated for strcmp
|
||||
if (exc_type) free(exc_type);
|
||||
if (exc_repr) free(exc_repr);
|
||||
|
||||
PyErr_Restore(type, value, traceback);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
||||
|
||||
//uwsgi_log("ready to call %p %p\n", callable, args);
|
||||
|
||||
pyret = PyEval_CallObject(callable, args);
|
||||
PyObject *pyret = PyEval_CallObject(callable, args);
|
||||
|
||||
//uwsgi_log("called\n");
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
|
||||
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
|
||||
// this can be in a spooler or in the master
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
@@ -32,6 +118,10 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi
|
||||
if (!catch) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -71,7 +161,7 @@ void init_pyargv() {
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t *pname = uwsgi_calloc(strlen(argv0)+1);
|
||||
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(argv0)+1));
|
||||
mbstowcs(pname, argv0, strlen(argv0)+1);
|
||||
#else
|
||||
char *pname = argv0;
|
||||
@@ -106,17 +196,18 @@ void init_pyargv() {
|
||||
|
||||
if (up.argv) {
|
||||
|
||||
char *py_argv_copy = uwsgi_str(up.argv);
|
||||
up.argc = 1;
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(py_argv_copy)+1));
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(up.argv, " ");
|
||||
ap = strtok(py_argv_copy, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&up.argv, " \t")) != NULL) {
|
||||
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
#ifdef PYTHREE
|
||||
|
||||
+145
-49
@@ -171,7 +171,7 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
|
||||
PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef __linux__
|
||||
return PyInt_FromLong(uwsgi.shared->ti.tcpi_unacked);
|
||||
return PyInt_FromLong(uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -312,7 +312,9 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -381,7 +383,9 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -1021,6 +1025,17 @@ PyObject *py_uwsgi_setprocname(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_ready(PyObject * self, PyObject * args) {
|
||||
|
||||
if (ushared->ready) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_in_farm(PyObject * self, PyObject * args) {
|
||||
|
||||
char *farm_name = NULL;
|
||||
@@ -1711,6 +1726,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
}
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
@@ -1721,6 +1738,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
|
||||
free(spool_buffer);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_DECREF(spool_vars);
|
||||
|
||||
if (i > 0) {
|
||||
@@ -3095,6 +3114,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"mule_get_msg", (PyCFunction) py_uwsgi_mule_get_msg, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"farm_get_msg", py_uwsgi_farm_get_msg, METH_VARARGS, ""},
|
||||
{"in_farm", py_uwsgi_in_farm, METH_VARARGS, ""},
|
||||
|
||||
{"ready", py_uwsgi_ready, METH_VARARGS, ""},
|
||||
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
|
||||
|
||||
{NULL, NULL},
|
||||
@@ -3130,7 +3151,7 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
if (uwsgi_cache_del(key, keylen, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
@@ -3245,15 +3266,25 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
// TODO FIX THIS !!!
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
if (valsize > 0) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
else if (uwsgi_cache_exists(key, keylen)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_exists(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -3272,16 +3303,20 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_push(message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3302,16 +3337,20 @@ PyObject *py_uwsgi_queue_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_set(pos, message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3337,18 +3376,29 @@ PyObject *py_uwsgi_queue_pull(PyObject * self, PyObject * args) {
|
||||
char *message;
|
||||
uint64_t size;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_pull(&size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3362,18 +3412,29 @@ PyObject *py_uwsgi_queue_pop(PyObject * self, PyObject * args) {
|
||||
char *message;
|
||||
uint64_t size;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_pop(&size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3389,22 +3450,32 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
|
||||
uint64_t size = 0;
|
||||
char *message;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:queue_get", &index)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_get(index, &size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3414,11 +3485,12 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
long num = 0;
|
||||
long i, num = 0;
|
||||
uint64_t size = 0;
|
||||
char *message;
|
||||
PyObject *res = NULL, *zero;
|
||||
PyObject *res = NULL;
|
||||
uint64_t base;
|
||||
char *storage;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|l:queue_last", &num)) {
|
||||
return NULL;
|
||||
@@ -3430,6 +3502,7 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
res = PyList_New(0);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
|
||||
if (uwsgi.queue_header->pos > 0) {
|
||||
@@ -3441,31 +3514,41 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
if (num == 0) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
if (message && size) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
|
||||
|
||||
char **queue_items = uwsgi_malloc(sizeof(char *) * num);
|
||||
uint64_t *queue_items_size = uwsgi_malloc(sizeof(uint64_t) * num);
|
||||
long item_pos = 0;
|
||||
while(num) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
if (message && size) {
|
||||
zero = PyString_FromStringAndSize(message, size);
|
||||
PyList_Append(res, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
if (!message || size == 0) {
|
||||
queue_items[item_pos] = NULL;
|
||||
queue_items_size[item_pos] = 0;
|
||||
}
|
||||
else {
|
||||
queue_items[item_pos] = uwsgi_malloc(size);
|
||||
memcpy(queue_items[item_pos], message, size);
|
||||
queue_items_size[item_pos] = size;
|
||||
}
|
||||
item_pos++;
|
||||
if (base > 0) {
|
||||
base--;
|
||||
}
|
||||
@@ -3474,7 +3557,24 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
}
|
||||
num--;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
for(i=0;i<item_pos;i++) {
|
||||
if (queue_items[i]) {
|
||||
PyObject *zero = PyString_FromStringAndSize(queue_items[i], queue_items_size[i]);
|
||||
PyList_Append(res, zero);
|
||||
Py_DECREF(zero);
|
||||
free(queue_items[i]);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
PyList_Append(res, Py_None);
|
||||
}
|
||||
}
|
||||
free(queue_items);
|
||||
free(queue_items_size);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3492,6 +3592,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
char *value = NULL;
|
||||
char *remote = NULL;
|
||||
char buffer[0xffff];
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
struct timeval tv, tv2;
|
||||
@@ -3523,14 +3624,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
PyObject *ret = PyString_FromStringAndSize(NULL, valsize);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(ret);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(ret);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
char *storage = uwsgi_malloc(valsize);
|
||||
#ifdef UWSGI_DEBUG
|
||||
gettimeofday(&tv2, NULL);
|
||||
if ((tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec) > 30000) {
|
||||
@@ -3540,6 +3634,8 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
memcpy(storage, value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
ret = PyString_FromStringAndSize(storage, valsize);
|
||||
free(storage);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
#define PyVarObject_HEAD_INIT(x, y) PyObject_HEAD_INIT(x) y,
|
||||
#endif
|
||||
|
||||
#define uwsgi_py_write_set_exception(x) PyErr_SetString(PyExc_IOError, "write error");
|
||||
#define uwsgi_py_write_exception(x) uwsgi_py_write_set_exception(x); PyErr_Print();
|
||||
|
||||
|
||||
#define uwsgi_py_check_write_errors if (wsgi_req->write_errors > 0 && uwsgi.write_errors_exception_only) {\
|
||||
uwsgi_py_write_set_exception(wsgi_req);\
|
||||
}\
|
||||
else if (wsgi_req->write_errors > uwsgi.write_errors_tolerance)\
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
@@ -136,9 +144,6 @@ struct uwsgi_python {
|
||||
|
||||
char *callable;
|
||||
|
||||
int ignore_script_name;
|
||||
int catch_exceptions;
|
||||
|
||||
int *current_recursion_depth;
|
||||
struct _frame **current_frame;
|
||||
|
||||
@@ -154,6 +159,8 @@ struct uwsgi_python {
|
||||
pthread_mutex_t lock_pyloaders;
|
||||
void (*gil_get) (void);
|
||||
void (*gil_release) (void);
|
||||
int auto_reload;
|
||||
struct uwsgi_string_list *auto_reload_ignore;
|
||||
#endif
|
||||
|
||||
PyObject *workers_tuple;
|
||||
@@ -251,10 +258,14 @@ void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
|
||||
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
int uwsgi_python_tracer(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
|
||||
void uwsgi_python_reset_random_seed(void);
|
||||
|
||||
char *uwsgi_pythonize(char *);
|
||||
void *uwsgi_python_autoreloader_thread(void *);
|
||||
|
||||
int uwsgi_python_manage_exceptions(void);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
|
||||
@@ -134,9 +134,6 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
@@ -170,11 +167,14 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
Py_DECREF(spit_args);
|
||||
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
goto clear;
|
||||
char *content = PyString_AsString(wsgi_req->async_placeholder);
|
||||
size_t content_len = PyString_Size(wsgi_req->async_placeholder);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,6 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -211,32 +210,28 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
}
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,12 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, content, len);
|
||||
UWSGI_GET_GIL
|
||||
// this is a special case for the write callable
|
||||
// no need to honout write-errors-exception-only
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -363,7 +369,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!up.ignore_script_name) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
@@ -445,8 +451,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (wsgi_req->async_result) {
|
||||
|
||||
|
||||
@@ -466,7 +470,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
else if (up.catch_exceptions) {
|
||||
else if (uwsgi.catch_exceptions) {
|
||||
|
||||
// LOCK THIS PART
|
||||
|
||||
@@ -501,6 +505,16 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
close(tmp_stderr);
|
||||
}
|
||||
|
||||
// this object must be freed/cleared always
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
clear:
|
||||
|
||||
up.reset_ts(wsgi_req, wi);
|
||||
|
||||
@@ -201,6 +201,11 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
UWSGI_GET_GIL
|
||||
#endif
|
||||
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
|
||||
Py_INCREF(up.wsgi_writeout);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
#endif
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
@@ -48,7 +48,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
}
|
||||
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
@@ -69,7 +68,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
|
||||
@@ -85,11 +83,9 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
zero = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
|
||||
|
||||
@@ -108,6 +104,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
@@ -125,16 +122,12 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
|
||||
wsgi_req->async_app = wi->callable;
|
||||
|
||||
|
||||
// export .env only in non-threaded mode
|
||||
#ifndef UWSGI_PYPY
|
||||
if (uwsgi.threads < 2) {
|
||||
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
|
||||
}
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
|
||||
|
||||
@@ -159,26 +152,26 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
// call
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
#ifdef UWSGI_SENDFILE
|
||||
ssize_t sf_len = 0;
|
||||
#endif
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// return or yield ?
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
goto clear;
|
||||
char *content = PyString_AsString(wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size(wsgi_req->async_result);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -195,7 +188,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
@@ -213,7 +205,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -224,15 +215,34 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder);
|
||||
|
||||
|
||||
if (!pychunk) {
|
||||
if (PyErr_Occurred()) {
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
PyErr_Print();
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
}
|
||||
if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "close")) {
|
||||
PyObject *close_method = PyObject_GetAttrString((PyObject *)wsgi_req->async_result, "close");
|
||||
PyObject *close_method_args = PyTuple_New(0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("calling close() for %.*s %p %p\n", wsgi_req->uri_len, wsgi_req->uri, close_method, close_method_args);
|
||||
#endif
|
||||
PyObject *close_method_output = PyEval_CallObject(close_method, close_method_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(close_method_args);
|
||||
Py_XDECREF(close_method_output);
|
||||
Py_DECREF(close_method);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -240,12 +250,16 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
@@ -258,7 +272,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
@@ -266,18 +279,11 @@ clear:
|
||||
if (wsgi_req->sendfile_fd != -1) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
|
||||
}
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
clear2:
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ VALUE rack_uwsgi_cache_del(VALUE *class, VALUE rbkey) {
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
if (uwsgi_cache_del(key, keylen, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
+25
-12
@@ -110,7 +110,18 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
int chunk_size;
|
||||
|
||||
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
|
||||
return Qnil;
|
||||
/*
|
||||
When EOF is reached, this method returns nil if length is given and not nil, or "" if length is not given or is nil.
|
||||
If buffer is given, then the read data will be placed into buffer instead of a newly created String object.
|
||||
*/
|
||||
if (RARRAY_LEN(args) > 0) {
|
||||
if (RARRAY_PTR(args)[0] == Qnil) {
|
||||
return rb_str_new("", 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return rb_str_new("", 0);
|
||||
}
|
||||
|
||||
if (RARRAY_LEN(args) == 0) {
|
||||
@@ -314,6 +325,11 @@ void uwsgi_ruby_gemset(char *gemset) {
|
||||
|
||||
}
|
||||
|
||||
static void rack_hack_dollar_zero(VALUE name, ID id) {
|
||||
ur.dollar_zero = rb_obj_as_string(name);
|
||||
rb_obj_taint(ur.dollar_zero);
|
||||
}
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
@@ -346,6 +362,10 @@ int uwsgi_rack_init(){
|
||||
|
||||
ruby_script("uwsgi");
|
||||
|
||||
ur.dollar_zero = rb_str_new2("uwsgi");
|
||||
rb_define_hooked_variable("$0", &ur.dollar_zero, 0, rack_hack_dollar_zero);
|
||||
rb_define_hooked_variable("$PROGRAM_NAME", &ur.dollar_zero, 0, rack_hack_dollar_zero);
|
||||
|
||||
ur.signals_protector = rb_ary_new();
|
||||
ur.rpc_protector = rb_ary_new();
|
||||
rb_gc_register_address(&ur.signals_protector);
|
||||
@@ -509,18 +529,15 @@ VALUE call_dispatch(VALUE env) {
|
||||
static VALUE send_body(VALUE obj) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
ssize_t len = 0;
|
||||
|
||||
//uwsgi_log("sending body\n");
|
||||
if (TYPE(obj) == T_STRING) {
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("UNMANAGED BODY TYPE %d\n", TYPE(obj));
|
||||
}
|
||||
|
||||
wsgi_req->response_size += len;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -701,7 +718,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
VALUE dws_wr = Data_Wrap_Struct(ur.rb_uwsgi_io_class, 0, 0, wsgi_req);
|
||||
|
||||
if (wsgi_req->async_post) {
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno(wsgi_req->async_post)), rb_str_new("r",1) ));
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno((FILE*)wsgi_req->async_post)), rb_str_new("r",1) ));
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(ur.rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
|
||||
@@ -754,9 +771,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->hvec[5].iov_base = (char *) "\r\n";
|
||||
wsgi_req->hvec[5].iov_len = 2 ;
|
||||
|
||||
if ( !(wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6)) ) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
|
||||
|
||||
headers = RARRAY_PTR(ret)[1] ;
|
||||
if (rb_respond_to( headers, rb_intern("each") )) {
|
||||
@@ -767,9 +782,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2) != 2) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2);
|
||||
|
||||
body = RARRAY_PTR(ret)[2] ;
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ struct uwsgi_rack {
|
||||
VALUE signals_protector;
|
||||
VALUE rpc_protector;
|
||||
|
||||
VALUE dollar_zero;
|
||||
|
||||
VALUE dispatcher;
|
||||
VALUE rb_uwsgi_io_class;
|
||||
ID call;
|
||||
|
||||
@@ -7,6 +7,7 @@ extern struct uwsgi_server uwsgi;
|
||||
ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
char buf[MAX_SYSLOG_PKT];
|
||||
char ctime_storage[26];
|
||||
time_t current_time;
|
||||
int portn = 514;
|
||||
int rlen;
|
||||
@@ -55,8 +56,12 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
|
||||
// drop newline
|
||||
if (message[len-1] == '\n') len--;
|
||||
|
||||
rlen = snprintf(buf, MAX_SYSLOG_PKT, "<29>%.*s %s: %.*s", 15, ctime(¤t_time)+4, (char *) ul->data, (int) len, message);
|
||||
#ifdef __sun__
|
||||
ctime_r(¤t_time, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r(¤t_time, ctime_storage);
|
||||
#endif
|
||||
rlen = snprintf(buf, MAX_SYSLOG_PKT, "<29>%.*s %s: %.*s", 15, ctime_storage+4, (char *) ul->data, (int) len, message);
|
||||
if (rlen > 0) {
|
||||
return sendto(ul->fd, buf, rlen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
}
|
||||
|
||||
@@ -7,14 +7,15 @@ int uwsgi_request_signal(struct wsgi_request *wsgi_req) {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t ret_status = 1;
|
||||
struct uwsgi_header uh;
|
||||
if (uwsgi_signal_send(uwsgi.signal_socket, wsgi_req->uh.modifier2) < 0) {
|
||||
ret_status = 0;
|
||||
}
|
||||
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = ret_status;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = ret_status;
|
||||
len = write(wsgi_req->poll.fd, &uh, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
char spool_filename[1024];
|
||||
struct uwsgi_header uh;
|
||||
|
||||
// get the spooler from the modifier2
|
||||
|
||||
@@ -24,11 +25,11 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize, NULL, 0, NULL, 0);
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (i > 0) {
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
if (write(wsgi_req->poll.fd, wsgi_req, 4) != 4) {
|
||||
uh.modifier2 = 1;
|
||||
if (write(wsgi_req->poll.fd, &uh, 4) != 4) {
|
||||
uwsgi_log("disconnected client, remove spool file.\n");
|
||||
/* client disconnect, remove spool file */
|
||||
if (unlink(spool_filename)) {
|
||||
@@ -41,8 +42,8 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
else {
|
||||
/* announce a failed spool request */
|
||||
wsgi_req->uh.modifier2 = 0;
|
||||
i = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
uh.modifier2 = 0;
|
||||
i = write(wsgi_req->poll.fd, &uh, 4);
|
||||
if (i != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
@@ -4,9 +4,63 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_syslog_facility {
|
||||
const char *name;
|
||||
int facility;
|
||||
};
|
||||
|
||||
struct uwsgi_syslog_facility usf[] = {
|
||||
|
||||
{ "auth", LOG_AUTH, },
|
||||
#ifdef LOG_AUTHPRIV
|
||||
{ "authpriv", LOG_AUTHPRIV, },
|
||||
#endif
|
||||
{ "cron", LOG_CRON, },
|
||||
{ "daemon", LOG_DAEMON, },
|
||||
#ifdef LOG_FTP
|
||||
{ "ftp", LOG_FTP, },
|
||||
#endif
|
||||
#ifdef LOG_INSTALL
|
||||
{ "install", LOG_INSTALL },
|
||||
#endif
|
||||
{ "kern", LOG_KERN, },
|
||||
{ "lpr", LOG_LPR, },
|
||||
{ "mail", LOG_MAIL, },
|
||||
#ifdef INTERNAL_MARK
|
||||
{ "mark", INTERNAL_MARK, }, /* INTERNAL */
|
||||
#endif
|
||||
#ifdef LOG_NETINFO
|
||||
{ "netinfo", LOG_NETINFO, },
|
||||
#endif
|
||||
#ifdef LOG_RAS
|
||||
{ "ras", LOG_RAS },
|
||||
#endif
|
||||
#ifdef LOG_REMOTEAUTH
|
||||
{ "remoteauth", LOG_REMOTEAUTH },
|
||||
#endif
|
||||
{ "news", LOG_NEWS, },
|
||||
{ "security", LOG_AUTH }, /* DEPRECATED */
|
||||
{ "syslog", LOG_SYSLOG, },
|
||||
{ "user", LOG_USER, },
|
||||
{ "uucp", LOG_UUCP, },
|
||||
{ "local0", LOG_LOCAL0, },
|
||||
{ "local1", LOG_LOCAL1, },
|
||||
{ "local2", LOG_LOCAL2, },
|
||||
{ "local3", LOG_LOCAL3, },
|
||||
{ "local4", LOG_LOCAL4, },
|
||||
{ "local5", LOG_LOCAL5, },
|
||||
{ "local6", LOG_LOCAL6, },
|
||||
{ "local7", LOG_LOCAL7, },
|
||||
#ifdef LOG_LAUNCHD
|
||||
{ "launchd", LOG_LAUNCHD },
|
||||
#endif
|
||||
{ NULL, -1, }
|
||||
};
|
||||
|
||||
ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
char *syslog_opts;
|
||||
int facility = LOG_DAEMON;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
@@ -16,10 +70,25 @@ ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
syslog_opts = "uwsgi";
|
||||
}
|
||||
else {
|
||||
syslog_opts = uwsgi.choosen_logger_arg;
|
||||
char *colon = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (colon) {
|
||||
struct uwsgi_syslog_facility *fn = usf;
|
||||
while(fn->name) {
|
||||
if (!strcmp(fn->name, colon+1)) {
|
||||
facility = fn->facility;
|
||||
break;
|
||||
}
|
||||
fn++;
|
||||
}
|
||||
syslog_opts = uwsgi_str(uwsgi.choosen_logger_arg);
|
||||
syslog_opts[colon-uwsgi.choosen_logger_arg] = 0;
|
||||
}
|
||||
else {
|
||||
syslog_opts = uwsgi.choosen_logger_arg;
|
||||
}
|
||||
}
|
||||
|
||||
openlog(syslog_opts, 0, LOG_DAEMON);
|
||||
openlog(syslog_opts, 0, facility);
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
+29
-9
@@ -193,22 +193,42 @@ ssize_t uwsgi_proto_fastcgi_write(struct wsgi_request * wsgi_req, char *buf, siz
|
||||
if (len <= 65535) {
|
||||
rlen = write(wsgi_req->poll.fd, &fr, 8);
|
||||
if (rlen <= 0) {
|
||||
return rlen;
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
return write(wsgi_req->poll.fd, buf, len);
|
||||
rlen = write(wsgi_req->poll.fd, buf, len);
|
||||
if (rlen <= 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
else {
|
||||
while(len > 0) {
|
||||
chunk_len = UMIN(65535, len);
|
||||
fr.cl = htons(chunk_len);
|
||||
rlen = write(wsgi_req->poll.fd, &fr, 8);
|
||||
if (rlen <= 0) {
|
||||
return rlen;
|
||||
}
|
||||
if (rlen != 8) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
rlen = write(wsgi_req->poll.fd, ptr, chunk_len);
|
||||
if (rlen <= 0) {
|
||||
return rlen;
|
||||
}
|
||||
if (rlen != 8) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
ptr += rlen;
|
||||
len -= rlen;
|
||||
}
|
||||
@@ -224,7 +244,7 @@ ssize_t uwsgi_proto_fastcgi_write_header(struct wsgi_request * wsgi_req, char *b
|
||||
void uwsgi_proto_fastcgi_close(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (write(wsgi_req->poll.fd, FCGI_END_REQUEST, 24) <= 0) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
|
||||
uwsgi_proto_base_close(wsgi_req);
|
||||
|
||||
@@ -369,19 +369,3 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_http_writev_header(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
return writev(wsgi_req->poll.fd, iovec, iov_len);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_http_writev(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
return writev(wsgi_req->poll.fd, iovec, iov_len);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_http_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
return write(wsgi_req->poll.fd, buf, len);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_http_write_header(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
return write(wsgi_req->poll.fd, buf, len);
|
||||
}
|
||||
|
||||
+27
-21
@@ -114,38 +114,44 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_uwsgi_writev_header(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
ssize_t uwsgi_proto_uwsgi_writev_header(struct wsgi_request *wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
if (iov_len == 0) return 0;
|
||||
ssize_t wlen = writev(wsgi_req->poll.fd, iovec, iov_len);
|
||||
if (wlen < 0) {
|
||||
uwsgi_req_error("writev()");
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("writev()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_uwsgi_writev(struct wsgi_request * wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
ssize_t wlen = writev(wsgi_req->poll.fd, iovec, iov_len);
|
||||
if (wlen < 0) {
|
||||
uwsgi_req_error("writev()");
|
||||
return 0;
|
||||
}
|
||||
return wlen;
|
||||
ssize_t uwsgi_proto_uwsgi_writev(struct wsgi_request *wsgi_req, struct iovec * iovec, size_t iov_len) {
|
||||
return uwsgi_proto_uwsgi_writev_header(wsgi_req, iovec, iov_len);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_uwsgi_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
ssize_t wlen = write(wsgi_req->poll.fd, buf, len);
|
||||
if (wlen < 0) {
|
||||
uwsgi_req_error("write()");
|
||||
return 0;
|
||||
ssize_t wlen;
|
||||
char *ptr = buf;
|
||||
if (len == 0) return 0;
|
||||
|
||||
while(len > 0) {
|
||||
wlen = write(wsgi_req->poll.fd, ptr, len);
|
||||
if (wlen <= 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return ptr-buf;
|
||||
}
|
||||
ptr+=wlen;
|
||||
len -= wlen;
|
||||
}
|
||||
return wlen;
|
||||
|
||||
return ptr-buf;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_uwsgi_write_header(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
ssize_t wlen = write(wsgi_req->poll.fd, buf, len);
|
||||
if (wlen < 0) {
|
||||
uwsgi_req_error("write()");
|
||||
return 0;
|
||||
}
|
||||
return wlen;
|
||||
ssize_t uwsgi_proto_uwsgi_write_header(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
return uwsgi_proto_uwsgi_write(wsgi_req, buf, len);
|
||||
}
|
||||
|
||||
+29
-6
@@ -96,6 +96,17 @@ static int uwsgi_mongrel2_json_parse(json_t * root, struct wsgi_request *wsgi_re
|
||||
}
|
||||
}
|
||||
|
||||
if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-forwarded-for"))) {
|
||||
char *colon = strchr(json_val, ',');
|
||||
if (colon) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - json_val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, json_val, strlen(json_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((json_val = uwsgi_mongrel2_json_get_string(root, "content-length"))) {
|
||||
wsgi_req->post_cl = atoi(json_val);
|
||||
}
|
||||
@@ -184,9 +195,9 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
else {
|
||||
// add header
|
||||
if (!uwsgi_strncmp("host", 4, key, keylen)) {
|
||||
char *colon = strchr(val, ':');
|
||||
char *colon = memchr(val, ':', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, (colon + 1) - val);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1)-val));
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
|
||||
@@ -200,12 +211,20 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
wsgi_req->async_post = fopen(post_filename, "r");
|
||||
if (!wsgi_req->async_post) {
|
||||
uwsgi_error_open(post_filename);
|
||||
free(post_filename);
|
||||
wsgi_req->do_not_log = 1;
|
||||
}
|
||||
async_upload += 2;
|
||||
free(post_filename);
|
||||
}
|
||||
else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
|
||||
char *colon = memchr(val, ',', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) {
|
||||
async_upload += 1;
|
||||
}
|
||||
@@ -416,7 +435,8 @@ ssize_t uwsgi_proto_zeromq_writev_header(struct wsgi_request *wsgi_req, struct i
|
||||
for (i = 0; i < (int) iov_len; i++) {
|
||||
len = uwsgi_proto_zeromq_write(wsgi_req, iovec[i].iov_base, iovec[i].iov_len);
|
||||
if (len <= 0) {
|
||||
return len;
|
||||
wsgi_req->write_errors++;
|
||||
return 0;
|
||||
}
|
||||
ret += len;
|
||||
}
|
||||
@@ -442,10 +462,13 @@ ssize_t uwsgi_proto_zeromq_write(struct wsgi_request * wsgi_req, char *buf, size
|
||||
zmq_msg_init_data(&reply, zmq_body, wsgi_req->proto_parser_pos + len, uwsgi_proto_zeromq_free, NULL);
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.zmq_lock);
|
||||
if (zmq_send(uwsgi.zmq_pub, &reply, 0)) {
|
||||
uwsgi_error("zmq_send()");
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("zmq_send()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.zmq_lock);
|
||||
zmq_msg_close(&reply);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.zmq_lock);
|
||||
zmq_msg_close(&reply);
|
||||
|
||||
+311
-73
@@ -16,7 +16,8 @@ static size_t get_content_length(char *buf, uint16_t size) {
|
||||
return val;
|
||||
}
|
||||
|
||||
void set_http_date(time_t t, char *dst) {
|
||||
|
||||
int set_http_date(time_t t, char *header, int header_len, char *dst, int last) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -26,12 +27,96 @@ void set_http_date(time_t t, char *dst) {
|
||||
};
|
||||
|
||||
struct tm *hdtm = gmtime(&t);
|
||||
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
|
||||
|
||||
if (last) {
|
||||
return snprintf(dst, 36+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
|
||||
header_len, header,
|
||||
week[hdtm->tm_wday], hdtm->tm_mday,
|
||||
months[hdtm->tm_mon], hdtm->tm_year+1900,
|
||||
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
|
||||
}
|
||||
|
||||
return snprintf(dst, 34+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
header_len, header,
|
||||
week[hdtm->tm_wday], hdtm->tm_mday,
|
||||
months[hdtm->tm_mon], hdtm->tm_year+1900,
|
||||
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
|
||||
}
|
||||
|
||||
void uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
|
||||
time_t now = wsgi_req->start_of_request.tv_sec;
|
||||
// Expires+34+1
|
||||
char expires[42];
|
||||
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_type_mtime;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
|
||||
time_t now = wsgi_req->start_of_request.tv_sec;
|
||||
// Expires+34+1
|
||||
char expires[42];
|
||||
|
||||
while(udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_mtime;
|
||||
while(udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// only RFC 1123 is supported
|
||||
time_t parse_http_date(char *date, uint16_t len) {
|
||||
|
||||
@@ -916,7 +1001,7 @@ next:
|
||||
udd->vallen = strlen(udd->value);
|
||||
}
|
||||
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
|
||||
return -1;
|
||||
}
|
||||
nextcs:
|
||||
@@ -944,11 +1029,11 @@ nextcs:
|
||||
if (!real_docroot) goto nextsm;
|
||||
udd->value = real_docroot;
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1;
|
||||
udd->status = 1 + uwsgi_is_file(real_docroot);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen, udd->status-1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -956,11 +1041,51 @@ nextsm:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
// check for static_maps in append mode
|
||||
udd = uwsgi.static_maps2;
|
||||
while(udd) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
|
||||
#endif
|
||||
if (udd->status == 0) {
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
|
||||
#endif
|
||||
char *real_docroot = uwsgi_malloc(PATH_MAX+1);
|
||||
if (!realpath(udd->value, real_docroot)) {
|
||||
free(real_docroot);
|
||||
udd->value = NULL;
|
||||
}
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
if (!real_docroot) goto nextsm2;
|
||||
udd->value = real_docroot;
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1 + uwsgi_is_file(real_docroot);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, udd->status-1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
nextsm2:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
|
||||
// finally check for docroot
|
||||
if (uwsgi.check_static_docroot && wsgi_req->document_root_len > 0) {
|
||||
if (!uwsgi_file_serve(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
char *real_docroot = uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, NULL);
|
||||
if (!real_docroot) {
|
||||
return -1;
|
||||
}
|
||||
if (!uwsgi_file_serve(wsgi_req, real_docroot, strlen(real_docroot), wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
|
||||
free(real_docroot);
|
||||
return -1;
|
||||
}
|
||||
free(real_docroot);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1514,31 +1639,41 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
udd->hits++;
|
||||
// auto optimization
|
||||
if (udd->prev) {
|
||||
if (udd->hits > udd->prev->hits) {
|
||||
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
|
||||
if (udd_parent) {
|
||||
udd_parent->next = udd;
|
||||
}
|
||||
udd_prev->prev = udd;
|
||||
udd_prev->next = udd->next;
|
||||
if (!ext) return NULL;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
udd->hits++;
|
||||
// auto optimization
|
||||
if (udd->prev) {
|
||||
if (udd->hits > udd->prev->hits) {
|
||||
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
|
||||
if (udd_parent) {
|
||||
udd_parent->next = udd;
|
||||
}
|
||||
|
||||
if (udd->next) {
|
||||
udd->next->prev = udd_prev;
|
||||
}
|
||||
|
||||
udd_prev->prev = udd;
|
||||
udd_prev->next = udd->next;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
|
||||
if (udd->prev == NULL) {
|
||||
uwsgi.mimetypes = udd;
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1593,58 +1728,26 @@ int uwsgi_static_stat(char *filename, struct stat *st) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
struct stat st;
|
||||
struct iovec headers_vec[8];
|
||||
char real_filename[PATH_MAX+1];
|
||||
|
||||
int mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
char content_length[sizeof(UMAX64_STR)+1];
|
||||
size_t real_filename_len = 0;
|
||||
|
||||
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &st)) {
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
int mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
if (st.st_mtime <= ims) {
|
||||
if (st->st_mtime <= ims) {
|
||||
wsgi_req->status = 304;
|
||||
headers_vec[0].iov_base = wsgi_req->protocol;
|
||||
headers_vec[0].iov_len = wsgi_req->protocol_len;
|
||||
@@ -1691,6 +1794,10 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
#endif
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
headers_vec[0].iov_base = "Content-Type: ";
|
||||
@@ -1701,6 +1808,9 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
// check for content-type related headers
|
||||
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
|
||||
}
|
||||
|
||||
// nginx
|
||||
@@ -1710,7 +1820,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
}
|
||||
@@ -1721,7 +1831,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
}
|
||||
@@ -1730,12 +1840,12 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
// set Content-Length
|
||||
headers_vec[0].iov_base = "Content-Length: ";
|
||||
headers_vec[0].iov_len = 16;
|
||||
headers_vec[1].iov_len = uwsgi_long2str2n(st.st_size, content_length, sizeof(UMAX64_STR)+1);
|
||||
headers_vec[1].iov_len = uwsgi_long2str2n(st->st_size, content_length, sizeof(UMAX64_STR)+1);
|
||||
headers_vec[1].iov_base = content_length;
|
||||
headers_vec[2].iov_base = "\r\n";
|
||||
headers_vec[2].iov_len = 2;
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
headers_vec[3].iov_base = http_last_modified;
|
||||
headers_vec[3].iov_len = 48;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
|
||||
@@ -1749,6 +1859,134 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *uwsgi_static_offload_thread(void *req) {
|
||||
|
||||
struct uwsgi_offload_request *uof_req = (struct uwsgi_offload_request *) req;
|
||||
|
||||
uwsgi_real_file_serve(&uof_req->wsgi_req, uof_req->real_filename, uof_req->real_filename_len, &uof_req->st);
|
||||
|
||||
// close the connection with the webserver
|
||||
if (!uof_req->wsgi_req.fd_closed || !uof_req->wsgi_req.body_as_file) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
uof_req->wsgi_req.socket->proto_close(&uof_req->wsgi_req);
|
||||
}
|
||||
|
||||
// free buffer
|
||||
free(uof_req->buffer);
|
||||
// free hvec
|
||||
free(uof_req->hvec);
|
||||
free(uof_req);
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads--;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {
|
||||
|
||||
struct stat st;
|
||||
char real_filename[PATH_MAX+1];
|
||||
size_t real_filename_len = 0;
|
||||
char *filename = NULL;
|
||||
|
||||
|
||||
if (!is_a_file) {
|
||||
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
}
|
||||
else {
|
||||
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &st)) {
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
// Ok, the file must be served as static from uWSGI
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uint64_t offload_thread_count = uwsgi.workers[uwsgi.mywid].static_offload_threads;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (offload_thread_count > (uint64_t) uwsgi.static_offload_to_thread) {
|
||||
uwsgi_log_verbose("OVERLOAD !!! unable to offload static file serving\n");
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
|
||||
|
||||
// buffer
|
||||
uor->buffer = uwsgi_malloc(uwsgi.buffer_size); memcpy(uor->buffer, wsgi_req->buffer, uwsgi.buffer_size);
|
||||
// iovec
|
||||
uor->hvec = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size); memcpy(uor->hvec, wsgi_req->hvec, sizeof(struct iovec) * uwsgi.vec_size);
|
||||
|
||||
// wsgi_req
|
||||
memcpy(&uor->wsgi_req, wsgi_req, sizeof(struct wsgi_request));
|
||||
|
||||
uor->wsgi_req.buffer = uor->buffer;
|
||||
uor->wsgi_req.hvec = uor->hvec;
|
||||
|
||||
// stat
|
||||
memcpy(&uor->st, &st, sizeof(struct stat));
|
||||
|
||||
// filename
|
||||
memcpy(uor->real_filename, real_filename, real_filename_len);
|
||||
uor->real_filename_len = real_filename_len;
|
||||
|
||||
// avoid closing the connection
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads++;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (pthread_create(&uor->tid, &uwsgi.static_offload_thread_attr, uwsgi_static_offload_thread, (void *) uor)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
// bad condition, better to exit...
|
||||
exit(1);
|
||||
}
|
||||
wsgi_req->status = -30;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -26,7 +26,6 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
routes = routes->next;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from threading import Thread
|
||||
import time
|
||||
import uwsgi
|
||||
|
||||
def mess():
|
||||
while True:
|
||||
for i in xrange(0, 100):
|
||||
if uwsgi.ready():
|
||||
uwsgi.signal(17)
|
||||
print(i)
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
@@ -31,15 +31,15 @@ def patch_bin_path(cmd, conf):
|
||||
|
||||
bin_name = conf.get('bin_name')
|
||||
|
||||
try:
|
||||
if not os.path.exists(cmd.install_scripts):
|
||||
os.makedirs(cmd.install_scripts)
|
||||
if not os.path.isabs(bin_name):
|
||||
print('Patching "bin_name" to properly install_scripts dir')
|
||||
if not os.path.isabs(bin_name):
|
||||
print('Patching "bin_name" to properly install_scripts dir')
|
||||
try:
|
||||
if not os.path.exists(cmd.install_scripts):
|
||||
os.makedirs(cmd.install_scripts)
|
||||
conf.set('bin_name',
|
||||
os.path.join(cmd.install_scripts, conf.get('bin_name')))
|
||||
except:
|
||||
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
|
||||
os.path.join(cmd.install_scripts, conf.get('bin_name')))
|
||||
except:
|
||||
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
|
||||
|
||||
|
||||
class uWSGIBuilder(build_ext):
|
||||
|
||||
@@ -559,3 +559,33 @@ cycle:
|
||||
return received_signal;
|
||||
}
|
||||
|
||||
void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
|
||||
ssize_t ret = read(fd, &uwsgi_signal, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
destroy:
|
||||
// better to kill the whole worker...
|
||||
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
|
||||
end_me(0);
|
||||
|
||||
}
|
||||
|
||||
@@ -354,8 +354,8 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
|
||||
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
|
||||
uwsgi.snmp = 1;
|
||||
if (value) {
|
||||
uwsgi.snmp_addr = optarg;
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.snmp_addr = value;
|
||||
uwsgi.master_process = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -758,6 +758,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
// set non-blocking socket
|
||||
void uwsgi_socket_nb(int fd) {
|
||||
int arg;
|
||||
|
||||
@@ -774,10 +775,28 @@ void uwsgi_socket_nb(int fd) {
|
||||
|
||||
}
|
||||
|
||||
// set blocking socket
|
||||
void uwsgi_socket_b(int fd) {
|
||||
int arg;
|
||||
|
||||
arg = fcntl(fd, F_GETFL, NULL);
|
||||
if (arg < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return;
|
||||
}
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout, int async) {
|
||||
|
||||
int arg, ret;
|
||||
int soopt;
|
||||
int soopt = 0;
|
||||
socklen_t solen = sizeof(int);
|
||||
int cnt;
|
||||
/* set non-blocking socket */
|
||||
@@ -847,7 +866,6 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -916,6 +934,7 @@ struct uwsgi_socket *uwsgi_new_shared_socket(char *name) {
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
|
||||
uwsgi_sock->name = name;
|
||||
uwsgi_sock->fd = -1;
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
@@ -943,6 +962,7 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
|
||||
uwsgi_sock->name = name;
|
||||
uwsgi_sock->fd = -1;
|
||||
|
||||
if (!name)
|
||||
return uwsgi_sock;
|
||||
@@ -1012,10 +1032,6 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
union uwsgi_sockaddr usa;
|
||||
int abstract = 0;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("creating socket from fd %d\n", fd);
|
||||
#endif
|
||||
|
||||
socket_type_len = sizeof(struct sockaddr_un);
|
||||
gsa.sa = &usa.sa;
|
||||
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
|
||||
@@ -1221,12 +1237,11 @@ void uwsgi_add_sockets_to_queue(int queue) {
|
||||
uwsgi_sock->fd = connect_to_sctp(uwsgi_sock->name, queue);
|
||||
uwsgi_sock->queue = queue;
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd);
|
||||
#ifdef UWSGI_SCTP
|
||||
if (uwsgi_sock->fd > -1) {
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd);
|
||||
}
|
||||
#endif
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
@@ -1236,7 +1251,9 @@ void uwsgi_del_sockets_from_queue(int queue) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->fd == -1) goto nextsock;
|
||||
event_queue_del_fd(queue, uwsgi_sock->fd, event_queue_read());
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
@@ -1255,6 +1272,34 @@ int uwsgi_is_bad_connection(int fd) {
|
||||
return soopt;
|
||||
}
|
||||
|
||||
int uwsgi_socket_is_already_bound(char *name) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_sock->name && !strcmp(uwsgi_sock->name, name) && uwsgi_sock->bound) {
|
||||
return 1;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_socket_uniq(struct uwsgi_socket *list, struct uwsgi_socket *item) {
|
||||
int found = 0;
|
||||
|
||||
if (list == item) return 0;
|
||||
struct uwsgi_socket *uwsgi_sock = list;
|
||||
while(uwsgi_sock && uwsgi_sock != item) {
|
||||
if (uwsgi_sock->fd == -1) goto nextsock;
|
||||
if (!strcmp(uwsgi_sock->name, item->name)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void uwsgi_manage_zerg(int fd, int num_sockets, int *sockets) {
|
||||
struct sockaddr_un zsun;
|
||||
socklen_t zsun_len = sizeof(struct sockaddr_un);
|
||||
@@ -1298,11 +1343,19 @@ void uwsgi_manage_zerg(int fd, int num_sockets, int *sockets) {
|
||||
|
||||
if (!sockets) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
int uniq_count = 0;
|
||||
while (uwsgi_sock) {
|
||||
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
|
||||
zerg_fd_ptr += sizeof(int);
|
||||
if (uwsgi_sock->fd == -1) goto nextsock;
|
||||
if (!uwsgi_socket_uniq(uwsgi.sockets, uwsgi_sock)) {
|
||||
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
|
||||
zerg_fd_ptr += sizeof(int);
|
||||
uniq_count++;
|
||||
}
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
zerg_iov[1].iov_base = &uniq_count;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * uniq_count);
|
||||
}
|
||||
else {
|
||||
memcpy(zerg_fd_ptr, sockets, sizeof(int) * num_sockets);
|
||||
|
||||
@@ -101,7 +101,7 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
|
||||
uwsgi_fixup_fds(0, 0, NULL);
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
@@ -109,7 +109,7 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
@@ -237,7 +237,8 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
// here the file will be unlocked too
|
||||
close(fd);
|
||||
|
||||
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
|
||||
|
||||
// and here waiting threads can continue
|
||||
uwsgi_unlock(uspool->lock);
|
||||
@@ -309,6 +310,9 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
|
||||
// reset the tasks counter
|
||||
uspool->tasks = 0;
|
||||
|
||||
for (;;) {
|
||||
|
||||
|
||||
@@ -336,19 +340,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
|
||||
if (uwsgi.master_process) {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
|
||||
uint8_t uwsgi_signal;
|
||||
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
|
||||
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
|
||||
end_me(0);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to the spooler\n", uwsgi_signal);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on the spooler\n", uwsgi_signal);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,6 +352,12 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
}
|
||||
wakeup = tmp_wakeup;
|
||||
|
||||
// need to recycle ?
|
||||
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
|
||||
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
|
||||
end_me(0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,20 +451,30 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
spool_fd = open(task, O_RDWR);
|
||||
|
||||
if (spool_fd < 0) {
|
||||
uwsgi_error_open(task);
|
||||
if (errno != ENOENT)
|
||||
uwsgi_error_open(task);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the file is locked by anther process
|
||||
// check if the file is locked by another process
|
||||
if (uwsgi_fcntl_is_locked(spool_fd)) {
|
||||
close(spool_fd);
|
||||
uwsgi_protected_close(spool_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (read(spool_fd, &uh, 4) != 4) {
|
||||
// unlink() can destroy the lock !!!
|
||||
if (access(task, R_OK | W_OK)) {
|
||||
uwsgi_protected_close(spool_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t rlen = uwsgi_protected_read(spool_fd, &uh, 4);
|
||||
|
||||
if (rlen != 4) {
|
||||
// it could be here for broken file or just opened one
|
||||
uwsgi_error("read()");
|
||||
close(spool_fd);
|
||||
if (rlen < 0)
|
||||
uwsgi_error("read()");
|
||||
uwsgi_protected_close(spool_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -474,10 +482,10 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
uh.pktsize = uwsgi_swap16(uh.pktsize);
|
||||
#endif
|
||||
|
||||
if (read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
|
||||
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
|
||||
uwsgi_error("read()");
|
||||
destroy_spool(dir, task);
|
||||
close(spool_fd);
|
||||
uwsgi_protected_close(spool_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -485,19 +493,20 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
if (sf_lstat.st_size > (uh.pktsize+4)) {
|
||||
body_len = sf_lstat.st_size - (uh.pktsize+4);
|
||||
body = uwsgi_malloc(body_len);
|
||||
if ((size_t)read(spool_fd, body, body_len) != body_len) {
|
||||
if ((size_t)uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
|
||||
uwsgi_error("read()");
|
||||
destroy_spool(dir, task);
|
||||
close(spool_fd);
|
||||
uwsgi_protected_close(spool_fd);
|
||||
free(body);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not the task is running and should not be waken
|
||||
// now the task is running and should not be waken up
|
||||
uspool->running = 1;
|
||||
|
||||
uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);
|
||||
|
||||
|
||||
// chdir before running the task (if requested)
|
||||
@@ -508,7 +517,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
}
|
||||
|
||||
int callable_found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->spooler) {
|
||||
time_t now = time(NULL);
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
@@ -520,8 +529,11 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
}
|
||||
if (ret == 0) continue;
|
||||
callable_found = 1;
|
||||
// increase task counter
|
||||
uspool->tasks++;
|
||||
if (ret == -2) {
|
||||
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, time(NULL)-now);
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, time(NULL)-now);
|
||||
destroy_spool(dir, task);
|
||||
}
|
||||
// re-spool it
|
||||
@@ -533,7 +545,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
free(body);
|
||||
|
||||
// here we free and unlock the task
|
||||
close(spool_fd);
|
||||
uwsgi_protected_close(spool_fd);
|
||||
uspool->running = 0;
|
||||
|
||||
if (!callable_found) {
|
||||
|
||||
@@ -8,12 +8,15 @@ if ($rpc_value) {
|
||||
}
|
||||
|
||||
my $app = sub {
|
||||
my $env = shift;
|
||||
uwsgi::cache_set("key1", "val1");
|
||||
print uwsgi::call('hello');
|
||||
return [
|
||||
my $env = shift;
|
||||
uwsgi::cache_set("key1", "val1");
|
||||
if ($rpc_value) {
|
||||
print uwsgi::call('hello')."\n";
|
||||
}
|
||||
print 'pid '.$$."\n";
|
||||
return [
|
||||
'200',
|
||||
[ 'Content-Type' => 'text/plain' ],
|
||||
[ "Hello World\r\n", $env->{'REQUEST_URI'}, uwsgi::cache_get('key1'), uwsgi::call('hello') ],
|
||||
];
|
||||
];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
def application(e, sr):
|
||||
time.sleep(3)
|
||||
print("3 seconds elapsed")
|
||||
sr('200 Ok', [('Content-Type', 'text/html')])
|
||||
|
||||
time.sleep(2)
|
||||
print("2 seconds elapsed")
|
||||
|
||||
yield "part1"
|
||||
|
||||
try:
|
||||
time.sleep(2)
|
||||
except:
|
||||
print("CLIENT DISCONNECTED !!!")
|
||||
print("2 seconds elapsed")
|
||||
|
||||
yield "part2"
|
||||
|
||||
try:
|
||||
time.sleep(2)
|
||||
except:
|
||||
print("CLIENT DISCONNECTED !!!")
|
||||
print("2 seconds elapsed")
|
||||
|
||||
yield "part3"
|
||||
|
||||
time.sleep(2)
|
||||
print("2 seconds elapsed")
|
||||
|
||||
yield "part4"
|
||||
|
||||
print("end of request")
|
||||
@@ -1,3 +1,4 @@
|
||||
# uwsgi --async 1000 --ugreen
|
||||
import uwsgi
|
||||
import psycopg2
|
||||
|
||||
@@ -12,9 +13,11 @@ def async_wait(conn):
|
||||
if state == psycopg2.extensions.POLL_OK:
|
||||
break
|
||||
elif state == psycopg2.extensions.POLL_READ:
|
||||
uwsgi.green_wait_fdread(conn.fileno())
|
||||
uwsgi.wait_fd_read(conn.fileno())
|
||||
uwsgi.suspend()
|
||||
elif state == psycopg2.extensions.POLL_WRITE:
|
||||
uwsgi.green_wait_fdwrite(conn.fileno())
|
||||
uwsgi.wait_fd_write(conn.fileno())
|
||||
uwsgi.suspend()
|
||||
else:
|
||||
raise Exception("Unexpected result from poll: %r", state)
|
||||
|
||||
@@ -26,7 +29,7 @@ def application(env, start_response):
|
||||
|
||||
start_response('200 Ok', [('Content-type', 'text/html')])
|
||||
|
||||
conn = psycopg2.connect("dbname=prova user=postgres", async=True)
|
||||
conn = psycopg2.connect("dbname=template1 user=postgres", async=True)
|
||||
|
||||
# suspend until connection
|
||||
async_wait(conn)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# uwsgi -s :3031 -M -p 4 --plugin gevent --loop gevent --async 1000 --enable-threads -w tests.testgevent
|
||||
from threading import Thread
|
||||
import gevent
|
||||
import uwsgi
|
||||
import time
|
||||
|
||||
def microtask(wid):
|
||||
print "i am a gevent task"
|
||||
gevent.sleep(10)
|
||||
print "10 seconds elapsed in worker id %d" % wid
|
||||
|
||||
def athread():
|
||||
while True:
|
||||
time.sleep(1)
|
||||
print "i am the thread 1"
|
||||
|
||||
def athread2():
|
||||
while True:
|
||||
time.sleep(1)
|
||||
print "i am the thread 2"
|
||||
|
||||
t1 = Thread(target=athread)
|
||||
t1.daemon = True
|
||||
t1.start()
|
||||
|
||||
t2 = Thread(target=athread2)
|
||||
t2.daemon = True
|
||||
t2.start()
|
||||
|
||||
def application(environ, start_response):
|
||||
|
||||
gevent.sleep()
|
||||
start_response('200 OK', [('Content-Type','text/html')])
|
||||
yield "sleeping for 3 seconds...<br/>"
|
||||
gevent.sleep(3)
|
||||
yield "done<br/>"
|
||||
gevent.spawn(microtask, uwsgi.worker_id())
|
||||
yield "microtask started<br/>"
|
||||
|
||||
@@ -5,6 +5,11 @@ import os
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
print(env.__class__)
|
||||
print(env['PATH_INFO'])
|
||||
print(env['REQUEST_METHOD'])
|
||||
print(env['wsgi.input'])
|
||||
|
||||
if env['PATH_INFO'].startswith('/progress/'):
|
||||
start_response('200 Ok', [('Content-type', 'application/json')])
|
||||
filename = 'foobar/' + env['PATH_INFO'][10:]
|
||||
|
||||
@@ -153,7 +153,7 @@ void daemonize(char *logfile) {
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -168,7 +168,7 @@ void daemonize(char *logfile) {
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
exit(0);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (!uwsgi.do_not_change_umask) {
|
||||
@@ -187,9 +187,12 @@ void daemonize(char *logfile) {
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (dup2(fdin, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
if (fdin != 0) {
|
||||
if (dup2(fdin, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fdin);
|
||||
}
|
||||
|
||||
|
||||
@@ -567,6 +570,41 @@ void uwsgi_as_root() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// fix ipcsem owner
|
||||
if (uwsgi.lock_ops.lock_init == uwsgi_lock_ipcsem_init) {
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
while(uli) {
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
ushort *array;
|
||||
} semu ;
|
||||
|
||||
struct semid_ds sds;
|
||||
memset(&sds, 0, sizeof(sds));
|
||||
semu.buf = &sds;
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
|
||||
if (semctl(semid, 0, IPC_STAT, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
semu.buf->sem_perm.uid = uwsgi.uid;
|
||||
semu.buf->sem_perm.gid = uwsgi.gid;
|
||||
|
||||
if (semctl(semid, 0, IPC_SET, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
exit(1);
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (uwsgi.gid) {
|
||||
if (!uwsgi.master_as_root)
|
||||
uwsgi_log("setgid() to %d\n", uwsgi.gid);
|
||||
@@ -584,7 +622,9 @@ void uwsgi_as_root() {
|
||||
char *uidname = uwsgi.uidname;
|
||||
if (!uidname) {
|
||||
struct passwd *pw = getpwuid(uwsgi.uid);
|
||||
uidname = pw->pw_name;
|
||||
if (pw)
|
||||
uidname = pw->pw_name;
|
||||
|
||||
}
|
||||
if (!uidname) uidname = uwsgi_num2str(uwsgi.uid);
|
||||
if (initgroups(uidname, uwsgi.gid)) {
|
||||
@@ -978,7 +1018,6 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int ret;
|
||||
int interesting_fd;
|
||||
char uwsgi_signal;
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
thunder_lock;
|
||||
@@ -997,23 +1036,7 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
|
||||
thunder_unlock;
|
||||
|
||||
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
else {
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
|
||||
@@ -1090,6 +1113,16 @@ void sanitize_args() {
|
||||
uwsgi.vacuum = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.write_errors_exception_only) {
|
||||
uwsgi.ignore_sigpipe = 1;
|
||||
uwsgi.ignore_write_errors = 1;
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
|
||||
uwsgi_log("invalid cheaper value: must be lower than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void env_to_arg(char *src, char *dst) {
|
||||
@@ -1154,6 +1187,7 @@ void uwsgi_log(const char *fmt, ...) {
|
||||
|
||||
struct timeval tv;
|
||||
char sftime[64];
|
||||
char ctime_storage[26];
|
||||
time_t now;
|
||||
|
||||
if (uwsgi.logdate) {
|
||||
@@ -1166,8 +1200,12 @@ void uwsgi_log(const char *fmt, ...) {
|
||||
}
|
||||
else {
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
memcpy(logpkt, ctime((const time_t *) &tv.tv_sec), 24);
|
||||
#ifdef __sun__
|
||||
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);
|
||||
|
||||
rlen = 24 + 3;
|
||||
@@ -1203,6 +1241,7 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
struct timeval tv;
|
||||
char sftime[64];
|
||||
time_t now;
|
||||
char ctime_storage[26];
|
||||
|
||||
if (uwsgi.log_strftime) {
|
||||
now = time(NULL);
|
||||
@@ -1213,8 +1252,12 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
}
|
||||
else {
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
memcpy(logpkt, ctime((const time_t *) &tv.tv_sec), 24);
|
||||
#ifdef __sun__
|
||||
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);
|
||||
|
||||
rlen = 24 + 3;
|
||||
@@ -1870,6 +1913,22 @@ int uwsgi_logic_opt_if_not_env(char *key, char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_reload(char *key, char *value) {
|
||||
if (uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
|
||||
if (!uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_file(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
@@ -2067,6 +2126,10 @@ add:
|
||||
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
|
||||
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
|
||||
}
|
||||
// requires building mime dict ?
|
||||
if (op->flags & UWSGI_OPT_MIME) {
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
// immediate ?
|
||||
if (op->flags & UWSGI_OPT_IMMEDIATE) {
|
||||
op->func(key, value, op->data);
|
||||
@@ -2653,6 +2716,7 @@ void spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -3130,6 +3194,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
|
||||
uwsgi_string->len = strlen(value);
|
||||
}
|
||||
uwsgi_string->next = NULL;
|
||||
uwsgi_string->custom = 0;
|
||||
|
||||
return uwsgi_string;
|
||||
}
|
||||
@@ -3860,7 +3925,11 @@ void uwsgi_set_processname(char *name) {
|
||||
strncat(uwsgi.orig_argv[0], uwsgi.procname_append, uwsgi.max_procname-(amount+1));
|
||||
}
|
||||
|
||||
memset(uwsgi.orig_argv[0]+amount+1, ' ', uwsgi.max_procname-(amount-1));
|
||||
// fill with spaces...
|
||||
memset(uwsgi.orig_argv[0]+amount+1, ' ', uwsgi.max_procname-(amount));
|
||||
// end with \0
|
||||
memset(uwsgi.orig_argv[0]+amount+1+(uwsgi.max_procname-(amount)), '\0', 1);
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
if (uwsgi.procname_prefix) {
|
||||
if (!uwsgi.procname_append) {
|
||||
@@ -4026,7 +4095,12 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
|
||||
touch->custom = 0;
|
||||
}
|
||||
else {
|
||||
if (!touch->custom) touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
if ((uint64_t) tr_st.st_mtime > touch->custom) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom,
|
||||
(unsigned long long) tr_st.st_mtime);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
return touch->value;
|
||||
}
|
||||
@@ -4108,3 +4182,113 @@ void uwsgi_emulate_cow_for_apps(int id) {
|
||||
time_t uwsgi_now() {
|
||||
return time(NULL);
|
||||
}
|
||||
|
||||
uint64_t uwsgi_micros() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
}
|
||||
|
||||
void uwsgi_write_pidfile(char *pidfile_name) {
|
||||
uwsgi_log("writing pidfile to %s\n", pidfile_name);
|
||||
FILE *pidfile = fopen(pidfile_name, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(pidfile_name);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
fclose(pidfile);
|
||||
}
|
||||
|
||||
int uwsgi_manage_exception(char *type, char *value, char *repr) {
|
||||
|
||||
struct uwsgi_string_list *list = NULL;
|
||||
|
||||
// first manage non fatal case (like signals and alarm)....
|
||||
|
||||
if (uwsgi.reload_on_exception) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
list = uwsgi.reload_on_exception_type;
|
||||
while(list) {
|
||||
if (!strcmp(list->value, type)) {
|
||||
return -1;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (value) {
|
||||
list = uwsgi.reload_on_exception_value;
|
||||
while(list) {
|
||||
if (!strcmp(list->value, value)) {
|
||||
return -1;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (repr) {
|
||||
list = uwsgi.reload_on_exception_repr;
|
||||
while(list) {
|
||||
if (!strcmp(list->value, repr)) {
|
||||
return -1;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_protected_close(int fd) {
|
||||
|
||||
sigset_t mask, oset;
|
||||
sigfillset(&mask);
|
||||
if (sigprocmask(SIG_BLOCK, &mask, &oset)) {
|
||||
uwsgi_error("sigprocmask()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
if (sigprocmask(SIG_SETMASK, &oset, NULL)) {
|
||||
uwsgi_error("sigprocmask()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t uwsgi_protected_read(int fd, void *buf, size_t len) {
|
||||
|
||||
sigset_t mask, oset;
|
||||
sigfillset(&mask);
|
||||
if (sigprocmask(SIG_BLOCK, &mask, &oset)) {
|
||||
uwsgi_error("sigprocmask()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ssize_t ret = read(fd, buf, len);
|
||||
|
||||
if (sigprocmask(SIG_SETMASK, &oset, NULL)) {
|
||||
uwsgi_error("sigprocmask()");
|
||||
exit(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
|
||||
char src[PATH_MAX+1];
|
||||
memcpy(src, dir, dir_len);
|
||||
src[dir_len] = 0;
|
||||
char *dst = ptr;
|
||||
if (!dst) dst = uwsgi_malloc(PATH_MAX+1);
|
||||
if (!realpath(src, dst)) {
|
||||
uwsgi_error_realpath(src);
|
||||
if (!ptr)
|
||||
free(dst);
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero,0},
|
||||
|
||||
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -68,6 +71,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-not-env", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_env, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifenv", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -83,6 +89,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"ignore-sigpipe", no_argument, 0, "do not report (annoying) SIGPIPE", uwsgi_opt_true, &uwsgi.ignore_sigpipe,0},
|
||||
{"ignore-write-errors", no_argument, 0, "do not report (annoying) write()/writev() errors", uwsgi_opt_true, &uwsgi.ignore_write_errors,0},
|
||||
{"write-errors-tolerance", required_argument, 0, "set the maximum number of allowed write errors (default: no tolerance)", uwsgi_opt_set_int, &uwsgi.write_errors_tolerance,0},
|
||||
{"write-errors-exception-only", no_argument, 0, "only raise an exception on write errors giving control to the app itself", uwsgi_opt_true, &uwsgi.write_errors_exception_only,0},
|
||||
|
||||
{"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL,0},
|
||||
{"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
|
||||
@@ -131,6 +140,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-amqp-username", required_argument, 0, "set emperor amqp username", uwsgi_opt_set_str, &uwsgi.emperor_amqp_username, 0},
|
||||
{"emperor-amqp-password", required_argument, 0, "set emperor amqp password", uwsgi_opt_set_str, &uwsgi.emperor_amqp_password, 0},
|
||||
{"emperor-throttle", required_argument, 0, "throttle each vassal spawn (in seconds)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
|
||||
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook,0},
|
||||
@@ -149,6 +159,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"no-fd-passing", no_argument, 0, "disable file descriptor passing", uwsgi_opt_true, &uwsgi.no_fd_passing, 0},
|
||||
{"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
|
||||
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_int, &uwsgi.cache_max_items, 0},
|
||||
@@ -157,6 +168,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cache-store-sync", required_argument, 0, "set frequency of sync for persistent cache", uwsgi_opt_set_int, &uwsgi.cache_store_sync,0},
|
||||
{"cache-server", required_argument, 0, "enable the threaded cache server", uwsgi_opt_set_str, &uwsgi.cache_server, 0},
|
||||
{"cache-server-threads", required_argument, 0, "set the number of threads for the cache server", uwsgi_opt_set_int, &uwsgi.cache_server_threads,0},
|
||||
{"cache-no-expire", no_argument, 0, "disable auto sweep of expired items", uwsgi_opt_true, &uwsgi.cache_no_expire,0},
|
||||
{"cache-expire-freq", required_argument, 0, "set the frequency of cache sweeper scans (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.cache_expire_freq,0},
|
||||
{"cache-report-freed-items", no_argument, 0, "constantly report the cache item freed by the sweeper (use only for debug)", uwsgi_opt_true, &uwsgi.cache_report_freed_items,0},
|
||||
|
||||
{"queue", required_argument, 0, "enable shared queue", uwsgi_opt_set_int, &uwsgi.queue_size, 0},
|
||||
{"queue-blocksize", required_argument, 0, "set queue blocksize", uwsgi_opt_set_int, &uwsgi.queue_store_sync, 0},
|
||||
@@ -168,6 +182,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"spooler-ordered", no_argument, 0, "try to order the execution of spooler tasks", uwsgi_opt_true, &uwsgi.spooler_ordered,0},
|
||||
{"spooler-chdir", required_argument, 0, "chdir() to specified directory before each spooler task", uwsgi_opt_set_str, &uwsgi.spooler_chdir,0},
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, 0},
|
||||
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
|
||||
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
|
||||
#endif
|
||||
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
|
||||
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -250,13 +266,19 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_int, &uwsgi.prio, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
|
||||
{"cpu-affinity", required_argument, 0, "set cpu affinity", uwsgi_opt_set_int, &uwsgi.cpu_affinity, 0},
|
||||
{"post-buffering", required_argument, 0, "enable post buffering", uwsgi_opt_set_64bit, &uwsgi.post_buffering, 0},
|
||||
{"post-buffering-bufsize", required_argument, 0, "set buffer size for read() in post buffering mode", uwsgi_opt_set_64bit, &uwsgi.post_buffering_bufsize,0},
|
||||
{"upload-progress", required_argument, 0, "enable creation of .json files in the specified directory during a file upload", uwsgi_opt_set_str, &uwsgi.upload_progress,0},
|
||||
{"no-default-app", no_argument, 0, "do not fallback to default app", uwsgi_opt_true, &uwsgi.no_default_app, 0},
|
||||
{"manage-script-name", no_argument, 0, "automatically rewrite SCRIPT_NAME and PATH_INFO", uwsgi_opt_true, &uwsgi.manage_script_name, 0},
|
||||
{"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &uwsgi.ignore_script_name, 0},
|
||||
{"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &uwsgi.catch_exceptions, 0},
|
||||
{"reload-on-exception", no_argument, 0, "reload a worker when an exception is raised", uwsgi_opt_true, &uwsgi.reload_on_exception, 0},
|
||||
{"reload-on-exception-type", required_argument, 0, "reload a worker when a specific exception type is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_type, 0},
|
||||
{"reload-on-exception-value", required_argument, 0, "reload a worker when a specific exception value is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_value, 0},
|
||||
{"reload-on-exception-repr", required_argument, 0, "reload a worker when a specific exception type+value (language-specific) is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_repr, 0},
|
||||
#ifdef UWSGI_UDP
|
||||
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
@@ -321,7 +343,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
|
||||
{"cheap", no_argument, 0, "set cheap mode (spawn workers only after the first request)", uwsgi_opt_true, &uwsgi.cheap, 0},
|
||||
{"cheaper", required_argument, 0, "set cheaper mode (adaptive process spawning)", uwsgi_opt_set_int, &uwsgi.cheaper_count, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning)", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning)", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
|
||||
{"cheaper-step", required_argument, 0, "number of additional processes to spawn at each overload", uwsgi_opt_set_int, &uwsgi.cheaper_step, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-overload", required_argument, 0, "increase workers after specified overload", uwsgi_opt_set_64bit, &uwsgi.cheaper_overload, UWSGI_OPT_MASTER|UWSGI_OPT_CHEAPER},
|
||||
{"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, 0},
|
||||
@@ -347,22 +369,35 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-qs", required_argument, 0, "add a route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
#endif
|
||||
{"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, 0},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, 0},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, 0},
|
||||
{"static-map", required_argument, 0, "map mountpoint to static directory", uwsgi_opt_static_map, NULL, 0},
|
||||
{"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, 0},
|
||||
{"static-index", required_argument, 0, "search for specified file if a directory is requested", uwsgi_opt_add_string_list, &uwsgi.static_index, 0},
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_set_str, &uwsgi.mime_file, 0},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_set_str, &uwsgi.mime_file, 0},
|
||||
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL,0},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL,0},
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"static-map", required_argument, 0, "map mountpoint to static directory (or file)", uwsgi_opt_static_map, &uwsgi.static_maps, UWSGI_OPT_MIME},
|
||||
{"static-map2", required_argument, 0, "like static-map but completely appending the requested resource to the docroot", uwsgi_opt_static_map, &uwsgi.static_maps2, UWSGI_OPT_MIME},
|
||||
{"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, UWSGI_OPT_MIME},
|
||||
{"static-index", required_argument, 0, "search for specified file if a directory is requested", uwsgi_opt_add_string_list, &uwsgi.static_index, UWSGI_OPT_MIME},
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
|
||||
{"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
|
||||
{"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
{"static-expires", required_argument, 0, "set the Expires header based on filename regexp", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires, UWSGI_OPT_MIME},
|
||||
{"static-expires-mtime", required_argument, 0, "set the Expires header based on filename regexp and file mtime", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires_mtime, UWSGI_OPT_MIME},
|
||||
#endif
|
||||
|
||||
{"static-offload-to-thread", required_argument, 0, "offload static file serving to a thread (upto the specified number of threads)", uwsgi_opt_set_int, &uwsgi.static_offload_to_thread, UWSGI_OPT_MIME},
|
||||
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
|
||||
{"check-cache", no_argument, 0, "check for response data in the cache", uwsgi_opt_true, &uwsgi.check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode,0},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
|
||||
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum,0},
|
||||
#ifdef __linux__
|
||||
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup,0},
|
||||
@@ -438,6 +473,9 @@ restart:
|
||||
continue;
|
||||
uwsgi.dirty_config = 0;
|
||||
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
|
||||
if (uwsgi.exported_opts[i]->configured == 0 && uwsgi.autoload) {
|
||||
uwsgi.dirty_config = uwsgi_try_autoload(uwsgi.exported_opts[i]->key);
|
||||
}
|
||||
if (uwsgi.dirty_config) goto restart;
|
||||
}
|
||||
|
||||
@@ -528,8 +566,8 @@ void gracefully_kill(int signum) {
|
||||
uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
#ifdef UWSGI_THREADING
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
if (uwsgi.threads > 1) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
wait_for_threads();
|
||||
if (!uwsgi.core[wsgi_req->async_id]->in_request) {
|
||||
exit(UWSGI_RELOAD_CODE);
|
||||
@@ -859,6 +897,7 @@ void what_i_am_doing() {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
int i;
|
||||
char ctime_storage[26];
|
||||
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
@@ -866,11 +905,16 @@ void what_i_am_doing() {
|
||||
for (i = 0; i < uwsgi.cores; i++) {
|
||||
wsgi_req = uwsgi.wsgi_requests[i];
|
||||
if (wsgi_req->uri_len > 0) {
|
||||
#ifdef __sun__
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
|
||||
#endif
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d core %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime((const time_t *) &wsgi_req->start_of_request.tv_sec));
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d core %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("SIGUSR2: --- uWSGI worker %d core %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime((const time_t *) &wsgi_req->start_of_request.tv_sec));
|
||||
uwsgi_log("SIGUSR2: --- uWSGI worker %d core %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -878,11 +922,16 @@ void what_i_am_doing() {
|
||||
else {
|
||||
wsgi_req = uwsgi.wsgi_requests[0];
|
||||
if (wsgi_req->uri_len > 0) {
|
||||
#ifdef __sun__
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, ctime_storage);
|
||||
#endif
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL)) {
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime((const time_t *) &wsgi_req->start_of_request.tv_sec));
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("SIGUSR2: --- uWSGI worker %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime((const time_t *) &wsgi_req->start_of_request.tv_sec));
|
||||
uwsgi_log("SIGUSR2: --- uWSGI worker %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < time(NULL) && uwsgi.workers[uwsgi.mywid].sig) {
|
||||
@@ -1082,7 +1131,7 @@ void uwsgi_plugins_atexit(void) {
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j<0xFF; j++) {
|
||||
for (j = 0; j<256; j++) {
|
||||
if (uwsgi.p[j]->atexit) {
|
||||
uwsgi.p[j]->atexit();
|
||||
}
|
||||
@@ -1092,7 +1141,7 @@ void uwsgi_plugins_atexit(void) {
|
||||
|
||||
void uwsgi_backtrace(int depth) {
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
@@ -1190,8 +1239,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
int i;
|
||||
int rlen;
|
||||
|
||||
FILE *pidfile;
|
||||
|
||||
char *env_reloads;
|
||||
char env_reload_buf[11];
|
||||
|
||||
@@ -1256,7 +1303,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.shared->spooler_frequency = 30;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
uwsgi.p[i] = &unconfigured_plugin;
|
||||
}
|
||||
|
||||
@@ -1313,7 +1360,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.shared->worker_log_pipe[0] = -1;
|
||||
uwsgi.shared->worker_log_pipe[1] = -1;
|
||||
|
||||
uwsgi.mime_file = "/etc/mime.types";
|
||||
|
||||
#ifdef UWSGI_BLACKLIST
|
||||
if (!uwsgi_file_to_string_list(UWSGI_BLACKLIST, &uwsgi.blacklist)) {
|
||||
@@ -1493,7 +1539,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
}
|
||||
}
|
||||
if (!magic) {
|
||||
for (j = 0; j < 0xFF; j++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (uwsgi.p[j]->magic) {
|
||||
if (uwsgi.p[j]->magic(NULL, lazy)) {
|
||||
magic = 1;
|
||||
@@ -1612,6 +1658,12 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_log_initial("*** big endian arch detected ***\n");
|
||||
#endif
|
||||
|
||||
#if defined(_SC_NPROCESSORS_ONLN)
|
||||
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_ONLN));
|
||||
#elif defined(_SC_NPROCESSORS_CONF)
|
||||
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_CONF));
|
||||
#endif
|
||||
|
||||
|
||||
uwsgi_log_initial("current working directory: %s\n", uwsgi.cwd);
|
||||
|
||||
@@ -1620,16 +1672,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
}
|
||||
|
||||
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
|
||||
uwsgi_log("writing pidfile to %s\n", uwsgi.pidfile);
|
||||
pidfile = fopen(uwsgi.pidfile, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(uwsgi.pidfile);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
fclose(pidfile);
|
||||
uwsgi_write_pidfile(uwsgi.pidfile);
|
||||
}
|
||||
|
||||
uwsgi_log_initial("detected binary path: %s\n", uwsgi.binary_path);
|
||||
@@ -1669,7 +1712,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_sock->fd = shared_sock->fd;
|
||||
uwsgi_sock->family = shared_sock->family;
|
||||
uwsgi_sock->name = shared_sock->name;
|
||||
uwsgi_log("uwsgi socket %d mapped to shared socket %d (%s)\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_get_shared_socket_num(shared_sock), shared_sock->name);
|
||||
uwsgi_log("uwsgi socket %d mapped to shared socket %d (%s) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, uwsgi_sock->fd);
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
@@ -1782,16 +1825,7 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
|
||||
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
|
||||
uwsgi_log("writing pidfile2 to %s\n", uwsgi.pidfile2);
|
||||
FILE *pidfile2 = fopen(uwsgi.pidfile2, "w");
|
||||
if (!pidfile2) {
|
||||
uwsgi_error_open(uwsgi.pidfile2);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile2, "%d\n", (int) getpid()) < 0) {
|
||||
uwsgi_log("could not write pidfile2.\n");
|
||||
}
|
||||
fclose(pidfile2);
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process && !uwsgi.command_mode) {
|
||||
@@ -1840,13 +1874,27 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
// initialize workers
|
||||
|
||||
|
||||
if (uwsgi.build_mime_dict) {
|
||||
if (!access(uwsgi.mime_file, R_OK)) {
|
||||
uwsgi_build_mime_dict(uwsgi.mime_file);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("!!! no mime.types file found !!!\n");
|
||||
if (!uwsgi.mime_file) uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
|
||||
struct uwsgi_string_list *umd = uwsgi.mime_file;
|
||||
while(umd) {
|
||||
if (!access(umd->value, R_OK)) {
|
||||
uwsgi_build_mime_dict(umd->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("!!! no %s file found !!!\n", umd->value);
|
||||
}
|
||||
umd = umd->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_attr_init(&uwsgi.static_offload_thread_attr);
|
||||
pthread_attr_setdetachstate(&uwsgi.static_offload_thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
// 512K should be enough...
|
||||
pthread_attr_setstacksize(&uwsgi.static_offload_thread_attr, 512*1024);
|
||||
pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
|
||||
}
|
||||
|
||||
// end of generic initialization
|
||||
@@ -1920,7 +1968,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
|
||||
uwsgi_log_initial("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
uwsgi.wsgi_requests = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.cores);
|
||||
@@ -2040,10 +2088,9 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi.no_server) {
|
||||
|
||||
// systemd socket activation
|
||||
// systemd/upstart/zerg socket activation
|
||||
if (!uwsgi.is_a_reload) {
|
||||
char *listen_pid = getenv("LISTEN_PID");
|
||||
if (listen_pid) {
|
||||
@@ -2052,32 +2099,44 @@ int uwsgi_start(void *v_argv) {
|
||||
if (listen_fds) {
|
||||
int systemd_fds = atoi(listen_fds);
|
||||
if (systemd_fds > 0) {
|
||||
uwsgi_log("- SystemD socket activation detected -\n");
|
||||
for(i=3;i<3+systemd_fds;i++) {
|
||||
uwsgi_sock = uwsgi_new_socket(NULL);
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, i);
|
||||
}
|
||||
uwsgi.skip_zero = 1;
|
||||
}
|
||||
unsetenv("LISTEN_PID");
|
||||
unsetenv("LISTEN_FDS");
|
||||
goto skipzero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *zn = uwsgi.zerg_node;
|
||||
while (zn) {
|
||||
if (uwsgi_zerg_attach(zn->value)) {
|
||||
if (!uwsgi.zerg_fallback) {
|
||||
exit(1);
|
||||
char *upstart_events = getenv("UPSTART_EVENTS");
|
||||
if (upstart_events && !strcmp(upstart_events, "socket")) {
|
||||
char *upstart_fds = getenv("UPSTART_FDS");
|
||||
if (upstart_fds) {
|
||||
uwsgi_log("- Upstart socket bridge detected (job: %s) -\n", getenv("UPSTART_JOB"));
|
||||
uwsgi_sock = uwsgi_new_socket(NULL);
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, atoi(upstart_fds));
|
||||
uwsgi.skip_zero = 1;
|
||||
}
|
||||
unsetenv("UPSTART_EVENTS");
|
||||
unsetenv("UPSTART_FDS");
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_string_list *zn = uwsgi.zerg_node;
|
||||
while (zn) {
|
||||
if (uwsgi_zerg_attach(zn->value)) {
|
||||
if (!uwsgi.zerg_fallback) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
zn = zn->next;
|
||||
}
|
||||
zn = zn->next;
|
||||
}
|
||||
|
||||
|
||||
//check for inherited sockets
|
||||
if (uwsgi.is_a_reload || uwsgi.zerg) {
|
||||
|
||||
if (uwsgi.zerg) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -2097,6 +2156,11 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
uwsgi_log("zerg sockets attached\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//check for inherited sockets
|
||||
if (uwsgi.is_a_reload) {
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -2141,6 +2205,31 @@ int uwsgi_start(void *v_argv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
int found = 0;
|
||||
while (ugs) {
|
||||
if (ugs->fd == j) {
|
||||
found = 1;break;
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
if (found) continue;
|
||||
|
||||
|
||||
int y;
|
||||
found = 0;
|
||||
for(y=0;y<ushared->gateways_cnt;y++) {
|
||||
if (ushared->gateways[y].internal_subscription_pipe[0] == j) {
|
||||
found = 1; break;
|
||||
}
|
||||
if (ushared->gateways[y].internal_subscription_pipe[1] == j) {
|
||||
found = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) continue;
|
||||
|
||||
|
||||
socket_type_len = sizeof(struct sockaddr_un);
|
||||
gsa.sa = (struct sockaddr *) &usa;
|
||||
if (!getsockname(j, gsa.sa, &socket_type_len)) {
|
||||
@@ -2153,14 +2242,18 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
if (useless)
|
||||
|
||||
if (useless) {
|
||||
close(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//now bind all the unbound sockets
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound) {
|
||||
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
|
||||
char *tcp_port = strchr(uwsgi_sock->name, ':');
|
||||
if (tcp_port == NULL) {
|
||||
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
@@ -2197,6 +2290,7 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
@@ -2216,13 +2310,19 @@ int uwsgi_start(void *v_argv) {
|
||||
if (!zero_used) {
|
||||
socket_type_len = sizeof(struct sockaddr_un);
|
||||
gsa.sa = (struct sockaddr *) &usa;
|
||||
if (!getsockname(0, gsa.sa, &socket_type_len)) {
|
||||
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
|
||||
if (gsa.sa->sa_family == AF_UNIX) {
|
||||
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_sock = uwsgi_new_socket(uwsgi_concat2("::",""));
|
||||
uwsgi_sock->family = AF_INET;
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
}
|
||||
}
|
||||
@@ -2248,8 +2348,6 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
}
|
||||
|
||||
skipzero:
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -2263,6 +2361,7 @@ skipzero:
|
||||
// put listening socket in non-blocking state and set the protocol
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound || uwsgi_sock->fd == -1) goto nextsock;
|
||||
if (!uwsgi_sock->per_core) {
|
||||
uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
|
||||
if (uwsgi_sock->arg < 0) {
|
||||
@@ -2284,10 +2383,10 @@ skipzero:
|
||||
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_write = uwsgi_proto_http_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_http_writev;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_http_write_header;
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_http_writev_header;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
@@ -2331,7 +2430,7 @@ skipzero:
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
@@ -2356,7 +2455,7 @@ skipzero:
|
||||
|
||||
// initialize request plugin only if workers or master are available
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init) {
|
||||
uwsgi.p[i]->init();
|
||||
}
|
||||
@@ -2372,7 +2471,7 @@ skipzero:
|
||||
|
||||
// again check for workers/sockets...
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
for (i = 0; i < 0xff; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_init) {
|
||||
uwsgi.p[i]->post_init();
|
||||
}
|
||||
@@ -2400,7 +2499,7 @@ skipzero:
|
||||
|
||||
// again check for workers/sockets...
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->enable_threads)
|
||||
uwsgi.p[i]->enable_threads();
|
||||
}
|
||||
@@ -2605,7 +2704,7 @@ skipzero:
|
||||
}
|
||||
|
||||
// preinit apps (create the language environment)
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->preinit_apps) {
|
||||
uwsgi.p[i]->preinit_apps();
|
||||
}
|
||||
@@ -2639,6 +2738,14 @@ skipzero:
|
||||
masterpid = uwsgi.mypid;
|
||||
|
||||
uwsgi.workers[0].pid = masterpid;
|
||||
|
||||
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile);
|
||||
}
|
||||
|
||||
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.no_server) {
|
||||
@@ -2680,7 +2787,7 @@ skipzero:
|
||||
|
||||
// security in multiuser environment: allow only a subset of modifiers
|
||||
if (uwsgi.allowed_modifiers) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (!uwsgi_list_has_num(uwsgi.allowed_modifiers, i)) {
|
||||
uwsgi.p[i]->request = unconfigured_hook;
|
||||
uwsgi.p[i]->after_request = unconfigured_after_hook;
|
||||
@@ -2689,7 +2796,7 @@ skipzero:
|
||||
}
|
||||
|
||||
// master fixup
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(0);
|
||||
}
|
||||
@@ -2803,9 +2910,8 @@ skipzero:
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
int fd = uwsgi_sock->fd;
|
||||
close(fd);
|
||||
fd = open("/dev/null", O_RDONLY);
|
||||
close(uwsgi_sock->fd);
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
@@ -2890,7 +2996,7 @@ skipzero:
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
@@ -3024,7 +3130,7 @@ skipzero:
|
||||
//initialization done
|
||||
|
||||
// run fixup handler
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->fixup) {
|
||||
uwsgi.p[i]->fixup();
|
||||
}
|
||||
@@ -3090,7 +3196,7 @@ void uwsgi_ignition() {
|
||||
uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->hijack_worker) {
|
||||
uwsgi.p[i]->hijack_worker();
|
||||
}
|
||||
@@ -3196,7 +3302,7 @@ void build_options() {
|
||||
op++;
|
||||
}
|
||||
|
||||
for(i=0;i<0xFF;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->options) {
|
||||
options_count += uwsgi_count_options(uwsgi.p[i]->options);
|
||||
}
|
||||
@@ -3219,7 +3325,7 @@ void build_options() {
|
||||
op++;
|
||||
}
|
||||
|
||||
for(i=0;i<0xFF;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->options) {
|
||||
int c = uwsgi_count_options(uwsgi.p[i]->options);
|
||||
memcpy(&uwsgi.options[pos], uwsgi.p[i]->options, sizeof(struct uwsgi_option) * c);
|
||||
@@ -3352,7 +3458,7 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_apps) {
|
||||
uwsgi.p[i]->init_apps();
|
||||
}
|
||||
@@ -3370,7 +3476,7 @@ void uwsgi_init_all_apps() {
|
||||
what[0] = 0;
|
||||
what++;
|
||||
uwsgi_log("mounting %s on %s\n", what, uwsgi.mounts[i]);
|
||||
for (j = 0; j < 0xFF; j++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (uwsgi.p[j]->mount_app) {
|
||||
if (!uwsgi_startswith(uwsgi.mounts[i], "regexp://", 9)) {
|
||||
if (uwsgi.p[j]->mount_app(uwsgi.mounts[i]+9, what, 1) != -1)
|
||||
@@ -3434,8 +3540,24 @@ void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
else {
|
||||
*ptr = 1;
|
||||
}
|
||||
|
||||
if (*ptr < 0) {
|
||||
uwsgi_log("invalid value for option \"%s\": must be > 0\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_rawint(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
*ptr = atoi((char *)value);
|
||||
}
|
||||
else {
|
||||
*ptr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_64bit(char *opt, char *value, void *key) {
|
||||
uint64_t *ptr = (uint64_t *) key;
|
||||
|
||||
@@ -3590,6 +3712,12 @@ void uwsgi_opt_set_env(char *opt, char *value, void *none) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
|
||||
if (unsetenv(value)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
|
||||
long *signum_fake_ptr = (long *) sig;
|
||||
@@ -3635,6 +3763,44 @@ void uwsgi_opt_check_static(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_dyn_dict(char *opt, char *value, void *dict) {
|
||||
|
||||
char *equal = strchr(value, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
||||
|
||||
uwsgi_dyn_dict_new(udd, value, equal-value, equal+1, strlen(equal+1));
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_opt_add_regexp_dyn_dict(char *opt, char *value, void *dict) {
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
||||
|
||||
struct uwsgi_dyn_dict *new_udd = uwsgi_dyn_dict_new(udd, value, space-value, space+1, strlen(space+1));
|
||||
|
||||
char *regexp = uwsgi_concat2n(value, space-value, "", 0);
|
||||
|
||||
if (uwsgi_regexp_build(regexp, &new_udd->pattern, &new_udd->pattern_extra)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(regexp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
|
||||
|
||||
if (!strcasecmp("x-sendfile", value)) {
|
||||
@@ -3655,16 +3821,20 @@ void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_static_map(char *opt, char *value, void *foobar) {
|
||||
void uwsgi_opt_static_map(char *opt, char *value, void *static_maps) {
|
||||
|
||||
struct uwsgi_dyn_dict **maps = (struct uwsgi_dyn_dict **) static_maps;
|
||||
char *mountpoint = uwsgi_str(value);
|
||||
char *docroot = strchr(mountpoint, '=');
|
||||
|
||||
char *docroot = strchr(mountpoint, '=');
|
||||
|
||||
if (!docroot) {
|
||||
uwsgi_log("invalid document root in static map, syntax mountpoint=docroot\n");
|
||||
exit(1);
|
||||
}
|
||||
docroot[0] = 0;
|
||||
docroot++;
|
||||
uwsgi_dyn_dict_new(&uwsgi.static_maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
|
||||
uwsgi_dyn_dict_new(maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
|
||||
uwsgi_log("[uwsgi-static] added mapping for %s => %s\n", mountpoint, docroot);
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
@@ -3729,9 +3899,11 @@ void uwsgi_opt_signal(char *opt, char *value, void *foobar) {
|
||||
void uwsgi_opt_log_date(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.logdate = 1;
|
||||
if (value) {
|
||||
uwsgi.log_strftime = value;
|
||||
}
|
||||
if (value) {
|
||||
if (strcasecmp("true", value) && strcasecmp("1", value) && strcasecmp("on", value) && strcasecmp("yes", value)) {
|
||||
uwsgi.log_strftime = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_chmod_socket(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -11,6 +11,7 @@ extern "C" {
|
||||
#define UMAX64_STR "18446744073709551616"
|
||||
|
||||
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_error_realpath(x) uwsgi_log("realpath() of %s failed: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_log_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log(x);
|
||||
#define uwsgi_error_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
|
||||
@@ -23,7 +24,7 @@ extern "C" {
|
||||
#define uwsgi_str(x) uwsgi_concat2(x, "")
|
||||
|
||||
#define uwsgi_notify(x) if (uwsgi.notify) uwsgi.notify(x)
|
||||
#define uwsgi_notify_ready() if (uwsgi.notify_ready) uwsgi.notify_ready()
|
||||
#define uwsgi_notify_ready() uwsgi.shared->ready = 1 ; if (uwsgi.notify_ready) uwsgi.notify_ready()
|
||||
|
||||
#define uwsgi_apps uwsgi.workers[uwsgi.mywid].apps
|
||||
#define uwsgi_apps_cnt uwsgi.workers[uwsgi.mywid].apps_cnt
|
||||
@@ -50,6 +51,7 @@ extern "C" {
|
||||
#define UWSGI_OPT_NO_SERVER (1 << 10)
|
||||
#define UWSGI_OPT_POST_BUFFERING (1 << 11)
|
||||
#define UWSGI_OPT_CLUSTER (1 << 12)
|
||||
#define UWSGI_OPT_MIME (1 << 13)
|
||||
|
||||
#define MAX_APPS 64
|
||||
#define MAX_GENERIC_PLUGINS 64
|
||||
@@ -140,6 +142,9 @@ extern char UWSGI_EMBED_CONFIG_END;
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#ifndef __USE_ISOC99
|
||||
@@ -329,6 +334,9 @@ struct uwsgi_lock_ops {
|
||||
#define uwsgi_wlock(x) uwsgi.lock_ops.wlock(x)
|
||||
#define uwsgi_rwunlock(x) uwsgi.lock_ops.rwunlock(x)
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_dyn_dict {
|
||||
|
||||
@@ -340,6 +348,11 @@ struct uwsgi_dyn_dict {
|
||||
uint64_t hits;
|
||||
int status;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
#endif
|
||||
|
||||
struct uwsgi_dyn_dict *prev;
|
||||
struct uwsgi_dyn_dict *next;
|
||||
};
|
||||
@@ -390,6 +403,7 @@ struct uwsgi_gateway_socket {
|
||||
// this requires SCTP
|
||||
int sctp;
|
||||
#endif
|
||||
int shared;
|
||||
|
||||
char *owner;
|
||||
struct uwsgi_gateway *gateway;
|
||||
@@ -543,6 +557,7 @@ struct uwsgi_opt {
|
||||
#define UWSGI_EXILE_CODE 26
|
||||
#define UWSGI_FAILED_APP_CODE 22
|
||||
#define UWSGI_DE_HIJACKED_CODE 173
|
||||
#define UWSGI_EXCEPTION_CODE 5
|
||||
#define UWSGI_QUIET_CODE 29
|
||||
|
||||
#define MAX_VARS 64
|
||||
@@ -640,7 +655,6 @@ struct uwsgi_plugin {
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
#include <pcre.h>
|
||||
int uwsgi_regexp_build(char *, pcre **, pcre_extra **);
|
||||
int uwsgi_regexp_match(pcre *, pcre_extra *, char *, int);
|
||||
int uwsgi_regexp_match_ovec(pcre *, pcre_extra *, char *, int, int *, int);
|
||||
@@ -665,7 +679,6 @@ struct uwsgi_app {
|
||||
void *interpreter;
|
||||
void *callable;
|
||||
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
void **args;
|
||||
void **environ;
|
||||
@@ -713,6 +726,7 @@ struct uwsgi_spooler {
|
||||
char dir[PATH_MAX];
|
||||
pid_t pid;
|
||||
uint64_t respawned;
|
||||
uint64_t tasks;
|
||||
struct uwsgi_lock_item *lock;
|
||||
time_t harakiri;
|
||||
|
||||
@@ -910,6 +924,7 @@ struct wsgi_request {
|
||||
int async_plagued;
|
||||
|
||||
int suspended;
|
||||
int write_errors;
|
||||
|
||||
int *ovector;
|
||||
size_t post_cl;
|
||||
@@ -1099,6 +1114,7 @@ struct uwsgi_server {
|
||||
int emperor_fd_config;
|
||||
int early_emperor;
|
||||
int emperor_throttle;
|
||||
int emperor_magic_exec;
|
||||
char *emperor_dir;
|
||||
pid_t emperor_pid;
|
||||
int emperor_broodlord;
|
||||
@@ -1180,6 +1196,9 @@ struct uwsgi_server {
|
||||
#endif
|
||||
|
||||
int ignore_sigpipe;
|
||||
int ignore_write_errors;
|
||||
int write_errors_tolerance;
|
||||
int write_errors_exception_only;
|
||||
|
||||
// still working on it
|
||||
char *profiler;
|
||||
@@ -1200,6 +1219,13 @@ struct uwsgi_server {
|
||||
|
||||
int ignore_script_name;
|
||||
int manage_script_name;
|
||||
int reload_on_exception;
|
||||
int catch_exceptions;
|
||||
struct uwsgi_string_list *reload_on_exception_type;
|
||||
struct uwsgi_string_list *reload_on_exception_value;
|
||||
struct uwsgi_string_list *reload_on_exception_repr;
|
||||
|
||||
|
||||
int no_default_app;
|
||||
// exit if no-app is loaded
|
||||
int need_app;
|
||||
@@ -1228,7 +1254,8 @@ struct uwsgi_server {
|
||||
// static file serving
|
||||
int file_serve_mode;
|
||||
int build_mime_dict;
|
||||
char *mime_file;
|
||||
|
||||
struct uwsgi_string_list *mime_file;
|
||||
|
||||
struct uwsgi_probe *probes;
|
||||
|
||||
@@ -1251,11 +1278,22 @@ struct uwsgi_server {
|
||||
int daemons_cnt;
|
||||
|
||||
struct uwsgi_dyn_dict *static_maps;
|
||||
struct uwsgi_dyn_dict *static_maps2;
|
||||
struct uwsgi_dyn_dict *check_static;
|
||||
struct uwsgi_dyn_dict *mimetypes;
|
||||
struct uwsgi_string_list *static_skip_ext;
|
||||
struct uwsgi_string_list *static_index;
|
||||
|
||||
struct uwsgi_dyn_dict *static_expires_type;
|
||||
struct uwsgi_dyn_dict *static_expires_type_mtime;
|
||||
|
||||
struct uwsgi_dyn_dict *static_expires;
|
||||
struct uwsgi_dyn_dict *static_expires_mtime;
|
||||
|
||||
int check_static_docroot;
|
||||
int static_offload_to_thread;
|
||||
pthread_attr_t static_offload_thread_attr;
|
||||
pthread_mutex_t static_offload_thread_lock;
|
||||
|
||||
char *daemonize;
|
||||
char *daemonize2;
|
||||
@@ -1326,7 +1364,9 @@ struct uwsgi_server {
|
||||
int spooler_numproc;
|
||||
struct uwsgi_spooler *i_am_a_spooler;
|
||||
char *spooler_chdir;
|
||||
int spooler_max_tasks;
|
||||
int spooler_ordered;
|
||||
int spooler_quiet;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
@@ -1440,10 +1480,10 @@ struct uwsgi_server {
|
||||
|
||||
|
||||
int no_orphans;
|
||||
int skip_zero;
|
||||
|
||||
char *chdir;
|
||||
char *chdir2;
|
||||
int catch_exceptions;
|
||||
|
||||
int vacuum;
|
||||
int no_server;
|
||||
@@ -1524,7 +1564,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_loop loops[MAX_LOOPS];
|
||||
int loops_cnt;
|
||||
|
||||
struct uwsgi_plugin *p[0xFF];
|
||||
struct uwsgi_plugin *p[256];
|
||||
struct uwsgi_plugin *gp[MAX_GENERIC_PLUGINS];
|
||||
int gp_cnt;
|
||||
|
||||
@@ -1540,6 +1580,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_lock_item *registered_locks;
|
||||
struct uwsgi_lock_ops lock_ops;
|
||||
char *lock_engine;
|
||||
char *ftok;
|
||||
char *lock_id;
|
||||
size_t lock_size;
|
||||
size_t rwlock_size;
|
||||
@@ -1555,6 +1596,9 @@ struct uwsgi_server {
|
||||
char *cache_store;
|
||||
size_t cache_filesize;
|
||||
int cache_store_sync;
|
||||
int cache_no_expire;
|
||||
int cache_expire_freq;
|
||||
int cache_report_freed_items;
|
||||
|
||||
char *cache_server;
|
||||
int cache_server_threads;
|
||||
@@ -1610,6 +1654,17 @@ struct uwsgi_server {
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_offload_request {
|
||||
pthread_t tid;
|
||||
struct wsgi_request wsgi_req;
|
||||
char *buffer;
|
||||
struct iovec *hvec;
|
||||
char real_filename[PATH_MAX+1];
|
||||
size_t real_filename_len;
|
||||
struct stat st;
|
||||
};
|
||||
|
||||
|
||||
struct uwsgi_rpc {
|
||||
char name[0xff];
|
||||
void *func;
|
||||
@@ -1756,6 +1811,8 @@ struct uwsgi_shared {
|
||||
struct uwsgi_gateway gateways[MAX_GATEWAYS];
|
||||
int gateways_cnt;
|
||||
time_t gateways_harakiri[MAX_GATEWAYS];
|
||||
|
||||
int ready;
|
||||
};
|
||||
|
||||
struct uwsgi_core {
|
||||
@@ -1831,6 +1888,8 @@ struct uwsgi_worker {
|
||||
|
||||
uint64_t avg_response_time;
|
||||
|
||||
uint64_t static_offload_threads;
|
||||
|
||||
char name[0xff];
|
||||
};
|
||||
|
||||
@@ -2099,7 +2158,7 @@ ssize_t uwsgi_send_message(int, uint8_t, uint8_t, char *, uint16_t, int, ssize_t
|
||||
char *uwsgi_cluster_best_node(void);
|
||||
|
||||
int uwsgi_cache_set(char *, uint16_t, char *, uint64_t, uint64_t, uint16_t);
|
||||
int uwsgi_cache_del(char *, uint16_t);
|
||||
int uwsgi_cache_del(char *, uint16_t, uint64_t);
|
||||
char *uwsgi_cache_get(char *, uint16_t, uint64_t *);
|
||||
uint32_t uwsgi_cache_exists(char *, uint16_t);
|
||||
|
||||
@@ -2325,7 +2384,7 @@ int uwsgi_netlink_del(char *);
|
||||
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *);
|
||||
char *uwsgi_amqp_consume(int, uint64_t *, char **);
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int);
|
||||
inline int uwsgi_starts_with(char *, int, char *, int);
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -2356,10 +2415,6 @@ ssize_t uwsgi_proto_sctp_read_body(struct wsgi_request *, char *, size_t);
|
||||
#endif
|
||||
|
||||
int uwsgi_proto_http_parser(struct wsgi_request *);
|
||||
ssize_t uwsgi_proto_http_writev_header(struct wsgi_request *, struct iovec *, size_t);
|
||||
ssize_t uwsgi_proto_http_writev(struct wsgi_request *, struct iovec *, size_t);
|
||||
ssize_t uwsgi_proto_http_write(struct wsgi_request *, char *, size_t);
|
||||
ssize_t uwsgi_proto_http_write_header(struct wsgi_request *, char *, size_t);
|
||||
|
||||
int uwsgi_proto_fastcgi_parser(struct wsgi_request *);
|
||||
ssize_t uwsgi_proto_fastcgi_writev_header(struct wsgi_request *, struct iovec *, size_t);
|
||||
@@ -2410,6 +2465,7 @@ void uwsgi_string_del_list(struct uwsgi_string_list **, struct uwsgi_string_list
|
||||
|
||||
void uwsgi_init_all_apps(void);
|
||||
void uwsgi_socket_nb(int);
|
||||
void uwsgi_socket_b(int);
|
||||
|
||||
void uwsgi_destroy_request(struct wsgi_request *);
|
||||
|
||||
@@ -2617,7 +2673,12 @@ void uwsgi_opt_set_str(char *, char *, void *);
|
||||
void uwsgi_opt_set_logger(char *, char *, void *);
|
||||
void uwsgi_opt_set_str_spaced(char *, char *, void *);
|
||||
void uwsgi_opt_add_string_list(char *, char *, void *);
|
||||
void uwsgi_opt_add_dyn_dict(char *, char *, void *);
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_opt_add_regexp_dyn_dict(char *, char *, void *);
|
||||
#endif
|
||||
void uwsgi_opt_set_int(char *, char *, void *);
|
||||
void uwsgi_opt_set_rawint(char *, char *, void *);
|
||||
void uwsgi_opt_set_64bit(char *, char *, void *);
|
||||
void uwsgi_opt_set_megabytes(char *, char *, void *);
|
||||
void uwsgi_opt_set_dyn(char *, char *, void *);
|
||||
@@ -2659,6 +2720,7 @@ void uwsgi_opt_add_daemon(char *, char *, void *);
|
||||
void uwsgi_opt_set_uid(char *, char *, void *);
|
||||
void uwsgi_opt_set_gid(char *, char *, void *);
|
||||
void uwsgi_opt_set_env(char *, char *, void *);
|
||||
void uwsgi_opt_unset_env(char *, char *, void *);
|
||||
void uwsgi_opt_pidfile_signal(char *, char *, void *);
|
||||
void uwsgi_opt_add_app(char *, char *, void *);
|
||||
|
||||
@@ -2695,6 +2757,8 @@ int uwsgi_logic_opt_if_file(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_file(char *, char *);
|
||||
int uwsgi_logic_opt_if_dir(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_dir(char *, char *);
|
||||
int uwsgi_logic_opt_if_reload(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_reload(char *, char *);
|
||||
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
@@ -2745,6 +2809,24 @@ char *uwsgi_read_fd(int, int *, int);
|
||||
|
||||
void uwsgi_setup_post_buffering(void);
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *);
|
||||
|
||||
void uwsgi_write_pidfile(char *);
|
||||
int uwsgi_manage_exception(char *, char *, char *);
|
||||
|
||||
void uwsgi_protected_close(int);
|
||||
ssize_t uwsgi_protected_read(int, void *, size_t);
|
||||
int uwsgi_socket_uniq(struct uwsgi_socket *, struct uwsgi_socket *);
|
||||
int uwsgi_socket_is_already_bound(char *name);
|
||||
|
||||
char *uwsgi_expand_path(char *, int, char *);
|
||||
int uwsgi_try_autoload(char *);
|
||||
|
||||
uint64_t uwsgi_micros(void);
|
||||
int uwsgi_is_file(char *);
|
||||
|
||||
void uwsgi_receive_signal(int, char *, int);
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
#endif
|
||||
@@ -2753,4 +2835,3 @@ int uwsgi_init(int, char **, char **);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+34
-6
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.1'
|
||||
uwsgi_version = '1.2'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -306,6 +306,11 @@ class uConf(object):
|
||||
raise
|
||||
except:
|
||||
self.include_path = ['/usr/include', '/usr/local/include']
|
||||
|
||||
additional_include_paths = self.get('additional_include_paths')
|
||||
if additional_include_paths:
|
||||
for ipath in additional_include_paths.split():
|
||||
self.include_path.append(ipath)
|
||||
|
||||
if not mute:
|
||||
print("detected include path: %s" % self.include_path)
|
||||
@@ -383,6 +388,23 @@ class uConf(object):
|
||||
if self.has_include('ifaddrs.h'):
|
||||
self.cflags.append('-DUWSGI_HAS_IFADDRS')
|
||||
|
||||
if uwsgi_os in ('FreeBSD', 'OpenBSD'):
|
||||
if self.has_include('execinfo.h') or os.path.exists('/usr/local/include/execinfo.h'):
|
||||
if os.path.exists('/usr/local/include/execinfo.h'):
|
||||
self.cflags.append('-I/usr/local/include')
|
||||
self.ldflags.append('-L/usr/local/lib')
|
||||
self.cflags.append('-DUWSGI_HAS_EXECINFO')
|
||||
self.libs.append('-lexecinfo')
|
||||
|
||||
if uwsgi_os == 'OpenBSD':
|
||||
try:
|
||||
obsd_major = int(uwsgi_os_k.split('.')[0])
|
||||
obsd_minor = int(uwsgi_os_k.split('.')[1])
|
||||
if obsd_major >= 5 and obsd_minor > 0:
|
||||
self.cflags.append('-DUWSGI_NEW_OPENBSD')
|
||||
except:
|
||||
pass
|
||||
|
||||
if uwsgi_os == 'SunOS':
|
||||
self.libs.append('-lsendfile')
|
||||
self.gcc_list.append('lib/sun_fixes')
|
||||
@@ -415,16 +437,22 @@ class uConf(object):
|
||||
if uwsgi_os == 'Linux' or uwsgi_os == 'SunOS':
|
||||
locking_mode = 'pthread_mutex'
|
||||
# FreeBSD umtx is still not ready for process shared locking
|
||||
#elif uwsgi_os == 'FreeBSD':
|
||||
# locking_mode = 'umtx'
|
||||
# starting from FreeBSD 9 posix semaphores can be shared between processes
|
||||
elif uwsgi_os == 'FreeBSD':
|
||||
try:
|
||||
fbsd_major = int(uwsgi_os_k.split('.')[0])
|
||||
if fbsd_major >= 9:
|
||||
locking_mode = 'posix_sem'
|
||||
except:
|
||||
pass
|
||||
elif uwsgi_os == 'Darwin':
|
||||
locking_mode = 'osx_spinlock'
|
||||
|
||||
if locking_mode == 'pthread_mutex':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_MUTEX')
|
||||
# FreeBSD umtx is still not ready for process shared locking
|
||||
#elif locking_mode == 'umtx':
|
||||
# self.cflags.append('-DUWSGI_LOCK_USE_UMTX')
|
||||
elif locking_mode == 'posix_sem':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_POSIX_SEM')
|
||||
elif locking_mode == 'osx_spinlock':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_OSX_SPINLOCK')
|
||||
|
||||
@@ -588,7 +616,7 @@ class uConf(object):
|
||||
if self.has_include('uuid/uuid.h'):
|
||||
has_uuid = True
|
||||
self.cflags.append("-DUWSGI_UUID")
|
||||
if os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
|
||||
if uwsgi_os == 'Linux' or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
|
||||
self.libs.append('-luuid')
|
||||
|
||||
if self.get('append_version'):
|
||||
|
||||
+4
-2
@@ -3,7 +3,10 @@ import os
|
||||
import gc
|
||||
import sys
|
||||
from uwsgidecorators import *
|
||||
gc.set_debug(gc.DEBUG_SAVEALL)
|
||||
print(sys.version)
|
||||
print(sys.version_info)
|
||||
if 'set_debug' in gc.__dict__:
|
||||
gc.set_debug(gc.DEBUG_SAVEALL)
|
||||
|
||||
print(os.environ)
|
||||
print(sys.modules)
|
||||
@@ -64,7 +67,6 @@ def setprocname():
|
||||
uwsgi.setprocname("i am the worker %d" % uwsgi.worker_id())
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
try:
|
||||
uwsgi.mule_msg(env['REQUEST_URI'], 1)
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user