mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 07:58:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb1ef28d69 | ||
|
|
1d5b05265d | ||
|
|
d9fef3c30e | ||
|
|
e5dfb9efc3 | ||
|
|
02bab15e86 | ||
|
|
6f4ddead09 | ||
|
|
b361248ff6 | ||
|
|
e9c42ceaa5 | ||
|
|
5d7029744a | ||
|
|
1084a3afa8 | ||
|
|
ed254bffee | ||
|
|
733784d7dd | ||
|
|
cb5b26bcb4 | ||
|
|
0065152bb1 | ||
|
|
03266203fd | ||
|
|
4a5f68f9d8 | ||
|
|
83e31a1c27 | ||
|
|
0efed5ef9c | ||
|
|
cdfef1281d | ||
|
|
e00907e142 | ||
|
|
6dcbcf39e3 | ||
|
|
044579a8e0 | ||
|
|
d2b52b4663 | ||
|
|
7f75b2c02c | ||
|
|
24a3f671e5 | ||
|
|
875100e3c8 | ||
|
|
34bc7c0cfd | ||
|
|
b39a10ff7c | ||
|
|
02331904de | ||
|
|
d1a4ae694e | ||
|
|
7a5ffc1124 | ||
|
|
19c5bfb42c | ||
|
|
893bf3686b | ||
|
|
e54fa9bcd4 | ||
|
|
c1eb5ab0fe | ||
|
|
461914dde4 | ||
|
|
85662578e4 | ||
|
|
a59c0ae795 | ||
|
|
3a860155ee | ||
|
|
27553c2967 | ||
|
|
9a8ac9af3c | ||
|
|
2f5daffe99 | ||
|
|
75cd31dce4 | ||
|
|
f7150d1b41 | ||
|
|
d6a6b65338 | ||
|
|
979f6027b4 | ||
|
|
7dc059c75b | ||
|
|
b639b5974f | ||
|
|
0de08c553c | ||
|
|
80788ac695 | ||
|
|
1494c621c1 | ||
|
|
605e5b5173 | ||
|
|
4cf2213051 | ||
|
|
3aa36668e5 | ||
|
|
1c0b5b42e9 | ||
|
|
702dc44fad | ||
|
|
2cae07aa52 | ||
|
|
b5616ff25c | ||
|
|
b7b7521975 | ||
|
|
dce3263ee3 | ||
|
|
9796e05ca1 | ||
|
|
5cc0d459ec | ||
|
|
531a850a71 | ||
|
|
4c36280287 | ||
|
|
70be8eb55e | ||
|
|
f8b757b21e | ||
|
|
3a63d352bb | ||
|
|
60467705c5 | ||
|
|
eada0c09e0 | ||
|
|
8e851aa6a1 | ||
|
|
eaf7bb967d | ||
|
|
7be45c77b1 | ||
|
|
5e2b460dc8 | ||
|
|
16143e698f | ||
|
|
4259946e3b | ||
|
|
0a750d76ee | ||
|
|
e4a9f5f0dd | ||
|
|
d5b7698f89 | ||
|
|
a481e8508e | ||
|
|
a53b57497b | ||
|
|
d871357b2d | ||
|
|
2d57db55f4 | ||
|
|
bae45ce03a | ||
|
|
44cc4336f1 | ||
|
|
44f6e214fd | ||
|
|
3e46f81d2b | ||
|
|
e4532b9a50 | ||
|
|
2694be562c | ||
|
|
fadb9edd7f | ||
|
|
d85e0790de | ||
|
|
bc46c4d704 | ||
|
|
a73a010188 | ||
|
|
4e8c8ef317 | ||
|
|
e402e7805d | ||
|
|
302b8f026b | ||
|
|
630054b72a | ||
|
|
a05f459b2b | ||
|
|
207979580a | ||
|
|
f69526f8bf | ||
|
|
e249d567a1 | ||
|
|
a23ba653da | ||
|
|
0644d53572 | ||
|
|
f58f51294d | ||
|
|
86194eb93e | ||
|
|
0a89f375e6 | ||
|
|
6282178b3c | ||
|
|
8e14d68022 | ||
|
|
e86bd0c070 | ||
|
|
bf991f8892 | ||
|
|
b341678d20 | ||
|
|
5f59365d88 | ||
|
|
5130a7bb33 | ||
|
|
cc84a596d6 | ||
|
|
e67bed431a | ||
|
|
72613a9f48 | ||
|
|
c048ea0615 | ||
|
|
957ca1b7ed | ||
|
|
d80a6df039 | ||
|
|
94f9bd9d91 | ||
|
|
b480efe672 | ||
|
|
4fc306d979 | ||
|
|
56abccbdeb | ||
|
|
f218af0735 | ||
|
|
9b69c62780 | ||
|
|
eb5d67e07f | ||
|
|
e7391987b1 | ||
|
|
02cbe15575 | ||
|
|
a5a657f0d4 | ||
|
|
67567c86e0 | ||
|
|
445d02da45 | ||
|
|
4a05df41ce | ||
|
|
5c0c2f6b45 | ||
|
|
0ab55fef46 | ||
|
|
dd344bfe38 | ||
|
|
e92a889bcc | ||
|
|
419d656a83 | ||
|
|
3c3d58bfe9 | ||
|
|
1989099cc5 | ||
|
|
1446e3f0a9 | ||
|
|
00fc31289d | ||
|
|
2c463ad6af | ||
|
|
e641ae05c4 | ||
|
|
a13e0075ee | ||
|
|
e617a7b88e | ||
|
|
cbdeb4caad | ||
|
|
59314d692f | ||
|
|
3dfa56b279 | ||
|
|
920d5d7416 | ||
|
|
dcb654d7fb | ||
|
|
a563da1223 | ||
|
|
1e26cda615 | ||
|
|
97133b27ce | ||
|
|
b428bd3b87 | ||
|
|
05136e74b4 | ||
|
|
9f28a8bdf1 | ||
|
|
d9361f1fee | ||
|
|
835230b1a4 | ||
|
|
f88f51c553 | ||
|
|
1996305eb1 | ||
|
|
c7ad50e950 | ||
|
|
0ec0c29d67 | ||
|
|
75af117e8a | ||
|
|
2b04cefe4e | ||
|
|
0e41c4111a | ||
|
|
5f5d382c64 | ||
|
|
3e867fe401 | ||
|
|
153142b8b0 | ||
|
|
5562c0c047 | ||
|
|
f4a1f800ba | ||
|
|
bdbc5e5605 | ||
|
|
4104f825ff | ||
|
|
efa01ea404 | ||
|
|
982559ae66 | ||
|
|
60002e8de8 | ||
|
|
25d671e0f6 | ||
|
|
5a58281a3f | ||
|
|
c422231806 | ||
|
|
4979883fe5 | ||
|
|
8158a624d3 | ||
|
|
06403b5fce | ||
|
|
bc482652fc | ||
|
|
58aa5755e0 | ||
|
|
bca835c58a | ||
|
|
4b0f68a57a | ||
|
|
b693d73ebe | ||
|
|
dfab80447b | ||
|
|
bbde0c866a | ||
|
|
7b3514f757 | ||
|
|
6d5fb3b252 | ||
|
|
87e8f118d3 | ||
|
|
3ae78cc0a8 | ||
|
|
7ef921356f | ||
|
|
378185d997 | ||
|
|
c4b15a8509 | ||
|
|
96ef9d155b | ||
|
|
d5e6412b20 | ||
|
|
eebe757c16 | ||
|
|
43a21d32cb | ||
|
|
9f9eb5ef17 | ||
|
|
0116c62980 | ||
|
|
fae446e495 | ||
|
|
6f7054df18 | ||
|
|
0f31c21f4a | ||
|
|
bd3e234703 | ||
|
|
71bfd63623 | ||
|
|
98b89dc83c | ||
|
|
97ec789bbe | ||
|
|
14b403c046 | ||
|
|
bc01d25068 | ||
|
|
69808c34a8 | ||
|
|
273181daf5 | ||
|
|
8d2394eba1 | ||
|
|
6f5b468b11 | ||
|
|
c9e759bc14 | ||
|
|
e6d064f5c1 | ||
|
|
8f7ed02475 | ||
|
|
f7edcebbdc | ||
|
|
a19b392ba6 | ||
|
|
287df9ef86 | ||
|
|
de7be379c4 | ||
|
|
1e4d41795c | ||
|
|
e2e973a20e | ||
|
|
5d993fbfc0 | ||
|
|
a94a8ea287 | ||
|
|
55d8677a46 | ||
|
|
4004aeb54e | ||
|
|
2de2898d86 | ||
|
|
8c1b48a88d | ||
|
|
9bd3022a5e | ||
|
|
eb0ce609f0 | ||
|
|
5353eba35b | ||
|
|
4f94ceed5e | ||
|
|
cd29998b40 | ||
|
|
9aad6be26a | ||
|
|
19edee88bc | ||
|
|
42e6a7d024 | ||
|
|
1890290d05 | ||
|
|
c85231be96 | ||
|
|
0ca89771d6 | ||
|
|
d203b12464 | ||
|
|
b64690bdd6 | ||
|
|
e76c696678 | ||
|
|
f1ad2090fc | ||
|
|
f0be3c3966 | ||
|
|
8b7abc956f | ||
|
|
25a8af392b | ||
|
|
ebe1b3497e | ||
|
|
6a7246fe5a | ||
|
|
1d64e46fcd | ||
|
|
6d5e089e4e | ||
|
|
845bc1d41b | ||
|
|
007cd73ac5 | ||
|
|
651a7e4078 | ||
|
|
c3423370ec | ||
|
|
500f1e37f6 | ||
|
|
699a9bfa8e | ||
|
|
90aa7f0d0e | ||
|
|
527819703e | ||
|
|
47adc8fe48 | ||
|
|
865ad5d631 | ||
|
|
877b99c1d5 | ||
|
|
45bb124200 | ||
|
|
147af04342 | ||
|
|
b30e54bdc1 | ||
|
|
1b7484cf22 | ||
|
|
c04513f8bd | ||
|
|
c29db6ee6f | ||
|
|
0d60b001fb | ||
|
|
ea7d428c1b | ||
|
|
55ac61dbb0 | ||
|
|
048878b197 | ||
|
|
1e479de839 | ||
|
|
5b34f6c515 | ||
|
|
8fcf83769c | ||
|
|
d1ca55da55 | ||
|
|
375328623b | ||
|
|
be15137a49 | ||
|
|
43d89b2eaf | ||
|
|
d590a189ed | ||
|
|
c26861bff6 | ||
|
|
b4923deae2 | ||
|
|
20e7a65d92 | ||
|
|
fc895d105e | ||
|
|
e0e8dbe6b6 | ||
|
|
8e5834dcbb |
@@ -26,3 +26,11 @@ e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
|
||||
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
|
||||
@@ -12,3 +12,5 @@ Marco Beri, Link I.T. S.p.a.
|
||||
Leonid Borisenko
|
||||
Cal Leeming, Simplicity Media Ltd
|
||||
Luigi Scarso
|
||||
Corey Farwell
|
||||
Charles Duffy
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
*** august 2011 ***
|
||||
|
||||
* 0.9.9 [20110829]
|
||||
|
||||
- various spooler improvements
|
||||
- upload progress optimizations and fixes
|
||||
- new emperor mode: Tyrant
|
||||
- allows multiple --ini options
|
||||
- better binary path detection
|
||||
- gevent loop engine support
|
||||
- resolve domain names in socket logging
|
||||
- snmp fixes and reintroduction of the snmp-api
|
||||
- fixed grunt mode
|
||||
- you can specify build profile via env var UWSGI_PROFILE
|
||||
- reintroduction of string-based multiapp
|
||||
- new option --emperor-throttle
|
||||
- improved queue and sharedarea subsystems
|
||||
- uWSGI can now be built as a shared library
|
||||
- new api attribute: uwsgi.magic_table
|
||||
- improved apache2 module
|
||||
- new option --pyshell
|
||||
- allow threads in gateways
|
||||
- fastrouter improvements
|
||||
- the application list is now shared and exported to the api
|
||||
- allows setting the thread stack size
|
||||
- UWSGI_APPID for better multiapp hosting
|
||||
- better reloading in lazy mode
|
||||
- native pump support
|
||||
- various rack fixes
|
||||
- support for attaching binary data in the executable
|
||||
- new option --set
|
||||
- extreme-optimized http protocol parser
|
||||
- WSGI handler optimizations
|
||||
|
||||
*** july 2011 ***
|
||||
|
||||
* 0.9.8.3 [20110723]
|
||||
|
||||
- implemented uwsgi.SymZipImporter to load embedded zip files
|
||||
- OSX Lion is officially supported
|
||||
- fixed xinetd support (example file added in contrib)
|
||||
- suppot for systemd socket activation
|
||||
- added --freebind option (Linux only)
|
||||
|
||||
* 0.9.8.2 [20110719]
|
||||
|
||||
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
|
||||
|
||||
+76
-52
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define MAX_VARS 64
|
||||
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
|
||||
|
||||
typedef struct {
|
||||
@@ -73,6 +72,7 @@ typedef struct {
|
||||
char script_name[256];
|
||||
char scheme[9];
|
||||
int cgi_mode ;
|
||||
int max_vars;
|
||||
} uwsgi_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
@@ -83,8 +83,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
|
||||
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
|
||||
|
||||
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
if (i+6 > c->max_vars) {
|
||||
#else
|
||||
if (i+4 > c->max_vars) {
|
||||
#endif
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
|
||||
return i;
|
||||
}
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
char *ptr;
|
||||
@@ -150,6 +160,8 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
|
||||
c->modifier1 = 0 ;
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->script_name[0] = 0;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -164,6 +176,13 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
|
||||
c->modifier1 = 0 ;
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->script_name[0] = 0;
|
||||
if (dir) {
|
||||
if (strcmp(dir, "/")) {
|
||||
strncpy(c->script_name, dir, 255);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -243,11 +262,8 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
|
||||
#else
|
||||
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
|
||||
#endif
|
||||
struct iovec *uwsgi_vars;
|
||||
|
||||
int vecptr = 1 ;
|
||||
char pkt_header[4];
|
||||
uint16_t pkt_size = 0;
|
||||
@@ -315,68 +331,49 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
|
||||
#else
|
||||
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
|
||||
#endif
|
||||
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
|
||||
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) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
|
||||
|
||||
if (c->scheme[0] != 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
}
|
||||
|
||||
if (c->script_name[0] == '/') {
|
||||
if (c->script_name[1] == 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
|
||||
}
|
||||
if (c->script_name[0] != 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
if (r->path_info) {
|
||||
if (strlen(r->path_info) <= 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
|
||||
|
||||
headers = apr_table_elts(r->headers_in);
|
||||
h = (apr_table_entry_t *) headers->elts;
|
||||
|
||||
// check for max vars (a bit ugly)
|
||||
cnt = headers->nelts ;
|
||||
if (cnt + 11 > MAX_VARS) {
|
||||
cnt = MAX_VARS -11;
|
||||
}
|
||||
|
||||
for(i=0;i< cnt;i++) {
|
||||
for(i=0;i< headers->nelts;i++) {
|
||||
if (h[i].key){
|
||||
if (!strcasecmp(h[i].key, "Content-Type")) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
|
||||
}
|
||||
else if (!strcasecmp(h[i].key, "Content-Length")) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
|
||||
@@ -388,7 +385,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
*cp = toupper(*cp);
|
||||
}
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,7 +394,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
headers = apr_table_elts(r->subprocess_env);
|
||||
h = (apr_table_entry_t*) headers->elts;
|
||||
for (i = 0; i < headers->nelts; ++i) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -418,11 +415,13 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt != pkt_size+4) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
@@ -434,6 +433,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -458,6 +458,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt == 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
@@ -467,6 +468,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (errno != ECONNRESET) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else {
|
||||
@@ -489,6 +491,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (r->connection->aborted) {
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
apr_brigade_write(bb, NULL, NULL, buf, cnt);
|
||||
@@ -508,6 +511,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -521,6 +525,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
if (!c->cgi_mode) {
|
||||
if (uwsgi_http_status_read == 0) {
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -528,11 +533,13 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return hret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(uwsgi_vars);
|
||||
return ap_pass_brigade(r->output_filters, bb) ;
|
||||
}
|
||||
|
||||
@@ -564,6 +571,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
|
||||
|
||||
}
|
||||
|
||||
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
uwsgi_cfg *c ;
|
||||
int val ;
|
||||
|
||||
if (cfg) {
|
||||
c = cfg ;
|
||||
}
|
||||
else {
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
c->max_vars = atoi(value);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
|
||||
uwsgi_cfg *c ;
|
||||
@@ -707,6 +730,7 @@ static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
|
||||
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
|
||||
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
|
||||
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -212,6 +212,10 @@ void *async_loop(void *arg1) {
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
}
|
||||
|
||||
// set a default request manager
|
||||
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import struct
|
||||
import sys
|
||||
import os
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("pygments_zip"))
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("django_zip:djenv/lib/python2.6/site-packages"))
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("djapp_zip"))
|
||||
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
|
||||
@@ -0,0 +1,3 @@
|
||||
import uwsgi
|
||||
|
||||
print uwsgi.extract("data://0")
|
||||
@@ -28,6 +28,7 @@ bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, ugreen
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embed_files = bootstrap3.py,django.zip,djapp.zip
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = libuwsgi.so
|
||||
embedded_plugins = null
|
||||
as_shared_library = true
|
||||
@@ -1,7 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = +,lua
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = libuwsgi.so
|
||||
embedded_plugins = symcall
|
||||
as_shared_library = true
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = pyuwsgi.so
|
||||
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
|
||||
as_shared_library = true
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = rack, ping, nagios, rpc
|
||||
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
|
||||
|
||||
@@ -8,7 +8,7 @@ void uwsgi_init_cache() {
|
||||
if (!uwsgi.cache_blocksize)
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
if (uwsgi.cache_blocksize % uwsgi.page_size != 0) {
|
||||
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
@@ -138,7 +138,7 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *
|
||||
struct uwsgi_subscriber *usub, nusub;
|
||||
int found = 0;
|
||||
int i;
|
||||
|
||||
|
||||
ptr = uwsgi_dict_get(udict, usr->key, usr->keylen, &vallen);
|
||||
if (ptr && vallen) {
|
||||
usub = (struct uwsgi_subscriber *) ptr;
|
||||
@@ -164,6 +164,8 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *
|
||||
if (found == (int) usub->nodes) {
|
||||
usub->nodes++;
|
||||
}
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
udict->count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -171,9 +173,13 @@ void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *
|
||||
nusub.nodes = 1;
|
||||
nusub.current = 0;
|
||||
memcpy(nusub.names[0].name, usr->address, usr->address_len);
|
||||
nusub.names[0].len = usr->address_len;
|
||||
nusub.names[0].modifier1 = usr->modifier1;
|
||||
nusub.names[0].modifier2 = usr->modifier2;
|
||||
uwsgi_dict_set(udict, usr->key, usr->keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
|
||||
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
udict->count++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -512,6 +518,16 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
uci->prev = last_index;
|
||||
}
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = &uwsgi.cache_items[index] ;
|
||||
if (expires) {
|
||||
expires += time(NULL);
|
||||
uci->expires = expires;
|
||||
}
|
||||
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
|
||||
uci->valsize = vallen;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
@@ -674,6 +690,7 @@ clear:
|
||||
close(ctl_poll.fd);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_cache_server(char *socket, int threads) {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
require 'stringio'
|
||||
|
||||
hello = proc do |signum|
|
||||
puts "Hello i am signal #{signum}"
|
||||
end
|
||||
|
||||
file_changed = proc do |signum|
|
||||
puts "/tmp has been modified"
|
||||
end
|
||||
|
||||
UWSGI.register_signal(17, '', hello)
|
||||
UWSGI.register_signal(30, '', file_changed)
|
||||
|
||||
UWSGI.add_rb_timer(17 , 2)
|
||||
UWSGI.add_timer(17 , 1)
|
||||
UWSGI.add_file_monitor(30 , '/tmp')
|
||||
|
||||
puts UWSGI.signal_registered(1)
|
||||
puts UWSGI.signal_registered(17)
|
||||
|
||||
run lambda { |env|
|
||||
puts env.inspect
|
||||
UWSGI.signal(17)
|
||||
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
from tasksconsumer import enqueue
|
||||
|
||||
def application(env, sr):
|
||||
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
|
||||
enqueue(queue='fast', pippo='pluto')
|
||||
|
||||
return "Task enqueued"
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from tasksconsumer import *
|
||||
|
||||
@queueconsumer('fast', 4)
|
||||
def fast_queue(arguments):
|
||||
print "fast", arguments
|
||||
|
||||
@queueconsumer('slow')
|
||||
def slow_queue(arguments):
|
||||
print "foobar", arguments
|
||||
@@ -0,0 +1,44 @@
|
||||
from uwsgidecorators import *
|
||||
import Queue
|
||||
from threading import Thread
|
||||
|
||||
queues = {}
|
||||
|
||||
class queueconsumer(object):
|
||||
|
||||
def __init__(self, name, num=1, **kwargs):
|
||||
self.name = name
|
||||
self.num = num
|
||||
self.queue = Queue.Queue()
|
||||
self.threads = []
|
||||
self.func = None
|
||||
queues[self.name] = self
|
||||
|
||||
|
||||
@staticmethod
|
||||
def consumer(self):
|
||||
while True:
|
||||
req = self.queue.get()
|
||||
print req
|
||||
self.func(req)
|
||||
self.queue.task_done()
|
||||
|
||||
def __call__(self, f):
|
||||
self.func = f
|
||||
for i in range(self.num):
|
||||
t = Thread(target=self.consumer,args=(self,))
|
||||
self.threads.append(t)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
@spool
|
||||
def spooler_enqueuer(arguments):
|
||||
if 'queue' in arguments:
|
||||
queue = arguments['queue']
|
||||
queues[queue].queue.put(arguments)
|
||||
else:
|
||||
raise Exception("You have to specify a queue name")
|
||||
|
||||
|
||||
def enqueue(*args, **kwargs):
|
||||
return spooler_enqueuer.spool(*args, **kwargs)
|
||||
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
|
||||
# --die-on-term could be a good idea
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
require 'rubygems'
|
||||
require 'socket'
|
||||
begin
|
||||
require 'bundler/setup'
|
||||
rescue LoadError
|
||||
end
|
||||
require 'rack'
|
||||
require 'rack/content_length'
|
||||
require 'rack/rewindable_input'
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
service uwsgi
|
||||
{
|
||||
disable = no
|
||||
id = uwsgi-000
|
||||
type = UNLISTED
|
||||
socket_type = stream
|
||||
server = /root/uwsgi/uwsgi
|
||||
server_args = --chdir /root/uwsgi/ --module welcome --logto /tmp/uwsgi.log
|
||||
port = 3031
|
||||
bind = 127.0.0.1
|
||||
user = root
|
||||
wait = yes
|
||||
}
|
||||
|
||||
+21
-10
@@ -10,8 +10,8 @@ import time
|
||||
|
||||
# register rpc function helloworld
|
||||
@rpc("helloworld")
|
||||
def hello_world():
|
||||
return "Hello World"
|
||||
def hello2():
|
||||
return "[RPC] Hello World"
|
||||
|
||||
# register signal 1
|
||||
@signal(1)
|
||||
@@ -45,6 +45,7 @@ def tmpmodified(num):
|
||||
def a_long_task(args):
|
||||
for i in xrange(1,10):
|
||||
print("%s = %d" % ( str(args), i))
|
||||
print(uwsgi.call('helloworld'))
|
||||
time.sleep(1)
|
||||
|
||||
# continuosly spool a long running task
|
||||
@@ -52,10 +53,12 @@ def a_long_task(args):
|
||||
def an_infinite_task(args):
|
||||
for i in xrange(1,4):
|
||||
print("infinite: %d %s" % (i, str(args)))
|
||||
print(uwsgi.call('helloworld'))
|
||||
uwsgi.signal(100)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
# spool a task after 60 seconds
|
||||
# spool a task after 5 seconds
|
||||
@spool
|
||||
def delayed_task(args):
|
||||
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
|
||||
@@ -89,7 +92,10 @@ def a_running_thread_with_args(who):
|
||||
def a_post_fork_thread():
|
||||
while True:
|
||||
time.sleep(3)
|
||||
print("Hello from a thread in worker %d" % uwsgi.worker_id())
|
||||
if uwsgi.i_am_the_spooler():
|
||||
print("Hello from a thread in the spooler")
|
||||
else:
|
||||
print("Hello from a thread in worker %d" % uwsgi.worker_id())
|
||||
|
||||
@postfork
|
||||
def fork_happened():
|
||||
@@ -97,24 +103,29 @@ def fork_happened():
|
||||
|
||||
@postfork
|
||||
def fork_happened2():
|
||||
print("waiting for a signal...")
|
||||
uwsgi.signal_wait()
|
||||
print("signal received: %d" % uwsgi.signal_received())
|
||||
if uwsgi.i_am_the_spooler():
|
||||
return
|
||||
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
|
||||
uwsgi.signal_wait(100)
|
||||
print("worker %d received signal %d" % (uwsgi.worker_id(), uwsgi.signal_received()))
|
||||
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
|
||||
|
||||
@postfork
|
||||
@lock
|
||||
def locked_func():
|
||||
print("starting locked function on worker %d" % uwsgi.worker_id())
|
||||
for i in xrange(1, 100):
|
||||
time.sleep(0.2)
|
||||
for i in xrange(1, 5):
|
||||
time.sleep(1)
|
||||
print("[locked %d] waiting..." % uwsgi.worker_id())
|
||||
print("done with locked function on worker %d" % uwsgi.worker_id())
|
||||
|
||||
print(uwsgi.call('helloworld'))
|
||||
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
|
||||
print("spool filename = %s" % spool_filename)
|
||||
an_infinite_task.spool(foo='bar', priority=3)
|
||||
delayed_task.spool(foo2='bar2', at=time.time()+60)
|
||||
when = int(time.time())+5
|
||||
print("scheduling a delayed task at %d" % when)
|
||||
delayed_task.spool(foo2='bar2', at=when)
|
||||
a_running_thread()
|
||||
a_running_thread_with_args("uWSGI")
|
||||
uwsgi_source_file = open('uwsgi.c','r')
|
||||
|
||||
@@ -14,10 +14,11 @@ def index(request):
|
||||
w['load'] = (100 * (w['running_time']/1000))/total_load
|
||||
w['last_spawn_str'] = time.ctime(w['last_spawn'])
|
||||
|
||||
spooler_jobs = uwsgi.spooler_jobs()
|
||||
jobs = []
|
||||
for j in spooler_jobs:
|
||||
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
|
||||
if 'spooler' in uwsgi.opt:
|
||||
spooler_jobs = uwsgi.spooler_jobs()
|
||||
for j in spooler_jobs:
|
||||
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
|
||||
|
||||
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
|
||||
'started_on': time.ctime(uwsgi.started_on),
|
||||
|
||||
@@ -8,6 +8,8 @@ extern char **environ;
|
||||
int emperor_queue;
|
||||
char *emperor_absolute_dir;
|
||||
|
||||
void emperor_send_stats(int);
|
||||
|
||||
struct uwsgi_instance {
|
||||
struct uwsgi_instance *ui_prev;
|
||||
struct uwsgi_instance *ui_next;
|
||||
@@ -32,6 +34,9 @@ struct uwsgi_instance {
|
||||
int loyal;
|
||||
|
||||
int zerg;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
|
||||
@@ -169,19 +174,26 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid;
|
||||
char **argv;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
|
||||
sleep(1);
|
||||
usleep(uwsgi.emperor_throttle*1000);
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (uid == 0 || gid == 0) {
|
||||
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
@@ -209,6 +221,8 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
|
||||
memcpy(n_ui->name, name, strlen(name));
|
||||
n_ui->born = born;
|
||||
n_ui->uid = uid;
|
||||
n_ui->gid = gid;
|
||||
n_ui->last_mod = born;
|
||||
// start without loyalty
|
||||
n_ui->last_loyal = born;
|
||||
@@ -253,6 +267,24 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
|
||||
if (setgid(gid)) {
|
||||
uwsgi_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsetenv("UWSGI_RELOADS");
|
||||
unsetenv("NOTIFY_SOCKET");
|
||||
|
||||
@@ -308,9 +340,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
argv[0] = uwsgi.binary_path;
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
@@ -319,29 +351,29 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
}
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
argv[1] = "--xml";
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
argv[1] = "--ini";
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
argv[1] = "--json";
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
argv[2] = name;
|
||||
vassal_argv[2] = name;
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
argv[counter] = "--inherit";
|
||||
argv[counter+1] = uct->filename;
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->filename;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
argv[counter] = NULL;
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
|
||||
@@ -360,7 +392,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(argv[0], argv)) {
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
|
||||
@@ -400,6 +432,8 @@ void emperor_loop() {
|
||||
int interesting_fd;
|
||||
char notification_message[64];
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
uwsgi_unix_signal(SIGINT, royal_death);
|
||||
uwsgi_unix_signal(SIGTERM, royal_death);
|
||||
@@ -420,6 +454,23 @@ void emperor_loop() {
|
||||
uwsgi_log("*** starting uWSGI Emperor ***\n");
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_stats) {
|
||||
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
|
||||
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
|
||||
}
|
||||
|
||||
amqp_port = strchr(uwsgi.emperor_dir, ':');
|
||||
|
||||
if (amqp_port) {
|
||||
@@ -517,7 +568,7 @@ reconnect:
|
||||
}
|
||||
else {
|
||||
if (msgsize > 0) {
|
||||
emperor_add(config_file, time(NULL), config, msgsize);
|
||||
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,13 +605,18 @@ reconnect:
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
else {
|
||||
emperor_add(config_file, time(NULL), NULL, 0);
|
||||
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.emperor_stats_fd) {
|
||||
emperor_send_stats(uwsgi.emperor_stats_fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui_current = emperor_get_by_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
@@ -583,7 +639,7 @@ reconnect:
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
|
||||
emperor_add(zerg_name, time(NULL), NULL, 0);
|
||||
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
@@ -620,13 +676,21 @@ reconnect:
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, sotp the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(de->d_name, st.st_mtime, NULL, 0);
|
||||
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -659,13 +723,21 @@ reconnect:
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, sotp the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0);
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +801,7 @@ reconnect:
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
|
||||
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
@@ -748,3 +820,72 @@ reconnect:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
|
||||
#define stats_send(x, y) fprintf(output, x, y)
|
||||
|
||||
void emperor_send_stats(int fd) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *output = fdopen(client_fd, "w");
|
||||
if (!output) {
|
||||
uwsgi_error("fdopen()");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
|
||||
|
||||
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
|
||||
|
||||
|
||||
fprintf(output, "\"vassals\": [\n");
|
||||
|
||||
struct uwsgi_instance *c_ui = ui->ui_next;
|
||||
|
||||
while (c_ui) {
|
||||
fprintf(output,"\t{");
|
||||
stats_send("\"id\": \"%s\", ", c_ui->name);
|
||||
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
|
||||
|
||||
stats_send_llu( "\"born\": %llu, ", c_ui->born);
|
||||
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
|
||||
|
||||
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
|
||||
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
|
||||
|
||||
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
|
||||
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
|
||||
|
||||
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
if (c_ui) {
|
||||
fprintf(output,"},\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(output,"]}\n");
|
||||
fclose(output);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ void *event_queue_alloc(int nevents) {
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
return (int) pe[id].portev_user;
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
return (int) pe[id].portev_object;
|
||||
@@ -149,7 +149,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
*interesting_fd = (int) pe.portev_user;
|
||||
*interesting_fd = (long) pe.portev_user;
|
||||
}
|
||||
else {
|
||||
*interesting_fd = (int) pe.portev_object;
|
||||
@@ -327,11 +327,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
@@ -476,7 +478,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
fo.fo_ctime = st.st_ctim;
|
||||
|
||||
fmon_id++;
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
|
||||
uwsgi_error("port_associate()");
|
||||
return -1;
|
||||
}
|
||||
@@ -506,7 +508,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
fo.fo_atime = st.st_atim;
|
||||
fo.fo_mtime = st.st_mtim;
|
||||
fo.fo_ctime = st.st_ctim;
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
|
||||
uwsgi_error("port_associate()");
|
||||
return NULL;
|
||||
}
|
||||
@@ -687,13 +689,21 @@ enum
|
||||
|
||||
|
||||
static int timerfd_create (clockid_t __clock_id, int __flags) {
|
||||
#ifdef __amd64__
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int timerfd_settime (int __ufd, int __flags,
|
||||
__const struct itimerspec *__utmr,
|
||||
struct itimerspec *__otmr) {
|
||||
#ifdef __amd64__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -765,7 +775,7 @@ int event_queue_add_timer(int eq, int *id, int sec) {
|
||||
timer_id++;
|
||||
|
||||
pnotif.portnfy_port = eq;
|
||||
pnotif.portnfy_user = (void *) timer_id;
|
||||
pnotif.portnfy_user = (void *) (long) timer_id;
|
||||
|
||||
sigev.sigev_notify = SIGEV_PORT;
|
||||
sigev.sigev_value.sival_ptr = &pnotif;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use POSIX;
|
||||
|
||||
open CONFIG,'welcome.ini';
|
||||
|
||||
dup2(fileno(CONFIG), 17);
|
||||
|
||||
exec './uwsgi','--ini','fd://17';
|
||||
@@ -47,7 +47,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
}
|
||||
}
|
||||
|
||||
gw_pid = fork();
|
||||
gw_pid = uwsgi_fork(name);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return NULL;
|
||||
@@ -60,6 +60,11 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!uwsgi.sockets) {
|
||||
// wait for child end
|
||||
//waitpid(-1, &i, 0);
|
||||
}
|
||||
loop();
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
@@ -85,7 +90,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
|
||||
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
@@ -98,7 +103,7 @@ void gateway_respawn(int id) {
|
||||
pid_t gw_pid;
|
||||
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
|
||||
|
||||
gw_pid = fork();
|
||||
gw_pid = uwsgi_fork(ug->name);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
@@ -117,6 +122,12 @@ void gateway_respawn(int id) {
|
||||
}
|
||||
|
||||
ug->pid = gw_pid;
|
||||
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
ug->respawns++;
|
||||
if (ug->respawns == 1) {
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
import uwsgi
|
||||
uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
return "<h1>Hello World</h1>"
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
|
||||
@@ -92,7 +92,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
if (!uwsgi_startswith(file, "http://", 7)) {
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
char *colon;
|
||||
int i;
|
||||
|
||||
if (!uwsgi_startswith(file, "http://", 7)) {
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
@@ -49,7 +49,11 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
|
||||
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
#ifdef JANSSON_MAJOR_VERSION
|
||||
root = json_loads(json_data, 0, &error);
|
||||
#else
|
||||
root = json_loads(json_data, &error);
|
||||
#endif
|
||||
|
||||
if (!root) {
|
||||
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ void uwsgi_lock(void *lock) {
|
||||
void uwsgi_unlock(void *lock) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) {
|
||||
|
||||
@@ -50,7 +50,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->do_not_log) return ;
|
||||
|
||||
if (wsgi_req->app_id >= 0) {
|
||||
wi = &uwsgi.apps[wsgi_req->app_id];
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
if (wi->requests > 0) {
|
||||
app_req = wi->requests;
|
||||
}
|
||||
@@ -129,22 +129,22 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
rlen = writev(2, logvec, logvecpos+1);
|
||||
}
|
||||
|
||||
void get_memusage() {
|
||||
void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
|
||||
*vsz = syscall(356);
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
@@ -152,8 +152,8 @@ void get_memusage() {
|
||||
procfd = open("/proc/self/psinfo", O_RDONLY);
|
||||
if (procfd >= 0) {
|
||||
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
|
||||
*rss = (uint64_t) info.pr_rssize * 1024;
|
||||
*vsz = (uint64_t) info.pr_size * 1024;
|
||||
}
|
||||
close(procfd);
|
||||
}
|
||||
@@ -164,8 +164,8 @@ void get_memusage() {
|
||||
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
|
||||
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
|
||||
*rss = t_info.resident_size;
|
||||
*vsz = t_info.virtual_size;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
kvm_t *kv;
|
||||
@@ -184,8 +184,8 @@ void get_memusage() {
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kinfo_proc2 *kproc2;
|
||||
@@ -193,11 +193,11 @@ void get_memusage() {
|
||||
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
|
||||
if (kproc2 && cnt > 0) {
|
||||
#ifdef __OpenBSD__
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
#else
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
#endif
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -207,13 +207,14 @@ void get_memusage() {
|
||||
area_info ai;
|
||||
int32 cookie;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
*vsz = 0;
|
||||
*rss = 0;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
|
||||
*vsz += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
|
||||
*rss += ai.ram_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ void uwsgi_subscribe(char *subscription) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ':');
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
@@ -135,7 +135,7 @@ void uwsgi_subscribe(char *subscription) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ':');
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
@@ -159,7 +159,7 @@ void uwsgi_subscribe(char *subscription) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key+1, ':');
|
||||
modifier1 = strchr(subscription_key+1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
@@ -168,7 +168,7 @@ void uwsgi_subscribe(char *subscription) {
|
||||
|
||||
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ':';
|
||||
modifier1[-1] = ',';
|
||||
}
|
||||
|
||||
clear:
|
||||
@@ -238,7 +238,7 @@ void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t val
|
||||
}
|
||||
}
|
||||
|
||||
void master_loop(char **argv, char **environ) {
|
||||
int master_loop(char **argv, char **environ) {
|
||||
|
||||
uint64_t tmp_counter;
|
||||
|
||||
@@ -284,15 +284,28 @@ void master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_SNMP
|
||||
int snmp_fd = -1;
|
||||
#endif
|
||||
|
||||
int i=0;
|
||||
int rlen;
|
||||
|
||||
int check_interval = 1;
|
||||
uint64_t overload_count = 0;
|
||||
uint64_t idle_count = 0;
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct rb_root *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
uwsgi_set_processname(uwsgi.procname_master);
|
||||
}
|
||||
else if (uwsgi.procname) {
|
||||
uwsgi_set_processname(uwsgi.procname);
|
||||
}
|
||||
else if (uwsgi.auto_procname) {
|
||||
uwsgi_set_processname("uWSGI master");
|
||||
}
|
||||
|
||||
|
||||
uwsgi.current_time = time(NULL);
|
||||
|
||||
uwsgi_unix_signal(SIGHUP, grace_them_all);
|
||||
@@ -318,6 +331,15 @@ void master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding %d to signal poll (spooler)\n", uwsgi.shared->spooler_signal_pipe[0]);
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding %d to master logging\n", uwsgi.shared->worker_log_pipe[0]);
|
||||
@@ -337,6 +359,23 @@ void master_loop(char **argv, char **environ) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
|
||||
uwsgi_log("*** Zerg server enabled on %s ***\n", uwsgi.zerg_server);
|
||||
}
|
||||
|
||||
if (uwsgi.stats) {
|
||||
char *tcp_port = strchr(uwsgi.stats, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
uwsgi.stats_fd = bind_to_tcp(uwsgi.stats, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
uwsgi.stats_fd = bind_to_unix(uwsgi.stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.stats_fd);
|
||||
uwsgi_log("*** Stats server enabled on %s fd: %d ***\n", uwsgi.stats, uwsgi.stats_fd);
|
||||
}
|
||||
#ifdef UWSGI_UDP
|
||||
if (uwsgi.udp_socket) {
|
||||
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
|
||||
@@ -351,6 +390,9 @@ void master_loop(char **argv, char **environ) {
|
||||
|
||||
if (uwsgi.cheap) {
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
}
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
@@ -450,10 +492,12 @@ void master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
// spawn mules
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
size_t mule_patch_size = 0;
|
||||
uwsgi.mules[i].patch = uwsgi_string_get_list(&uwsgi.mules_patches, i, &mule_patch_size);
|
||||
uwsgi_mule(i+1);
|
||||
}
|
||||
|
||||
// spawn fat gateways
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
@@ -476,30 +520,42 @@ void master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_store && uwsgi.queue_filesize) {
|
||||
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
|
||||
if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) {
|
||||
uwsgi_error("msync()");
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.touch_reload) {
|
||||
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
|
||||
while(touch_reload) {
|
||||
struct stat tr_st;
|
||||
if (stat(uwsgi.touch_reload, &tr_st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
|
||||
uwsgi.touch_reload = NULL;
|
||||
if (stat(touch_reload->value, &tr_st)) {
|
||||
uwsgi_log("unable to stat() %s, reload will be triggered as soon as the file is created\n", touch_reload->value);
|
||||
touch_reload->custom = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.last_touch_reload_mtime = tr_st.st_mtime;
|
||||
touch_reload->custom = (uint64_t) tr_st.st_mtime;
|
||||
}
|
||||
touch_reload = touch_reload->next;
|
||||
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
|
||||
|
||||
if (uwsgi.to_outworld) {
|
||||
//uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc);
|
||||
if (uwsgi.lazy_respawned >= uwsgi.numproc) {
|
||||
uwsgi.to_outworld = 0;
|
||||
uwsgi.master_mercy = 0;
|
||||
uwsgi.lazy_respawned = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_mercy) {
|
||||
if (uwsgi.master_mercy < time(NULL)) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.lazy && uwsgi.workers[i].destroy == 0) continue;
|
||||
uwsgi_log("worker %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i, uwsgi.workers[i].pid);
|
||||
if (!kill(uwsgi.workers[i].pid, SIGKILL)) {
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
@@ -508,17 +564,22 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
if (uwsgi.to_hell) { ready_to_die++;}
|
||||
else if (uwsgi.to_heaven) { ready_to_reload++;}
|
||||
else if (uwsgi.to_outworld) {
|
||||
uwsgi.lazy_respawned++;
|
||||
if (uwsgi_respawn_worker(i)) return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi.master_mercy = 0;
|
||||
}
|
||||
}
|
||||
if (uwsgi.respawn_workers) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi_respawn_worker(i)) return;
|
||||
if (uwsgi_respawn_worker(i)) return 0;
|
||||
}
|
||||
|
||||
uwsgi.respawn_workers = 0;
|
||||
@@ -546,9 +607,74 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi.restore_snapshot = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// cheaper management
|
||||
if (uwsgi.cheaper) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].busy == 0) {
|
||||
if (overload_count > 0) overload_count--;
|
||||
goto healthy;
|
||||
}
|
||||
}
|
||||
}
|
||||
overload_count++;
|
||||
idle_count = 0;
|
||||
}
|
||||
|
||||
healthy:
|
||||
if (uwsgi.cheaper) {
|
||||
if (overload_count > 3) {
|
||||
// activate the first available worker
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
if (uwsgi_respawn_worker(i)) return 0;
|
||||
overload_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (overload_count == 0) {
|
||||
// how many active workers ?
|
||||
idle_count++;
|
||||
int active_workers = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
// find the oldest worker and cheap it
|
||||
if (active_workers > uwsgi.cheaper_count+1 || (idle_count > 60 && active_workers > uwsgi.cheaper_count)) {
|
||||
time_t oldest_worker_spawn = INT_MAX;
|
||||
int oldest_worker = 0;
|
||||
idle_count = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
|
||||
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
|
||||
oldest_worker = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldest_worker > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
// wakeup task in case of wait
|
||||
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
|
||||
overload_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((uwsgi.cheap || ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
|
||||
// call a series of waitpid to ensure all processes (gateways and daemons) are dead
|
||||
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
@@ -556,8 +682,8 @@ void master_loop(char **argv, char **environ) {
|
||||
exit(0);
|
||||
}
|
||||
if ( (uwsgi.cheap || ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
|
||||
// call a series of waitpid to ensure all processes (gateways and daemons) are dead
|
||||
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
@@ -602,6 +728,9 @@ void master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return -1;
|
||||
#else
|
||||
uwsgi_log( "running %s\n", uwsgi.binary_path);
|
||||
argv[0] = uwsgi.binary_path;
|
||||
//strcpy (argv[0], uwsgi.binary_path);
|
||||
@@ -609,6 +738,7 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!uwsgi.cheap) {
|
||||
@@ -629,6 +759,16 @@ void master_loop(char **argv, char **environ) {
|
||||
else {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
if (diedpid == -1) {
|
||||
if (errno == ECHILD && uwsgi.cheaper) {
|
||||
if (uwsgi.to_heaven) {
|
||||
ready_to_reload = uwsgi.numproc;
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi.to_hell) {
|
||||
ready_to_die = uwsgi.numproc;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uwsgi_error("waitpid()");
|
||||
/* here is better to reload all the uWSGI stack */
|
||||
uwsgi_log( "something horrible happened...\n");
|
||||
@@ -738,11 +878,20 @@ void master_loop(char **argv, char **environ) {
|
||||
else if (uwsgi.log_socket) {
|
||||
sendto(uwsgi.log_socket_fd, log_buf, rlen, 0, &uwsgi.log_socket_addr->sa, uwsgi.log_socket_size);
|
||||
}
|
||||
else {
|
||||
rlen = write(uwsgi.original_log_fd, log_buf, rlen);
|
||||
}
|
||||
// TODO allow uwsgi.logger = func
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
uwsgi_send_stats(uwsgi.stats_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
if (interesting_fd == uwsgi.zerg_server_fd) {
|
||||
struct sockaddr_un zsun;
|
||||
@@ -829,7 +978,7 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi.cheap = 0;
|
||||
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi_respawn_worker(i)) return;
|
||||
if (uwsgi_respawn_worker(i)) return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -999,23 +1148,75 @@ void master_loop(char **argv, char **environ) {
|
||||
//uwsgi.workers[i].pipe[0] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
// check for spooler signal
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
|
||||
rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("received uwsgi signal %d from the spooler\n", uwsgi_signal);
|
||||
#endif
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("lost connection with the spooler\n");
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
uwsgi.current_time = time(NULL);
|
||||
// checking logsize
|
||||
if (uwsgi.logfile) {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
/*
|
||||
if (uwsgi.shared->logsize > 8192) {
|
||||
//uwsgi_log("logsize: %d\n", uwsgi.shared->logsize);
|
||||
char *new_logfile = uwsgi_malloc(strlen(uwsgi.logfile) + 14 + 1);
|
||||
memset(new_logfile, 0, strlen(uwsgi.logfile) + 14 + 1);
|
||||
if (!rename(uwsgi.logfile, new_logfile)) {
|
||||
// close 2, reopen logfile dup'it and gracefully reload workers;
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int)time(NULL));
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
free(new_logfile);
|
||||
char message[1024];
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
rlen = write(uwsgi.original_log_fd, message, ret);
|
||||
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// close 2, reopen logfile dup'it and gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC , S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -1147,10 +1348,43 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi.workers[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
// then for evil memory checkers
|
||||
if (uwsgi.evil_reload_on_as) {
|
||||
if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid );
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
}
|
||||
}
|
||||
if (uwsgi.evil_reload_on_rss) {
|
||||
if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid );
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// need to find a better way
|
||||
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].harakiri > 0) {
|
||||
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i+1, uwsgi.mules[i].signum, uwsgi.mules[i].pid );
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid > 0 && uwsgi.shared->spooler_harakiri > 0) {
|
||||
if (uwsgi.shared->spooler_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uwsgi.shared->spooler_pid);
|
||||
kill(uwsgi.shared->spooler_pid, SIGKILL);
|
||||
uwsgi.shared->spooler_harakiri = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
// check for cluster nodes
|
||||
@@ -1177,25 +1411,26 @@ void master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((uwsgi.master_cycles % uwsgi.queue_store_sync) == 0)) {
|
||||
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
|
||||
if (msync(uwsgi.queue_header, uwsgi.queue_filesize, MS_ASYNC)) {
|
||||
uwsgi_error("msync()");
|
||||
}
|
||||
}
|
||||
|
||||
// check touch_reload
|
||||
if (uwsgi.touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
|
||||
while (touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
struct stat tr_st;
|
||||
if (stat(uwsgi.touch_reload, &tr_st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("unable to stat() %s, touch-reload will be disabled\n", uwsgi.touch_reload);
|
||||
uwsgi.touch_reload = NULL;
|
||||
if (stat(touch_reload->value, &tr_st)) {
|
||||
touch_reload->custom = 0;
|
||||
}
|
||||
else {
|
||||
if (tr_st.st_mtime > uwsgi.last_touch_reload_mtime) {
|
||||
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", uwsgi.touch_reload);
|
||||
if ((uint64_t)tr_st.st_mtime > touch_reload->custom) {
|
||||
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touch_reload->value);
|
||||
grace_them_all(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
touch_reload = touch_reload->next;
|
||||
}
|
||||
|
||||
|
||||
@@ -1213,12 +1448,27 @@ void master_loop(char **argv, char **environ) {
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (diedpid == uwsgi.shared->spooler_pid) {
|
||||
uwsgi_log( "OOOPS the spooler is no more...trying respawn...\n");
|
||||
uwsgi.spooler_respawned++;
|
||||
uwsgi.shared->spooler_pid = spooler_start();
|
||||
//event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pid_found = 0;
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("OOOPS mule %d crippled...trying respawn...\n", i+1);
|
||||
uwsgi_mule(i+1);
|
||||
pid_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pid_found) continue;
|
||||
|
||||
|
||||
/* reload the gateways */
|
||||
// TODO reload_gateway(diedpid);
|
||||
pid_found = 0;
|
||||
@@ -1259,6 +1509,37 @@ void master_loop(char **argv, char **environ) {
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (diedpid == uwsgi.shared->spooler_pid) {
|
||||
uwsgi_log("spooler (pid: %d) annihilated\n", (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("mule %d (pid: %d) annihilated\n", i+1, (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
if (uwsgi.gateways[i].pid == diedpid) {
|
||||
uwsgi_log("gateway %d (pid: %d) annihilated\n", i+1, (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.shared->daemons_cnt;i++) {
|
||||
if (uwsgi.shared->daemons[i].pid == diedpid) {
|
||||
uwsgi_log("daemon %d (pid: %d) annihilated\n", i+1, (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (WIFEXITED(waitpid_status)) {
|
||||
uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status));
|
||||
}
|
||||
@@ -1268,10 +1549,12 @@ void master_loop(char **argv, char **environ) {
|
||||
else if (WIFSTOPPED(waitpid_status)) {
|
||||
uwsgi_log("subprocess %d stopped\n", (int) diedpid);
|
||||
}
|
||||
next:
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
if (uwsgi.to_heaven) {
|
||||
ready_to_reload++;
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
@@ -1286,11 +1569,24 @@ void master_loop(char **argv, char **environ) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi.to_outworld) {
|
||||
uwsgi.lazy_respawned++;
|
||||
uwsgi.workers[uwsgi.mywid].destroy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
uwsgi_log( "DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int)diedpid);
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
gettimeofday(&last_respawn, NULL);
|
||||
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
|
||||
last_respawn_rate++;
|
||||
@@ -1314,7 +1610,7 @@ void master_loop(char **argv, char **environ) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid)) return;
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid)) return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+184
-37
@@ -2,6 +2,8 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void worker_wakeup() {}
|
||||
|
||||
void master_check_cluster_nodes() {
|
||||
|
||||
int i;
|
||||
@@ -31,24 +33,67 @@ void master_check_cluster_nodes() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
|
||||
int i;
|
||||
|
||||
// close the cache server
|
||||
if (uwsgi.cache_server_fd != -1) {
|
||||
close(uwsgi.cache_server_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
|
||||
if (i != wid) {
|
||||
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].signal_pipe[0] != -1) close(uwsgi.mules[i].signal_pipe[0]);
|
||||
if (muleid != i+1) {
|
||||
if (uwsgi.mules[i].signal_pipe[1] != -1) close(uwsgi.mules[i].signal_pipe[1]);
|
||||
if (uwsgi.mules[i].queue_pipe[1] != -1) close(uwsgi.mules[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
|
||||
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
int i;
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.signal_pipe[wid][0] != -1) close(uwsgi.signal_pipe[wid][0]);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.signal_pipe[wid])) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
|
||||
|
||||
if (pid == 0) {
|
||||
signal(SIGWINCH, worker_wakeup);
|
||||
uwsgi.mywid = wid;
|
||||
uwsgi.mypid = getpid();
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
@@ -59,43 +104,33 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi.workers[uwsgi.mywid].respawn_count++;
|
||||
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
|
||||
uwsgi.workers[uwsgi.mywid].cheaped = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
|
||||
// close the cache server
|
||||
if (uwsgi.cache_server_fd != -1) {
|
||||
close(uwsgi.cache_server_fd);
|
||||
}
|
||||
// reset the apps count with a copy from the master
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
|
||||
uwsgi_fixup_fds(wid, 0);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.signal_pipe[i][0] != -1) {
|
||||
close(uwsgi.signal_pipe[i][0]);
|
||||
}
|
||||
}
|
||||
uwsgi.my_signal_socket = uwsgi.signal_pipe[wid][1];
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
#endif
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (pid < 1) {
|
||||
uwsgi_error("fork()");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.master_process) {
|
||||
close(uwsgi.signal_pipe[wid][1]);
|
||||
}
|
||||
if (respawns > 0) {
|
||||
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
|
||||
}
|
||||
@@ -257,3 +292,115 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
|
||||
#define stats_send(x, y) fprintf(output, x, y)
|
||||
|
||||
void uwsgi_send_stats(int fd) {
|
||||
|
||||
int i,j;
|
||||
struct sockaddr_un client_src;
|
||||
struct uwsgi_app *ua;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *output = fdopen(client_fd, "w");
|
||||
if (!output) {
|
||||
uwsgi_error("fdopen()");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
#ifdef __linux__
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
|
||||
#endif
|
||||
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
fprintf(output, "\"workers\": [\n");
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
fprintf(output,"\t{");
|
||||
|
||||
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
|
||||
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
|
||||
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
|
||||
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output,"\"status\": \"cheap\", ");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output,"\"status\": \"busy\", ");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"\"status\": \"idle\", ");
|
||||
}
|
||||
}
|
||||
|
||||
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i+1].rss_size);
|
||||
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i+1].vsz_size);
|
||||
|
||||
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i+1].running_time);
|
||||
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i+1].last_spawn);
|
||||
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i+1].respawn_count);
|
||||
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i+1].tx);
|
||||
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i+1].avg_response_time);
|
||||
|
||||
fprintf(output,"\"apps\": [\n");
|
||||
|
||||
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
|
||||
ua = &uwsgi.workers[i+1].apps[j];
|
||||
fprintf(output,"\t\t{ ");
|
||||
|
||||
fprintf(output, "\"id\": %d, ", j);
|
||||
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
|
||||
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
|
||||
|
||||
stats_send_llu( "\"requests\": %llu, ", ua->requests);
|
||||
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
|
||||
|
||||
if (ua->chdir) {
|
||||
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\"chdir\": \"\" ");
|
||||
}
|
||||
|
||||
if (j == uwsgi.workers[i+1].apps_cnt-1) {
|
||||
fprintf(output,"}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output,"\t\t]");
|
||||
|
||||
if (i == uwsgi.numproc-1) {
|
||||
fprintf(output,"}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output,"]}\n");
|
||||
fclose(output);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
|
||||
uWSGI mules are very simple workers only managing signals or running custom code in background.
|
||||
|
||||
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
|
||||
|
||||
*/
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_mule_handler(void);
|
||||
|
||||
void uwsgi_mule(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
|
||||
if (pid == 0) {
|
||||
uwsgi.muleid = id;
|
||||
// avoid race conditions
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = getpid();
|
||||
|
||||
uwsgi_fixup_fds(0, id);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
|
||||
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
|
||||
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.mules[id-1].patch) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
|
||||
uwsgi_log("loaded mule patch %s\n", uwsgi.mules[id-1].patch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = pid;
|
||||
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
|
||||
while(umf) {
|
||||
if (umf->mule->id == muleid) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_signaled(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_msg(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_mule_add_farm_to_queue(int queue) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_handler() {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t uwsgi_signal;
|
||||
int rlen;
|
||||
int interesting_fd;
|
||||
|
||||
// this must be configurable
|
||||
char message[65536];
|
||||
|
||||
int mule_queue = event_queue_init();
|
||||
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
|
||||
|
||||
uwsgi_mule_add_farm_to_queue(mule_queue);
|
||||
|
||||
for(;;) {
|
||||
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
|
||||
if (rlen <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else if (len == 0) {
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_mule *get_mule_by_id(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].id == id) {
|
||||
return &uwsgi.mules[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
|
||||
|
||||
if (!uwsgi_mf) {
|
||||
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
uwsgi_mf = *umf;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_mf) {
|
||||
old_umf = uwsgi_mf;
|
||||
uwsgi_mf = uwsgi_mf->next;
|
||||
}
|
||||
|
||||
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
old_umf->next = uwsgi_mf;
|
||||
}
|
||||
|
||||
uwsgi_mf->mule = um;
|
||||
uwsgi_mf->next = NULL;
|
||||
|
||||
return uwsgi_mf;
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ int erlang_init() {
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
|
||||
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+121
-16
@@ -19,6 +19,7 @@
|
||||
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
|
||||
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
|
||||
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
|
||||
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
|
||||
|
||||
#define FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
@@ -42,6 +43,8 @@ struct uwsgi_fastrouter {
|
||||
int use_cache;
|
||||
int nevents;
|
||||
|
||||
int queue;
|
||||
|
||||
int subscription_slot;
|
||||
|
||||
char *pattern;
|
||||
@@ -55,7 +58,14 @@ struct uwsgi_fastrouter {
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
uint8_t code_string_modifier1;
|
||||
char *code_string_code;
|
||||
char *code_string_function;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
|
||||
int cheap;
|
||||
int i_am_cheap;
|
||||
} ufr;
|
||||
|
||||
|
||||
@@ -90,7 +100,9 @@ struct option fastrouter_options[] = {
|
||||
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
|
||||
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
|
||||
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
|
||||
{"fastrouter-use-code-string", required_argument, 0, LONG_ARGS_FASTROUTER_USE_CODE_STRING},
|
||||
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
|
||||
{"fastrouter-cheap", no_argument, &ufr.cheap, 1},
|
||||
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
|
||||
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
|
||||
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
|
||||
@@ -150,8 +162,22 @@ static void close_session(struct fastrouter_session **fr_table, struct fastroute
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
if (fr_session->instance_fd != -1) {
|
||||
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
fr_session->un->len = 0;
|
||||
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);
|
||||
if (fr_session->un->len > 0) {
|
||||
if (ufr.subscription_dict->count > 0) {
|
||||
ufr.subscription_dict->count--;
|
||||
}
|
||||
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
|
||||
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
@@ -216,7 +242,6 @@ struct fastrouter_session *alloc_fr_session() {
|
||||
|
||||
void fastrouter_loop() {
|
||||
|
||||
int fr_queue;
|
||||
int nevents;
|
||||
int interesting_fd;
|
||||
int new_connection;
|
||||
@@ -263,7 +288,7 @@ void fastrouter_loop() {
|
||||
fr_table[i] = NULL;
|
||||
}
|
||||
|
||||
fr_queue = event_queue_init();
|
||||
ufr.queue = event_queue_init();
|
||||
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
|
||||
@@ -287,7 +312,15 @@ void fastrouter_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(fr_queue, ufr_sock->fd);
|
||||
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
|
||||
|
||||
if (!ufr.cheap) {
|
||||
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fastrouter] cheap mode requested. Waiting for subscriptions...\n");
|
||||
ufr.i_am_cheap = 1;
|
||||
}
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
|
||||
@@ -297,7 +330,7 @@ void fastrouter_loop() {
|
||||
|
||||
if (ufr.subscription_server) {
|
||||
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
|
||||
event_queue_add_fd_read(fr_queue, ufr_subserver);
|
||||
event_queue_add_fd_read(ufr.queue, ufr_subserver);
|
||||
if (!ufr.subscription_slot) ufr.subscription_slot = 30;
|
||||
ufr.subscription_dict = uwsgi_dict_create(ufr.subscription_slot, 0);
|
||||
}
|
||||
@@ -323,7 +356,7 @@ void fastrouter_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
nevents = event_queue_wait_multi(fr_queue, delta, events, ufr.nevents);
|
||||
nevents = event_queue_wait_multi(ufr.queue, delta, events, ufr.nevents);
|
||||
|
||||
if (nevents == 0) {
|
||||
expire_timeouts(fr_table);
|
||||
@@ -350,12 +383,13 @@ void fastrouter_loop() {
|
||||
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
|
||||
fr_table[new_connection]->h_pos = 0;
|
||||
fr_table[new_connection]->pos = 0;
|
||||
fr_table[new_connection]->un = NULL;
|
||||
fr_table[new_connection]->instance_failed = 0;
|
||||
fr_table[new_connection]->instance_address_len = 0;
|
||||
|
||||
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
|
||||
|
||||
event_queue_add_fd_read(fr_queue, new_connection);
|
||||
event_queue_add_fd_read(ufr.queue, new_connection);
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
@@ -370,12 +404,21 @@ void fastrouter_loop() {
|
||||
if (interesting_fd == ufr_subserver) {
|
||||
len = recv(ufr_subserver, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(fr_queue, ufr_subserver);
|
||||
event_queue_add_fd_read(ufr.queue, ufr_subserver);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
|
||||
uwsgi_add_subscriber(ufr.subscription_dict, &usr);
|
||||
if (ufr.i_am_cheap) {
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 0;
|
||||
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -434,6 +477,11 @@ void fastrouter_loop() {
|
||||
#endif
|
||||
if (ufr.use_cache) {
|
||||
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
}
|
||||
else if (ufr.pattern) {
|
||||
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
|
||||
@@ -455,6 +503,19 @@ void fastrouter_loop() {
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = tmp_socket_name;
|
||||
}
|
||||
else if (ufr.code_string_code && ufr.code_string_function) {
|
||||
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
|
||||
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
|
||||
if (fr_session->instance_address) {
|
||||
fr_session->instance_address_len = strlen(fr_session->instance_address);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no address found
|
||||
if (!fr_session->instance_address_len) {
|
||||
@@ -471,8 +532,22 @@ void fastrouter_loop() {
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
if (ufr.subscription_server) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
fr_session->un->len = 0;
|
||||
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);
|
||||
if (fr_session->un->len > 0) {
|
||||
fr_session->un->len = 0;
|
||||
if (ufr.subscription_dict->count > 0) {
|
||||
ufr.subscription_dict->count--;
|
||||
}
|
||||
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
|
||||
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
@@ -481,7 +556,7 @@ void fastrouter_loop() {
|
||||
|
||||
fr_session->status = FASTROUTER_STATUS_CONNECTING;
|
||||
fr_table[fr_session->instance_fd] = fr_session;
|
||||
event_queue_add_fd_write(fr_queue, fr_session->instance_fd);
|
||||
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -547,7 +622,7 @@ void fastrouter_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
event_queue_fd_write_to_read(fr_queue, fr_session->instance_fd);
|
||||
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
|
||||
fr_session->status = FASTROUTER_STATUS_RESPONSE;
|
||||
}
|
||||
|
||||
@@ -625,9 +700,17 @@ int fastrouter_init() {
|
||||
|
||||
if (!ufr.nevents) ufr.nevents = 64;
|
||||
|
||||
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
|
||||
uwsgi_log("unable to register the fastrouter gateway\n");
|
||||
exit(1);
|
||||
if (ufr.code_string_code && ufr.code_string_function) {
|
||||
if (register_fat_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
|
||||
uwsgi_log("unable to register the fastrouter gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (register_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
|
||||
uwsgi_log("unable to register the fastrouter gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,6 +719,10 @@ int fastrouter_init() {
|
||||
|
||||
int fastrouter_opt(int i, char *optarg) {
|
||||
|
||||
char *cs;
|
||||
char *cs_code;
|
||||
char *cs_func;
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_FASTROUTER:
|
||||
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
|
||||
@@ -656,6 +743,24 @@ int fastrouter_opt(int i, char *optarg) {
|
||||
// optimization
|
||||
ufr.base_len = strlen(ufr.base);
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_USE_CODE_STRING:
|
||||
cs = uwsgi_str(optarg);
|
||||
cs_code = strchr(cs, ':');
|
||||
if (!cs_code) {
|
||||
uwsgi_log("invalid code_string option\n");
|
||||
exit(1);
|
||||
}
|
||||
cs_code[0] = 0;
|
||||
cs_func = strchr(cs_code+1, ':');
|
||||
if (!cs_func) {
|
||||
uwsgi_log("invalid code_string option\n");
|
||||
exit(1);
|
||||
}
|
||||
cs_func[0] = 0;
|
||||
ufr.code_string_modifier1 = atoi(cs);
|
||||
ufr.code_string_code = cs_code+1;
|
||||
ufr.code_string_function = cs_func+1;
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_TIMEOUT:
|
||||
ufr.socket_timeout = atoi(optarg);
|
||||
return -1;
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
struct option gevent_options[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#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 stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
|
||||
if (ret) Py_DECREF(ret);\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
if (ret) Py_DECREF(ret);
|
||||
|
||||
struct uwsgi_gevent {
|
||||
PyObject *greenlet_switch;
|
||||
PyObject *greenlet_switch_args;
|
||||
PyObject *get_current;
|
||||
PyObject *get_current_args;
|
||||
PyObject *hub;
|
||||
PyObject *hub_loop;
|
||||
PyObject *spawn;
|
||||
PyObject *greenlet_args;
|
||||
PyObject *signal_args;
|
||||
} ugevent;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
|
||||
|
||||
// spawn the signal_handler greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
// yes copy&paste no-DRY for me :P
|
||||
PyObject *py_uwsgi_gevent_my_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.my_signal_socket));
|
||||
|
||||
// spawn the signal_handler greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
|
||||
|
||||
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
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 );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.core[wsgi_req->async_id]->in_request = 1;
|
||||
|
||||
gettimeofday(&wsgi_req->start_of_request, NULL);
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
|
||||
uwsgi_close_request(wsgi_req);
|
||||
free_req_queue;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// hack to easily pass wsgi_req pointer to the greenlet
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
|
||||
|
||||
// spawn the request greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
|
||||
|
||||
PyObject *ret;
|
||||
|
||||
// start the io watcher
|
||||
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
|
||||
if (!ret) return NULL;
|
||||
Py_DECREF(ret);
|
||||
|
||||
// start the timeout handler
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) return NULL;
|
||||
Py_DECREF(ret);
|
||||
|
||||
// pass control to the hub
|
||||
return PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *ret;
|
||||
PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);
|
||||
int status ;
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
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;
|
||||
|
||||
// a timer to implement timeoit (thanks Denis)
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) goto clear0;
|
||||
|
||||
for(;;) {
|
||||
// wait for data in the socket
|
||||
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) {
|
||||
uwsgi_log( "timeout. skip request.\n");
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (ret == watcher) {
|
||||
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (status == 0) {
|
||||
stop_the_watchers;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unrecognized gevent event !!!\n");
|
||||
goto clear_and_stop;
|
||||
}
|
||||
|
||||
stop_the_watchers;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// switch after each yield
|
||||
GEVENT_SWITCH;
|
||||
}
|
||||
|
||||
goto clear;
|
||||
|
||||
clear_and_stop:
|
||||
|
||||
stop_the_watchers;
|
||||
|
||||
clear:
|
||||
Py_DECREF(timer);
|
||||
clear0:
|
||||
Py_DECREF(watcher);
|
||||
clear1:
|
||||
Py_DECREF(greenlet_switch);
|
||||
Py_DECREF(current_greenlet);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
free_req_queue;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
|
||||
}
|
||||
|
||||
PyMethodDef uwsgi_gevent_main_def[] = { {"uwsgi_gevent_main", py_uwsgi_gevent_main, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_request_def[] = { {"uwsgi_gevent_request", py_uwsgi_gevent_request, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_gevent_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
|
||||
|
||||
void gevent_loop() {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the gevent loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
|
||||
if (!gevent_dict) uwsgi_pyexit;
|
||||
|
||||
PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info");
|
||||
if (!gevent_version) uwsgi_pyexit;
|
||||
|
||||
if (PyInt_AsLong(PyTuple_GetItem(gevent_version, 0)) < 1) {
|
||||
uwsgi_log("uWSGI requires at least gevent 1.x version\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
|
||||
if (!ugevent.spawn) uwsgi_pyexit;
|
||||
|
||||
ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep");
|
||||
if (!ugevent.greenlet_switch) uwsgi_pyexit;
|
||||
|
||||
ugevent.greenlet_switch_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.greenlet_switch_args);
|
||||
|
||||
|
||||
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
|
||||
|
||||
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
|
||||
if (!ugevent.hub) uwsgi_pyexit;
|
||||
|
||||
ugevent.get_current = PyDict_GetItemString(gevent_dict, "getcurrent");
|
||||
if (!ugevent.get_current) uwsgi_pyexit;
|
||||
|
||||
ugevent.get_current_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.get_current_args);
|
||||
|
||||
|
||||
ugevent.hub_loop = PyObject_GetAttrString(ugevent.hub, "loop");
|
||||
if (!ugevent.hub_loop) uwsgi_pyexit;
|
||||
|
||||
// this is the watcher for server socket
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi_sock->fd, 1);
|
||||
if (!watcher) uwsgi_pyexit;
|
||||
|
||||
// main greenlet waiting for connection
|
||||
PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL);
|
||||
Py_INCREF(uwsgi_gevent_main);
|
||||
|
||||
// greenlet to run at each request
|
||||
PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL);
|
||||
Py_INCREF(uwsgi_request_greenlet);
|
||||
|
||||
// pre-fill the greenlet args
|
||||
ugevent.greenlet_args = PyTuple_New(2);
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 0, uwsgi_request_greenlet);
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
// and these are the watcher for signal sockets
|
||||
|
||||
PyObject *signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.signal_socket, 1);
|
||||
if (!signal_watcher) uwsgi_pyexit;
|
||||
|
||||
PyObject *my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1);
|
||||
if (!my_signal_watcher) uwsgi_pyexit;
|
||||
|
||||
PyObject *uwsgi_greenlet_signal = PyCFunction_New(uwsgi_gevent_signal_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_signal);
|
||||
|
||||
PyObject *uwsgi_greenlet_my_signal = PyCFunction_New(uwsgi_gevent_my_signal_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_my_signal);
|
||||
|
||||
PyObject *uwsgi_greenlet_signal_handler = PyCFunction_New(uwsgi_gevent_signal_handler_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_signal_handler);
|
||||
|
||||
ugevent.signal_args = PyTuple_New(2);
|
||||
PyTuple_SetItem(ugevent.signal_args, 0, uwsgi_greenlet_signal_handler);
|
||||
|
||||
// start the two signal watchers
|
||||
if (!PyObject_CallMethod(signal_watcher, "start", "O", uwsgi_greenlet_signal)) uwsgi_pyexit;
|
||||
if (!PyObject_CallMethod(my_signal_watcher, "start", "O", uwsgi_greenlet_my_signal)) uwsgi_pyexit;
|
||||
|
||||
}
|
||||
|
||||
// start the main greenlet
|
||||
PyObject_CallMethod(watcher, "start", "O", uwsgi_gevent_main);
|
||||
|
||||
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
uwsgi_log("the gevent Hub is no more :(\n");
|
||||
|
||||
}
|
||||
|
||||
int gevent_init() {
|
||||
|
||||
uwsgi_register_loop( (char *) "gevent", gevent_loop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin gevent_plugin = {
|
||||
|
||||
.name = "gevent",
|
||||
.init = gevent_init,
|
||||
.options = gevent_options,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='gevent'
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['gevent']
|
||||
+20
-3
@@ -136,6 +136,8 @@ struct http_session {
|
||||
char uss[MAX_HTTP_VEC*2];
|
||||
|
||||
char buffer[UMAX16];
|
||||
char path_info[UMAX16];
|
||||
uint16_t path_info_len;
|
||||
|
||||
struct uwsgi_subscriber_name *un;
|
||||
|
||||
@@ -325,13 +327,19 @@ int http_parse(struct http_session *h_session) {
|
||||
base = ptr;
|
||||
while(ptr < watermark) {
|
||||
if (*ptr == '?' && !query_string) {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
h_session->path_info_len = ptr-base;
|
||||
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
|
||||
query_string = ptr+1;
|
||||
}
|
||||
else if (*ptr == ' ') {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_URI", 11, base, ptr-base, &c);
|
||||
if (!query_string) {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
h_session->path_info_len = ptr-base;
|
||||
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, "", 0, &c);
|
||||
}
|
||||
else {
|
||||
@@ -403,6 +411,14 @@ int http_parse(struct http_session *h_session) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i=0;i<uhttp.http_vars_cnt;i++) {
|
||||
char *equal = strchr(uhttp.http_vars[i],'=');
|
||||
if (equal) {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, uhttp.http_vars[i], equal-uhttp.http_vars[i], equal+1, strlen(equal+1), &c);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("vec size: %d pkt size: %d load %d\n", c, h_session->uh.pktsize, uhttp.load);
|
||||
#endif
|
||||
@@ -639,6 +655,7 @@ void http_loop() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
uhttp_session->pass_fd = is_unix(uhttp_session->instance_address, uhttp_session->instance_address_len);
|
||||
|
||||
uhttp_session->instance_fd = uwsgi_connectn(uhttp_session->instance_address, uhttp_session->instance_address_len, 0, 1);
|
||||
@@ -874,7 +891,7 @@ int http_init() {
|
||||
|
||||
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
|
||||
|
||||
if (register_gateway("http", http_loop) == NULL) {
|
||||
if (register_gateway("uWSGI http", http_loop) == NULL) {
|
||||
uwsgi_log("unable to register the http gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+95
-25
@@ -374,7 +374,7 @@ void uwsgi_lua_app() {
|
||||
luaL_openlibs(ulua.L[i]);
|
||||
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
|
||||
if (luaL_loadfile(ulua.L[i], ulua.filename)) {
|
||||
uwsgi_log("unable to load file %s\n", ulua.filename);
|
||||
uwsgi_log("unable to load file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
|
||||
exit(1);
|
||||
}
|
||||
// use a pcall
|
||||
@@ -403,8 +403,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
|
||||
if (lua_type(L, -1) == LUA_TSTRING) {
|
||||
http = lua_tolstring(L, -1, &slen);
|
||||
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
wsgi_req->response_size += rlen;
|
||||
@@ -420,12 +419,12 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard WSAPI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log( "Invalid WSAPI request. skip.\n");
|
||||
goto clear;
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
uwsgi_log("Invalid WSAPI request. skip.\n");
|
||||
goto clear;
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
// put function in the stack
|
||||
@@ -453,12 +452,16 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
lua_setfield(L, -2, "read");
|
||||
lua_setfield(L, -2, "input");
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("stack pos %d\n", lua_gettop(L));
|
||||
#endif
|
||||
|
||||
// call function
|
||||
i = lua_pcall(L, 1, 3, 0);
|
||||
if (i != 0) {
|
||||
uwsgi_log("%s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -468,26 +471,30 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
// send status
|
||||
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
|
||||
http = lua_tolstring(L, -3, &slen);
|
||||
if (write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len) != wsgi_req->protocol_len) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len)) != wsgi_req->protocol_len) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
if (write(wsgi_req->poll.fd, " ", 1) != 1) {
|
||||
perror("write()");
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, " ", 1)) != 1) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
|
||||
perror("write()");
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
// a performance hack
|
||||
ptrbuf = (char *) http;
|
||||
ptrbuf[3] = 0;
|
||||
wsgi_req->status = atoi(ptrbuf);
|
||||
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
}
|
||||
else {
|
||||
raw = 1;
|
||||
@@ -499,31 +506,41 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -3) != 0) {
|
||||
http = lua_tolstring(L, -2, &slen);
|
||||
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
if (write(wsgi_req->poll.fd, ": ", 2) != 2) {
|
||||
perror("write()");
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, ": ", 2)) != 2) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
http = lua_tolstring(L, -1, &slen);
|
||||
if (write(wsgi_req->poll.fd, http, slen) != (ssize_t) slen) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
lua_pop(L, 1);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
|
||||
if (!raw) {
|
||||
if (write(wsgi_req->poll.fd, "\r\n", 2) != 2) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
}
|
||||
|
||||
// send body with coroutine
|
||||
@@ -532,8 +549,9 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
|
||||
if (lua_type(L, -1) == LUA_TSTRING) {
|
||||
http = lua_tolstring(L, -1, &slen);
|
||||
if ( (rlen = write(wsgi_req->poll.fd, http, slen)) != (ssize_t) slen) {
|
||||
perror("write()");
|
||||
if ( (rlen = wsgi_req->socket->proto_write(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pop(L, 1);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += rlen;
|
||||
@@ -550,6 +568,7 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
clear:
|
||||
|
||||
lua_pop(L, 4);
|
||||
clear2:
|
||||
|
||||
// set frequency
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
@@ -590,6 +609,55 @@ int uwsgi_lua_magic(char *mountpoint, char *lazy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_t keylen) {
|
||||
|
||||
static struct lua_State *L = NULL;
|
||||
|
||||
if (!L) {
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) {
|
||||
uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1));
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
return NULL;
|
||||
}
|
||||
lua_getglobal(L, func);
|
||||
if (!lua_isfunction(L,-1)) {
|
||||
uwsgi_log("unable to find %s function in lua file %s\n", func, code);
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
return NULL;
|
||||
}
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushlstring(L, key, keylen);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key);
|
||||
#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;
|
||||
|
||||
}
|
||||
|
||||
if (lua_isstring(L, -1)) {
|
||||
const char *ret = lua_tolstring(L, -1, NULL);
|
||||
return (char *)ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
@@ -664,6 +732,8 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.init_apps = uwsgi_lua_app,
|
||||
.magic = uwsgi_lua_magic,
|
||||
.signal_handler = uwsgi_lua_signal_handler,
|
||||
|
||||
.code_string = uwsgi_lua_code_string,
|
||||
.rpc = uwsgi_lua_rpc,
|
||||
|
||||
};
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ struct uwsgi_perl {
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
void uwsgi_psgi_app(void);
|
||||
int psgi_response(struct wsgi_request *, PerlInterpreter *, AV*);
|
||||
int psgi_response(struct wsgi_request *, AV*);
|
||||
|
||||
#define psgi_xs(func) newXS("uwsgi::" #func, XS_##func, "uwsgi")
|
||||
#define psgi_check_args(x) if (items < x) Perl_croak(aTHX_ "Usage: uwsgi::%s takes %d arguments", __FUNCTION__ + 3, x)
|
||||
|
||||
+26
-14
@@ -41,19 +41,11 @@ XS(XS_stream)
|
||||
AV *response = (AV* ) SvREFCNT_inc(SvRV(ST(0))) ;
|
||||
|
||||
if (av_len(response) == 2) {
|
||||
|
||||
#ifdef my_perl
|
||||
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
|
||||
#else
|
||||
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
|
||||
#endif
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
}
|
||||
else if (av_len(response) == 1) {
|
||||
#ifdef my_perl
|
||||
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
|
||||
#else
|
||||
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
|
||||
#endif
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
|
||||
XSRETURN(1);
|
||||
@@ -236,6 +228,7 @@ xs_init(pTHX)
|
||||
void uwsgi_psgi_app() {
|
||||
|
||||
struct stat stat_psgi;
|
||||
int id = uwsgi_apps_cnt;
|
||||
|
||||
if (uperl.psgi) {
|
||||
|
||||
@@ -291,7 +284,6 @@ void uwsgi_psgi_app() {
|
||||
|
||||
uperl.psgibuffer[stat_psgi.st_size] = 0;
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
@@ -303,11 +295,31 @@ void uwsgi_psgi_app() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
free(uperl.psgibuffer);
|
||||
close(uperl.fd);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[id];
|
||||
memset(wi, 0, sizeof(struct uwsgi_app));
|
||||
|
||||
wi->modifier1 = 5;
|
||||
wi->mountpoint = "";
|
||||
wi->mountpoint_len = 0;
|
||||
|
||||
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
|
||||
// check if we need to emulate fork() COW
|
||||
int i;
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
|
||||
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("PSGI app (%s) loaded at %p\n", uperl.psgi, uperl.psgi_main);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+45
-63
@@ -23,7 +23,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SV *newobj;
|
||||
// set current context ?
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -49,7 +49,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
|
||||
|
||||
SV *ret = NULL;
|
||||
// set current context ?
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -79,7 +79,7 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
int ret;
|
||||
// set current context ? needed for threading
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -107,6 +107,7 @@ SV *uwsgi_perl_obj_call(SV *obj, char *method) {
|
||||
|
||||
SV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -140,6 +141,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
AV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -149,6 +151,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
PUTBACK;
|
||||
|
||||
call_sv(psgi_func, G_SCALAR | G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
@@ -280,7 +283,7 @@ int uwsgi_perl_init(){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
int argc = 3;
|
||||
int argc;
|
||||
uperl.embedding[0] = "";
|
||||
uperl.embedding[1] = "-e";
|
||||
uperl.embedding[2] = "0";
|
||||
@@ -298,6 +301,9 @@ int uwsgi_perl_init(){
|
||||
#else
|
||||
uwsgi_log("initializing Perl environment\n");
|
||||
#endif
|
||||
|
||||
argc = 3;
|
||||
|
||||
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
|
||||
uperl.main = perl_alloc();
|
||||
if (!uperl.main) {
|
||||
@@ -323,51 +329,19 @@ int uwsgi_perl_init(){
|
||||
|
||||
}
|
||||
|
||||
#ifdef my_perl
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_enable_threads() {
|
||||
|
||||
int i;
|
||||
|
||||
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.interp = malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
if (!uperl.interp) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
uperl.interp[0] = uperl.main;
|
||||
|
||||
for(i=1;i<uwsgi.threads;i++) {
|
||||
uperl.interp[i] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
|
||||
|
||||
uperl.psgi_func = malloc( sizeof(SV*) * uwsgi.threads );
|
||||
if (!uperl.psgi_func) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
dTHXa(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main);
|
||||
|
||||
uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -378,12 +352,10 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
SV **harakiri;
|
||||
SV *psgi_func = uperl.psgi_main;
|
||||
// ugly hack
|
||||
register PerlInterpreter *my_perl = uperl.main;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
return psgi_response(wsgi_req, my_perl, wsgi_req->async_placeholder);
|
||||
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -398,19 +370,14 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1 && wsgi_req->async_id > 0) {
|
||||
if (uwsgi.threads > 1) {
|
||||
psgi_func = uperl.psgi_func[wsgi_req->async_id];
|
||||
my_perl = pthread_getspecific(uperl.u_interpreter);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
|
||||
wsgi_req->async_environ = build_psgi_env(wsgi_req);
|
||||
if (!wsgi_req->async_environ) goto clear;
|
||||
|
||||
@@ -428,7 +395,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
while (psgi_response(wsgi_req, my_perl, wsgi_req->async_result) != UWSGI_OK) {
|
||||
while (psgi_response(wsgi_req, wsgi_req->async_result) != UWSGI_OK) {
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
FREETMPS;
|
||||
@@ -468,26 +435,41 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
if (core_id > 0) {
|
||||
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[core_id]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
dTHXa(uperl.interp[core_id]);
|
||||
PERL_SET_CONTEXT(uperl.interp[core_id]);
|
||||
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uperl.psgibuffer, 0);
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
uperl.psgi_func[0] = uperl.psgi_main;
|
||||
if (core_id > 0) {
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_perl_manage_options(int i, char *optarg) {
|
||||
|
||||
@@ -528,11 +510,11 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
//.magic = uwsgi_perl_magic,
|
||||
//.help = uwsgi_perl_help,
|
||||
#ifdef my_perl
|
||||
#ifdef USE_ITHREADS
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
#endif
|
||||
.manage_opt = uwsgi_perl_manage_options,
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
.request = uwsgi_perl_request,
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
|
||||
|
||||
@@ -2,54 +2,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* statistically ordered */
|
||||
struct http_status_codes hsc[] = {
|
||||
{"200", "OK"},
|
||||
{"302", "Found"},
|
||||
{"404", "Not Found"},
|
||||
{"500", "Internal Server Error"},
|
||||
{"301", "Moved Permanently"},
|
||||
{"304", "Not Modified"},
|
||||
{"303", "See Other"},
|
||||
{"403", "Forbidden"},
|
||||
{"307", "Temporary Redirect"},
|
||||
{"401", "Unauthorized"},
|
||||
{"400", "Bad Request"},
|
||||
{"405", "Method Not Allowed"},
|
||||
{"408", "Request Timeout"},
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
{"100", "Continue"},
|
||||
{"101", "Switching Protocols"},
|
||||
{"201", "Created"},
|
||||
{"202", "Accepted"},
|
||||
{"203", "Non-Authoritative Information"},
|
||||
{"204", "No Content"},
|
||||
{"205", "Reset Content"},
|
||||
{"206", "Partial Content"},
|
||||
{"300", "Multiple Choices"},
|
||||
{"305", "Use Proxy"},
|
||||
{"402", "Payment Required"},
|
||||
{"406", "Not Acceptable"},
|
||||
{"407", "Proxy Authentication Required"},
|
||||
{"409", "Conflict"},
|
||||
{"410", "Gone"},
|
||||
{"411", "Length Required"},
|
||||
{"412", "Precondition Failed"},
|
||||
{"413", "Request Entity Too Large"},
|
||||
{"414", "Request-URI Too Long"},
|
||||
{"415", "Unsupported Media Type"},
|
||||
{"416", "Requested Range Not Satisfiable"},
|
||||
{"417", "Expectation Failed"},
|
||||
{"501", "Not Implemented"},
|
||||
{"502", "Bad Gateway"},
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{ "", NULL },
|
||||
};
|
||||
|
||||
|
||||
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
|
||||
int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
|
||||
SV **status_code, **hitem ;
|
||||
AV *headers, *body =NULL;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import os,sys
|
||||
|
||||
NAME='psgi'
|
||||
CFLAGS = [os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip()]
|
||||
LDFLAGS = [os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip()]
|
||||
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
|
||||
LDFLAGS = os.popen('perl -MExtUtils::Embed -e ldopts').read().rstrip().split()
|
||||
LIBS = []
|
||||
GCC_LIST = ['uwsgi_plmodule', 'psgi_loader', 'psgi_response', 'psgi_plugin']
|
||||
|
||||
for item in LDFLAGS:
|
||||
if item.endswith('DynaLoader.a'):
|
||||
GCC_LIST.append(item)
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
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
|
||||
@@ -26,5 +31,7 @@ void gil_real_release() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void gil_fake_get() {}
|
||||
void gil_fake_release() {}
|
||||
|
||||
@@ -15,6 +15,7 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
|
||||
|
||||
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
switch(what) {
|
||||
case PyTrace_CALL:
|
||||
uwsgi_log("[uWSGI Python profiler] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
@@ -29,6 +30,7 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
|
||||
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
#include "uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
|
||||
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
PyObject *zero;
|
||||
|
||||
int i;
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
|
||||
char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
|
||||
if (port) {
|
||||
|
||||
zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
|
||||
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyString_FromStringAndSize("80", 2);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "method", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
if (wsgi_req->post_cl > 0) {
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl));
|
||||
if (wsgi_req->content_type_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *headers = PyDict_New();
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
if (wsgi_req->hvec[i].iov_len < 6) continue;
|
||||
if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) {
|
||||
(void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
|
||||
#ifdef PYTHREE
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL);
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
|
||||
#else
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
#endif
|
||||
PyObject *old_value = PyDict_GetItem(headers, pydictkey);
|
||||
if (old_value) {
|
||||
if (PyString_Check(old_value)) {
|
||||
PyObject *new_value = PyList_New(0);
|
||||
PyList_Append(new_value, old_value);
|
||||
old_value = new_value;
|
||||
PyDict_SetItem(headers, pydictkey, old_value);
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
PyList_Append(old_value, pydictvalue);
|
||||
}
|
||||
else {
|
||||
PyDict_SetItem(headers, pydictkey, pydictvalue);
|
||||
}
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
|
||||
Py_DECREF(headers);
|
||||
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "pump_body", "rb", 0, NULL, NULL, NULL, 0);
|
||||
#else
|
||||
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "pump_body", "r", NULL);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// create wsgi.input custom object
|
||||
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
|
||||
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
|
||||
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);
|
||||
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
else if (wsgi_req->https_len > 0) {
|
||||
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
|
||||
zero = PyString_FromString("https");
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
}
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
}
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
|
||||
wsgi_req->async_app = wi->callable;
|
||||
|
||||
// export .env only in non-threaded mode
|
||||
if (uwsgi.threads < 2) {
|
||||
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
|
||||
|
||||
if (uwsgi.cores > 1) {
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
|
||||
}
|
||||
|
||||
// cache this ?
|
||||
if (uwsgi.cluster_fd >= 0) {
|
||||
zero = PyString_FromString(uwsgi.cluster);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
|
||||
Py_DECREF(zero);
|
||||
zero = PyString_FromString(uwsgi.hostname);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
|
||||
|
||||
|
||||
// call
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
int i;
|
||||
|
||||
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)) {
|
||||
|
||||
|
||||
PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
|
||||
if (!status) {
|
||||
uwsgi_log("invalid Pump response (status code).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
|
||||
if (!headers) {
|
||||
uwsgi_log("invalid Pump response (headers).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
wsgi_req->async_placeholder = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body");
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
uwsgi_log("invalid Pump response (body).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// get the status code
|
||||
if (!PyInt_Check(status)) {
|
||||
uwsgi_log("invalid Pump response (status code).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
|
||||
uwsgi_log("invalid Pump response (status code).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) {
|
||||
wsgi_req->hvec[4].iov_base = (char *) http_sc->message;
|
||||
wsgi_req->hvec[4].iov_len = http_sc->message_size;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_log("invalid Pump response (status code).\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
|
||||
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
|
||||
wsgi_req->hvec[1].iov_base = " ";
|
||||
wsgi_req->hvec[1].iov_len = 1;
|
||||
wsgi_req->hvec[2].iov_base = sc;
|
||||
wsgi_req->hvec[2].iov_len = 3;
|
||||
wsgi_req->hvec[3].iov_base = " ";
|
||||
wsgi_req->hvec[3].iov_len = 1;
|
||||
wsgi_req->hvec[5].iov_base = "\r\n";
|
||||
wsgi_req->hvec[5].iov_len = 2;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
|
||||
UWSGI_GET_GIL
|
||||
if (wsize < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += wsize;
|
||||
|
||||
PyObject *hhkey, *hhvalue;
|
||||
#ifdef UWSGI_PYTHON_OLD
|
||||
int hhpos = 0;
|
||||
#else
|
||||
Py_ssize_t hhpos = 0;
|
||||
#endif
|
||||
while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
|
||||
if (!PyString_Check(hhkey)) continue;
|
||||
|
||||
wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey);
|
||||
wsgi_req->hvec[0].iov_len = PyString_Size(hhkey);
|
||||
((char*)wsgi_req->hvec[0].iov_base)[0] = toupper((int) ((char*)wsgi_req->hvec[0].iov_base)[0]);
|
||||
|
||||
wsgi_req->hvec[1].iov_base = ": ";
|
||||
wsgi_req->hvec[1].iov_len = 2;
|
||||
|
||||
wsgi_req->hvec[3].iov_base = "\r\n";
|
||||
wsgi_req->hvec[3].iov_len = 2;
|
||||
if (PyList_Check(hhvalue)) {
|
||||
for(i=0;i<PyList_Size(hhvalue);i++) {
|
||||
PyObject *item = PyList_GetItem(hhvalue, i);
|
||||
if (PyString_Check(item)) {
|
||||
wsgi_req->hvec[2].iov_base = PyString_AsString(item);
|
||||
wsgi_req->hvec[2].iov_len = PyString_Size(item);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
|
||||
UWSGI_GET_GIL
|
||||
if (wsize < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += wsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PyString_Check(hhvalue)) {
|
||||
wsgi_req->hvec[2].iov_base = PyString_AsString(hhvalue);
|
||||
wsgi_req->hvec[2].iov_len = PyString_Size(hhvalue);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
|
||||
UWSGI_GET_GIL
|
||||
if (wsize < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += wsize;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2);
|
||||
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
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;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
|
||||
#else
|
||||
else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) {
|
||||
wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder));
|
||||
#endif
|
||||
wsize = uwsgi_sendfile(wsgi_req);
|
||||
if (wsize < 0) {
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
|
||||
|
||||
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
|
||||
|
||||
Py_DECREF(tmp);
|
||||
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
goto clear;
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("invalid Pump response.\n");
|
||||
goto clear;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder);
|
||||
|
||||
if (!pychunk) {
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
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;
|
||||
}
|
||||
|
||||
+154
-66
@@ -22,12 +22,62 @@ PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_re
|
||||
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
|
||||
#endif
|
||||
|
||||
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter) {
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
|
||||
void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
|
||||
|
||||
|
||||
char venv_version[15];
|
||||
PyObject *site_module;
|
||||
|
||||
PyObject *pysys_dict = get_uwsgi_pydict("sys");
|
||||
|
||||
PyObject *pypath = pypath = PyDict_GetItemString(pysys_dict, "path");
|
||||
if (!pypath) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// simulate a pythonhome directive
|
||||
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
||||
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
||||
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
|
||||
|
||||
venv_version[14] = 0;
|
||||
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check here
|
||||
PyString_Concat(&venv_path, PyString_FromString(venv_version));
|
||||
|
||||
if (PyList_Insert(pypath, 0, venv_path)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
site_module = PyImport_ImportModule("site");
|
||||
if (site_module) {
|
||||
PyImport_ReloadModule(site_module);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) {
|
||||
|
||||
PyObject *zero;
|
||||
PyObject *app_list = NULL, *applications = NULL;
|
||||
|
||||
int id = uwsgi.apps_cnt;
|
||||
int id = uwsgi_apps_cnt;
|
||||
int multiapp = 0;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
@@ -38,23 +88,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
if (wsgi_req->script_name_len == 0) {
|
||||
wsgi_req->script_name = "";
|
||||
}
|
||||
else if (wsgi_req->script_name_len == 1) {
|
||||
if (wsgi_req->script_name[0] == '/') {
|
||||
wsgi_req->script_name = "";
|
||||
wsgi_req->script_name_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
mountpoint = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|", 1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
}
|
||||
else {
|
||||
mountpoint = uwsgi_strncopy(wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
}
|
||||
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
|
||||
|
||||
if (uwsgi_get_app_id(mountpoint, strlen(mountpoint), -1) != -1) {
|
||||
uwsgi_log( "mountpoint %.*s already configured. skip.\n", strlen(mountpoint), mountpoint);
|
||||
@@ -63,7 +98,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
|
||||
|
||||
wi = &uwsgi.apps[id];
|
||||
wi = &uwsgi_apps[id];
|
||||
|
||||
memset(wi, 0, sizeof(struct uwsgi_app));
|
||||
wi->mountpoint = mountpoint;
|
||||
@@ -110,7 +145,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value));
|
||||
#endif
|
||||
|
||||
if (PyObject_SetItem(py_environ, k, env_value)) {
|
||||
PyErr_Print();
|
||||
@@ -125,7 +162,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (interpreter == NULL && id) {
|
||||
|
||||
wi->interpreter = Py_NewInterpreter();
|
||||
if (!wi->interpreter) {
|
||||
uwsgi_log( "unable to initialize the new python interpreter\n");
|
||||
@@ -148,6 +187,13 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
wi->interpreter = up.main_thread;
|
||||
}
|
||||
|
||||
if (wsgi_req->pyhome_len) {
|
||||
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
|
||||
}
|
||||
#else
|
||||
wi->interpreter = up.main_thread;
|
||||
#endif
|
||||
|
||||
if (wsgi_req->touch_reload_len) {
|
||||
struct stat trst;
|
||||
char *touch_reload = uwsgi_strncopy(wsgi_req->touch_reload, wsgi_req->touch_reload_len);
|
||||
@@ -160,7 +206,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
wi->callable = up.loaders[loader](arg1);
|
||||
|
||||
if (!wi->callable) {
|
||||
uwsgi_log("unable to load app SCRIPT_NAME=%s\n", mountpoint);
|
||||
uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, mountpoint);
|
||||
goto doh;
|
||||
}
|
||||
|
||||
@@ -184,12 +230,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
wi->mountpoint = PyString_AsString(app_mnt);
|
||||
wi->mountpoint_len = strlen(wi->mountpoint);
|
||||
wsgi_req->script_name = wi->mountpoint;
|
||||
wsgi_req->script_name_len = wi->mountpoint_len;
|
||||
wsgi_req->appid = wi->mountpoint;
|
||||
wsgi_req->appid_len = wi->mountpoint_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("main mountpoint = %s\n", wi->mountpoint);
|
||||
#endif
|
||||
wi->callable = PyDict_GetItem(applications, app_mnt);
|
||||
if (PyString_Check((PyObject *) wi->callable)) {
|
||||
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
|
||||
if (callables_dict) {
|
||||
wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Py_INCREF((PyObject *)wi->callable);
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
|
||||
if (!wi->environ) {
|
||||
@@ -212,47 +268,29 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
#endif
|
||||
|
||||
// check function args
|
||||
// by defaut it is a WSGI app
|
||||
wi->argc = 2;
|
||||
zero = PyObject_GetAttrString(wi->callable, "__code__");
|
||||
if (!zero) {
|
||||
zero = PyObject_GetAttrString(wi->callable, "__call__");
|
||||
if (zero) {
|
||||
zero = PyObject_GetAttrString(wi->callable, "__code__");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("WARNING: unable to get the number of callable args. Fallback to WSGI\n");
|
||||
}
|
||||
}
|
||||
wi->argc = 1;
|
||||
|
||||
// avoid __code__ attr error propagation
|
||||
PyErr_Clear();
|
||||
|
||||
if (zero) {
|
||||
zero = PyObject_GetAttrString(zero, "co_argcount");
|
||||
wi->argc = (int) PyInt_AsLong(zero);
|
||||
}
|
||||
|
||||
if (wi->argc == 2) {
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("-- WSGI callable detected --\n");
|
||||
uwsgi_log("-- WSGI callable selected --\n");
|
||||
#endif
|
||||
wi->request_subhandler = uwsgi_request_subhandler_wsgi;
|
||||
wi->response_subhandler = uwsgi_response_subhandler_wsgi;
|
||||
wi->argc = 2;
|
||||
}
|
||||
#ifdef UWSGI_WEB3
|
||||
else if (wi->argc == 1) {
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("-- Web3 callable detected --\n");
|
||||
uwsgi_log("-- Web3 callable selected --\n");
|
||||
#endif
|
||||
wi->request_subhandler = uwsgi_request_subhandler_web3;
|
||||
wi->response_subhandler = uwsgi_response_subhandler_web3;
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("-- Pump callable selected --\n");
|
||||
#endif
|
||||
else {
|
||||
uwsgi_log("-- INVALID callable detected --\n");
|
||||
goto doh;
|
||||
wi->request_subhandler = uwsgi_request_subhandler_pump;
|
||||
wi->response_subhandler = uwsgi_response_subhandler_pump;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
@@ -270,7 +308,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
|
||||
// add start_response on WSGI app
|
||||
if (wi->argc == 2) {
|
||||
Py_INCREF((PyObject *)up.wsgi_spitout);
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
|
||||
uwsgi_log("unable to set start_response in args tuple\n");
|
||||
exit(1);
|
||||
@@ -279,8 +318,10 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
#else
|
||||
|
||||
// add start_response on WSGI app
|
||||
Py_INCREF((PyObject *)up.wsgi_spitout);
|
||||
wi->wsgi_args = PyTuple_New(wi->argc);
|
||||
if (wi->argc == 2) {
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
|
||||
uwsgi_log("unable to set start_response in args tuple\n");
|
||||
exit(1);
|
||||
@@ -288,7 +329,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wi->argc == 2) {
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
// prepare sendfile() for WSGI app
|
||||
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
|
||||
@@ -300,6 +341,19 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
#endif
|
||||
}
|
||||
|
||||
// cache most used values
|
||||
|
||||
wi->gateway_version = PyTuple_New(2);
|
||||
PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
|
||||
PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0));
|
||||
Py_INCREF((PyObject *)wi->gateway_version);
|
||||
|
||||
wi->uwsgi_version = PyString_FromString(UWSGI_VERSION);
|
||||
Py_INCREF((PyObject *)wi->uwsgi_version);
|
||||
|
||||
wi->uwsgi_node = PyString_FromString(uwsgi.hostname);
|
||||
Py_INCREF((PyObject *)wi->uwsgi_node);
|
||||
|
||||
if (uwsgi.threads > 1 && id) {
|
||||
// if we have multiple threads we need to initialize a PyThreadState for each one
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
@@ -316,19 +370,22 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
PyThreadState_Swap(up.main_thread);
|
||||
}
|
||||
|
||||
if (wi->argc == 1) {
|
||||
uwsgi_log( "Web3 application %d (SCRIPT_NAME=%.*s) ready on interpreter %p", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter);
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "WSGI application %d (SCRIPT_NAME=%.*s) ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
|
||||
if (!wsgi_req->script_name_len) {
|
||||
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
|
||||
uwsgi_rawlog(" (default app)");
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
|
||||
uwsgi.apps_cnt++;
|
||||
uwsgi_apps_cnt++;
|
||||
|
||||
uwsgi_rawlog("\n");
|
||||
|
||||
@@ -340,9 +397,29 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
continue;
|
||||
}
|
||||
|
||||
wsgi_req->script_name = PyString_AsString(app_mnt);
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
init_uwsgi_app(LOADER_CALLABLE, PyDict_GetItem(applications, app_mnt), wsgi_req, wi->interpreter);
|
||||
wsgi_req->appid = PyString_AsString(app_mnt);
|
||||
wsgi_req->appid_len = strlen(wsgi_req->appid);
|
||||
PyObject *a_callable = PyDict_GetItem(applications, app_mnt);
|
||||
if (PyString_Check(a_callable)) {
|
||||
|
||||
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
|
||||
if (callables_dict) {
|
||||
a_callable = PyDict_GetItem(callables_dict, a_callable);
|
||||
}
|
||||
}
|
||||
if (!a_callable) {
|
||||
uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
|
||||
continue;
|
||||
}
|
||||
init_uwsgi_app(LOADER_CALLABLE, a_callable, wsgi_req, wi->interpreter, app_type);
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to emulate fork() COW
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
|
||||
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +428,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
doh:
|
||||
free(mountpoint);
|
||||
PyErr_Print();
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (interpreter == NULL && id) {
|
||||
Py_EndInterpreter(wi->interpreter);
|
||||
if (uwsgi.threads > 1) {
|
||||
@@ -360,6 +438,7 @@ doh:
|
||||
PyThreadState_Swap(up.main_thread);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -404,7 +483,9 @@ 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;
|
||||
|
||||
@@ -427,8 +508,10 @@ 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");
|
||||
@@ -441,7 +524,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
|
||||
quick_callable[strlen(quick_callable)] = '(';
|
||||
if (tmp_callable) {
|
||||
return python_call(tmp_callable, PyTuple_New(0), 0);
|
||||
return python_call(tmp_callable, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,7 +606,7 @@ PyObject *uwsgi_file_loader(void *arg1) {
|
||||
char *callable = up.callable;
|
||||
if (!callable) callable = "application";
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename("uwsgi_wsgi_file", filename);
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
|
||||
if (!wsgi_file_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
@@ -599,6 +682,8 @@ PyObject *uwsgi_paste_loader(void *arg1) {
|
||||
|
||||
PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
|
||||
char *code = (char *) arg1;
|
||||
|
||||
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
|
||||
@@ -654,6 +739,9 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
}
|
||||
|
||||
return wsgi_eval_callable;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
+309
-79
@@ -3,6 +3,8 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_python up;
|
||||
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
#include <glob.h>
|
||||
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
@@ -12,8 +14,9 @@ struct option uwsgi_python_options[] = {
|
||||
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
|
||||
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
|
||||
{"module", required_argument, 0, 'w'},
|
||||
{"wsgi", required_argument, 0, 'w'},
|
||||
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
|
||||
{"test", required_argument, 0, 'j'},
|
||||
{"test", required_argument, 0, 'J'},
|
||||
{"home", required_argument, 0, 'H'},
|
||||
{"virtualenv", required_argument, 0, 'H'},
|
||||
{"venv", required_argument, 0, 'H'},
|
||||
@@ -26,10 +29,17 @@ struct option uwsgi_python_options[] = {
|
||||
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-python-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
|
||||
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
|
||||
{"optimize", required_argument, 0, 'O'},
|
||||
{"paste", required_argument, 0, LONG_ARGS_PASTE},
|
||||
{"web3", required_argument, 0, LONG_ARGS_WEB3},
|
||||
{"pump", required_argument, 0, LONG_ARGS_PUMP},
|
||||
{"wsgi-lite", required_argument, 0, LONG_ARGS_WSGI_LITE},
|
||||
#ifdef UWSGI_INI
|
||||
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
|
||||
#endif
|
||||
@@ -37,7 +47,12 @@ struct option uwsgi_python_options[] = {
|
||||
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
|
||||
{"pep3333-input", no_argument, &up.pep3333_input, 1},
|
||||
{"reload-os-env", no_argument, &up.reload_os_env, 1},
|
||||
#ifndef UWSGI_PYPY
|
||||
{"no-site", no_argument, &Py_NoSiteFlag, 1},
|
||||
#endif
|
||||
{"pyshell", no_argument, 0, LONG_ARGS_PYSHELL},
|
||||
{"python", required_argument, 0, LONG_ARGS_PYTHON_RUN},
|
||||
{"py", required_argument, 0, LONG_ARGS_PYTHON_RUN},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
@@ -60,6 +75,7 @@ struct uwsgi_help_item uwsgi_python_help[] = {
|
||||
{"file <file>", "use python file instead of python module for configuration"},
|
||||
{"eval <code>", "evaluate code for app configuration"},
|
||||
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
|
||||
{"pyshell", "run a python interactive shell in the uwsgi environment (steals a worker)"},
|
||||
|
||||
|
||||
{ 0, 0},
|
||||
@@ -88,9 +104,14 @@ PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARG
|
||||
|
||||
int uwsgi_python_init() {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
char *pyversion = strchr(Py_GetVersion(), '\n');
|
||||
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
#else
|
||||
uwsgi_log("PyPy version: %s\n", PYPY_VERSION);
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
if (up.home != NULL) {
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wpyhome;
|
||||
@@ -119,9 +140,12 @@ int uwsgi_python_init() {
|
||||
#endif
|
||||
|
||||
|
||||
Py_OptimizeFlag = up.optimize;
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
Py_OptimizeFlag = up.optimize;
|
||||
|
||||
#endif
|
||||
|
||||
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
|
||||
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
|
||||
@@ -144,6 +168,7 @@ 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)
|
||||
@@ -163,23 +188,34 @@ void uwsgi_python_reset_random_seed() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_python_post_fork() {
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.shared->spooler_pid == getpid()) {
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_python_reset_random_seed();
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
// call the post_fork_hook
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *pfh = PyDict_GetItemString(uwsgi_dict, "post_fork_hook");
|
||||
if (pfh) {
|
||||
python_call(pfh, PyTuple_New(0), 0);
|
||||
python_call(pfh, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
@@ -187,6 +223,7 @@ UWSGI_RELEASE_GIL
|
||||
|
||||
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
FILE *pyfile;
|
||||
struct _node *py_file_node = NULL;
|
||||
PyObject *py_compiled_node, *py_file_module;
|
||||
@@ -195,7 +232,7 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
char *real_filename = filename;
|
||||
|
||||
|
||||
if (strncmp(filename, "http://", 7) && strncmp(filename, "sym://", 6)) {
|
||||
if (!uwsgi_check_scheme(filename)) {
|
||||
|
||||
pyfile = fopen(filename, "r");
|
||||
if (!pyfile) {
|
||||
@@ -225,7 +262,8 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
if (!py_file_node) {
|
||||
PyErr_Print();
|
||||
uwsgi_log("failed to parse file %s\n", real_filename);
|
||||
free(real_filename);
|
||||
if (is_a_package)
|
||||
free(real_filename);
|
||||
fclose(pyfile);
|
||||
return NULL;
|
||||
}
|
||||
@@ -271,10 +309,12 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
}
|
||||
|
||||
return py_file_module;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void init_uwsgi_vars() {
|
||||
|
||||
int i;
|
||||
@@ -283,11 +323,6 @@ void init_uwsgi_vars() {
|
||||
PyObject *modules = PyImport_GetModuleDict();
|
||||
PyObject *tmp_module;
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
char venv_version[15];
|
||||
PyObject *site_module;
|
||||
#endif
|
||||
|
||||
/* add cwd to pythonpath */
|
||||
pysys = PyImport_ImportModule("sys");
|
||||
if (!pysys) {
|
||||
@@ -310,39 +345,6 @@ void init_uwsgi_vars() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
// simulate a pythonhome directive
|
||||
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
||||
|
||||
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
||||
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
|
||||
|
||||
venv_version[14] = 0;
|
||||
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check here
|
||||
PyString_Concat(&venv_path, PyString_FromString(venv_version));
|
||||
|
||||
if (PyList_Insert(pypath, 0, venv_path)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
site_module = PyImport_ImportModule("site");
|
||||
if (site_module) {
|
||||
PyImport_ReloadModule(site_module);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (PyList_Insert(pypath, 0, UWSGI_PYFROMSTRING(".")) != 0) {
|
||||
PyErr_Print();
|
||||
}
|
||||
@@ -436,12 +438,17 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Py_INCREF((PyObject *) &uwsgi_InputType);
|
||||
|
||||
up.embedded_dict = PyModule_GetDict(new_uwsgi_module);
|
||||
if (!up.embedded_dict) {
|
||||
uwsgi_log("could not get uwsgi module __dict__\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// just for safety
|
||||
Py_INCREF(up.embedded_dict);
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "version", PyString_FromString(UWSGI_VERSION))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
@@ -523,7 +530,12 @@ void init_uwsgi_embedded_module() {
|
||||
if (PyDict_Contains(py_opt_dict, PyString_FromString(uwsgi.exported_opts[i]->key))) {
|
||||
PyObject *py_opt_item = PyDict_GetItemString(py_opt_dict, uwsgi.exported_opts[i]->key);
|
||||
if (PyList_Check(py_opt_item)) {
|
||||
PyList_Append(py_opt_item, PyString_FromString(uwsgi.exported_opts[i]->value));
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
PyList_Append(py_opt_item, Py_True);
|
||||
}
|
||||
else {
|
||||
PyList_Append(py_opt_item, PyString_FromString(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyObject *py_opt_list = PyList_New(0);
|
||||
@@ -553,6 +565,23 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PyObject *py_magic_table = PyDict_New();
|
||||
uint8_t mtk;
|
||||
for (i = 0; i <= 0xff; i++) {
|
||||
// a bit of magic :P
|
||||
mtk = i;
|
||||
if (uwsgi.magic_table[i]) {
|
||||
if (uwsgi.magic_table[i][0] != 0) {
|
||||
PyDict_SetItem(py_magic_table, PyString_FromStringAndSize((char *) &mtk, 1), PyString_FromString(uwsgi.magic_table[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "magic_table", py_magic_table)) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UNBIT
|
||||
if (PyDict_SetItemString(up.embedded_dict, "unbit", Py_True)) {
|
||||
#else
|
||||
@@ -631,9 +660,19 @@ void init_uwsgi_embedded_module() {
|
||||
init_uwsgi_module_sharedarea(new_uwsgi_module);
|
||||
}
|
||||
|
||||
init_uwsgi_module_cache(new_uwsgi_module);
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
init_uwsgi_module_cache(new_uwsgi_module);
|
||||
}
|
||||
|
||||
init_uwsgi_module_queue(new_uwsgi_module);
|
||||
if (uwsgi.queue_size > 0) {
|
||||
init_uwsgi_module_queue(new_uwsgi_module);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
if (uwsgi.snmp) {
|
||||
init_uwsgi_module_snmp(new_uwsgi_module);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (up.extension) {
|
||||
up.extension();
|
||||
@@ -697,9 +736,16 @@ int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_PYSHELL:
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_SPOOLER_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.spooler_import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_POST_PYMODULE_ALIAS:
|
||||
uwsgi_string_new_list(&up.post_pymodule_alias, optarg);
|
||||
return 1;
|
||||
@@ -716,7 +762,7 @@ int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
case LONG_ARGS_PYARGV:
|
||||
up.argv = optarg;
|
||||
return 1;
|
||||
case 'j':
|
||||
case 'J':
|
||||
up.test_module = optarg;
|
||||
return 1;
|
||||
case 'H':
|
||||
@@ -732,15 +778,24 @@ int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
case LONG_ARGS_INI_PASTE:
|
||||
uwsgi.ini = optarg;
|
||||
if (uwsgi.ini[0] != '/') {
|
||||
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", uwsgi.ini);
|
||||
uwsgi_string_new_list(&uwsgi.ini,optarg);
|
||||
if (optarg[0] != '/') {
|
||||
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", optarg);
|
||||
}
|
||||
else {
|
||||
up.paste = uwsgi_concat2("config:", uwsgi.ini);
|
||||
up.paste = uwsgi_concat2("config:", optarg);
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
case LONG_ARGS_WEB3:
|
||||
up.web3 = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PUMP:
|
||||
up.pump = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_WSGI_LITE:
|
||||
up.wsgi_lite = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PASTE:
|
||||
up.paste = optarg;
|
||||
return 1;
|
||||
@@ -752,14 +807,31 @@ int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_python_mount_app(char *mountpoint, char *app) {
|
||||
int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
uwsgi.wsgi_req->script_name = mountpoint;
|
||||
uwsgi.wsgi_req->script_name_len = strlen(mountpoint);
|
||||
int id;
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
if (uwsgi.single_interpreter) {
|
||||
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread);
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
return init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL);
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
int i;
|
||||
if (regexp && id != -1) {
|
||||
struct uwsgi_app *ua = &uwsgi_apps[id];
|
||||
uwsgi_regexp_build(mountpoint, &ua->pattern, &ua->pattern_extra);
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
uwsgi.workers[i].apps[id].pattern = ua->pattern;
|
||||
uwsgi.workers[i].apps[id].pattern_extra = ua->pattern_extra;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return id;
|
||||
|
||||
}
|
||||
|
||||
@@ -775,11 +847,17 @@ char *uwsgi_pythonize(char *orig) {
|
||||
else if (!strncmp(name, "http://", 7)) {
|
||||
name+=7;
|
||||
}
|
||||
else if (!strncmp(name, "data://", 7)) {
|
||||
name+=7;
|
||||
}
|
||||
|
||||
len = strlen(name);
|
||||
for(i=0;i<len;i++) {
|
||||
if (name[i] == '/') {
|
||||
name[i] = '.';
|
||||
if (name[i] == '.') {
|
||||
name[i] = '_';
|
||||
}
|
||||
else if (name[i] == '/') {
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,22 +870,52 @@ char *uwsgi_pythonize(char *orig) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_spooler_init(void) {
|
||||
|
||||
struct uwsgi_string_list *upli = up.spooler_import_list;
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
while(upli) {
|
||||
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
|
||||
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
|
||||
}
|
||||
else {
|
||||
if (PyImport_ImportModule(upli->value) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
upli = upli->next;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_init_apps() {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
init_pyargv();
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
init_uwsgi_embedded_module();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef PYTHREE
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
uwsgi_init_symbol_import();
|
||||
#endif
|
||||
#endif
|
||||
@@ -885,23 +993,38 @@ void uwsgi_python_init_apps() {
|
||||
|
||||
|
||||
if (up.wsgi_config != NULL) {
|
||||
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread);
|
||||
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
|
||||
if (up.file_config != NULL) {
|
||||
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread);
|
||||
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
if (up.paste != NULL) {
|
||||
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread);
|
||||
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
if (up.eval != NULL) {
|
||||
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread);
|
||||
init_uwsgi_app(LOADER_EVAL, up.eval, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
if (up.web3 != NULL) {
|
||||
init_uwsgi_app(LOADER_UWSGI, up.web3, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WEB3);
|
||||
}
|
||||
if (up.pump != NULL) {
|
||||
init_uwsgi_app(LOADER_UWSGI, up.pump, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_PUMP);
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = (int) strlen(http_sc->message);
|
||||
}
|
||||
}
|
||||
if (up.wsgi_lite != NULL) {
|
||||
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 (!strcmp(uwsgi.profiler, "pycall")) {
|
||||
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -952,7 +1075,9 @@ void uwsgi_python_enable_threads() {
|
||||
up.swap_ts = threaded_swap_ts;
|
||||
up.reset_ts = threaded_reset_ts;
|
||||
}
|
||||
|
||||
uwsgi_log("threads support enabled\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -963,6 +1088,9 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
pts = PyThreadState_New(up.main_thread->interp);
|
||||
pthread_setspecific(up.upt_save_key, (void *) pts);
|
||||
pthread_setspecific(up.upt_gil_key, (void *) pts);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("pts %d = %p\n", core_id, pts);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -975,16 +1103,16 @@ int uwsgi_python_xml(char *node, char *content) {
|
||||
}
|
||||
|
||||
if (!strcmp("script", node)) {
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("file", node)) {
|
||||
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("eval", node)) {
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("wsgi", node)) {
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("module", node)) {
|
||||
uwsgi.wsgi_req->module = content;
|
||||
@@ -995,10 +1123,10 @@ int uwsgi_python_xml(char *node, char *content) {
|
||||
uwsgi.wsgi_req->callable++;
|
||||
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
|
||||
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1010,12 +1138,13 @@ int uwsgi_python_xml(char *node, char *content) {
|
||||
else if (!strcmp("callable", node)) {
|
||||
uwsgi.wsgi_req->callable = content;
|
||||
uwsgi.wsgi_req->callable_len = strlen(content);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
@@ -1029,6 +1158,57 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
|
||||
up.current_main_frame = tstate->frame;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
|
||||
|
||||
PyObject *cs_module = NULL;
|
||||
PyObject *cs_dict = NULL;
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
cs_module = PyImport_ImportModule(id);
|
||||
if (!cs_module) {
|
||||
PyErr_Clear();
|
||||
cs_module = uwsgi_pyimport_by_filename(id, code);
|
||||
}
|
||||
|
||||
if (!cs_module) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cs_dict = PyModule_GetDict(cs_module);
|
||||
if (!cs_dict) {
|
||||
PyErr_Print();
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *func = PyDict_GetItemString(cs_dict, function);
|
||||
if (!func) {
|
||||
uwsgi_log("function %s not available in %s\n", function, code);
|
||||
PyErr_Print();
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *args = PyTuple_New(1);
|
||||
|
||||
PyTuple_SetItem(args, 0, PyString_FromStringAndSize(key, keylen));
|
||||
|
||||
PyObject *ret = python_call(func, args, 0, NULL);
|
||||
Py_DECREF(args);
|
||||
if (ret && PyString_Check(ret)) {
|
||||
char *val = PyString_AsString(ret);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return val;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
|
||||
@@ -1046,9 +1226,10 @@ int uwsgi_python_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
PyTuple_SetItem(args, 0, PyInt_FromLong(sig));
|
||||
|
||||
ret = python_call(handler, args, 0);
|
||||
|
||||
ret = python_call(handler, args, 0, NULL);
|
||||
Py_DECREF(args);
|
||||
if (ret) {
|
||||
Py_DECREF(ret);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 0;
|
||||
}
|
||||
@@ -1073,7 +1254,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
|
||||
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
|
||||
}
|
||||
|
||||
ret = python_call((PyObject *) func, pyargs, 0);
|
||||
ret = python_call((PyObject *) func, pyargs, 0, NULL);
|
||||
|
||||
if (ret) {
|
||||
if (PyString_Check(ret)) {
|
||||
@@ -1143,8 +1324,9 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
|
||||
PyDict_SetItemString(spool_dict, "body", PyString_FromStringAndSize(body, body_len));
|
||||
}
|
||||
PyTuple_SetItem(pyargs, 0, spool_dict);
|
||||
|
||||
ret = python_call(spool_func, pyargs, 0);
|
||||
|
||||
ret = python_call(spool_func, pyargs, 0, NULL);
|
||||
|
||||
if (ret) {
|
||||
if (!PyInt_Check(ret)) {
|
||||
// error, retry
|
||||
@@ -1166,6 +1348,7 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
@@ -1180,10 +1363,48 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_python_fixup() {
|
||||
// set hacky modifier 30
|
||||
uwsgi.p[30] = uwsgi.p[0];
|
||||
uwsgi.p[30] = uwsgi_malloc( sizeof(struct uwsgi_plugin) );
|
||||
memcpy(uwsgi.p[30], uwsgi.p[0], sizeof(struct uwsgi_plugin) );
|
||||
uwsgi.p[30]->init_thread = NULL;
|
||||
}
|
||||
|
||||
void uwsgi_python_hijack(void) {
|
||||
// the pyshell will be execute only in the first worker
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
if (up.pyshell && uwsgi.mywid == 1) {
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
PyImport_ImportModule("readline");
|
||||
PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_python_mule(char *opt) {
|
||||
|
||||
if (uwsgi_endswith(opt, ".py")) {
|
||||
UWSGI_GET_GIL;
|
||||
uwsgi_pyimport_by_filename("__main__", opt);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_plugin python_plugin = {
|
||||
@@ -1195,7 +1416,7 @@ struct uwsgi_plugin python_plugin = {
|
||||
.post_fork = uwsgi_python_post_fork,
|
||||
.options = uwsgi_python_options,
|
||||
.manage_opt = uwsgi_python_manage_options,
|
||||
.short_options = "w:O:H:j:",
|
||||
.short_options = "w:O:H:J:",
|
||||
.request = uwsgi_request_wsgi,
|
||||
.after_request = uwsgi_after_request_wsgi,
|
||||
.init_apps = uwsgi_python_init_apps,
|
||||
@@ -1211,14 +1432,23 @@ struct uwsgi_plugin python_plugin = {
|
||||
|
||||
.magic = uwsgi_python_magic,
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
.suspend = uwsgi_python_suspend,
|
||||
.resume = uwsgi_python_resume,
|
||||
#endif
|
||||
|
||||
.hijack_worker = uwsgi_python_hijack,
|
||||
.spooler_init = uwsgi_python_spooler_init,
|
||||
|
||||
.signal_handler = uwsgi_python_signal_handler,
|
||||
.rpc = uwsgi_python_rpc,
|
||||
|
||||
.mule = uwsgi_python_mule,
|
||||
|
||||
.spooler = uwsgi_python_spooler,
|
||||
|
||||
.code_string = uwsgi_python_code_string,
|
||||
|
||||
.help = uwsgi_python_help,
|
||||
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ 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) {
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pyret;
|
||||
|
||||
@@ -22,7 +22,13 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
// this can be in a spooler or in the master
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
if (wsgi_req) {
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
}
|
||||
}
|
||||
if (!catch) {
|
||||
PyErr_Print();
|
||||
}
|
||||
@@ -39,7 +45,7 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
|
||||
|
||||
int uwsgi_python_call(struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
|
||||
|
||||
wsgi_req->async_result = python_call(callable, args, 0);
|
||||
wsgi_req->async_result = python_call(callable, args, 0, wsgi_req);
|
||||
|
||||
if (wsgi_req->async_result) {
|
||||
while ( manage_python_response(wsgi_req) != UWSGI_OK) {
|
||||
@@ -66,8 +72,9 @@ void init_pyargv() {
|
||||
up.py_argv[0] = "uwsgi";
|
||||
#endif
|
||||
|
||||
if (up.argv != NULL && !up.argc) {
|
||||
up.argc++;
|
||||
up.argc = 1;
|
||||
|
||||
if (up.argv != NULL) {
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
if (!wcargv) {
|
||||
@@ -98,7 +105,20 @@ void init_pyargv() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
PySys_SetArgv(up.argc, up.py_argv);
|
||||
#endif
|
||||
|
||||
PyObject *sys_dict = get_uwsgi_pydict("sys");
|
||||
if (!sys_dict) {
|
||||
uwsgi_log("unable to load python sys module !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
PyDict_SetItemString(sys_dict, "executable", PyUnicode_FromString(uwsgi.binary_path));
|
||||
#else
|
||||
PyDict_SetItemString(sys_dict, "executable", PyString_FromString(uwsgi.binary_path));
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "uwsgi_python.h"
|
||||
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
@@ -8,6 +10,14 @@ struct _symimporter {
|
||||
PyObject_HEAD;
|
||||
} uwsgi_symbol_importer_object;
|
||||
|
||||
struct _symzipimporter {
|
||||
PyObject_HEAD;
|
||||
char *prefix;
|
||||
PyObject *zip;
|
||||
PyObject *items;
|
||||
} uwsgi_symbol_zip_importer_object;
|
||||
|
||||
|
||||
static char *symbolize(char *name) {
|
||||
|
||||
char *base = uwsgi_concat2(name, "");
|
||||
@@ -22,6 +32,84 @@ static char *symbolize(char *name) {
|
||||
return base;
|
||||
}
|
||||
|
||||
static char *name_to_py(char *prefix, char *name) {
|
||||
|
||||
char *base;
|
||||
char *ptr;
|
||||
|
||||
if (prefix) {
|
||||
if (prefix[strlen(prefix)-1] == '/') {
|
||||
base = uwsgi_concat3(prefix, name, ".py");
|
||||
ptr = base + strlen(prefix);
|
||||
}
|
||||
else {
|
||||
base = uwsgi_concat4(prefix, "/", name, ".py");
|
||||
ptr = base + strlen(prefix) + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
base = uwsgi_concat2(name, ".py");
|
||||
ptr = base;
|
||||
}
|
||||
while(*ptr != 0) {
|
||||
if (*ptr == '.') {
|
||||
*ptr = '/';
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// fix .py
|
||||
ptr-=3;
|
||||
*ptr = '.';
|
||||
return base;
|
||||
}
|
||||
|
||||
static char *name_to_init_py(char *prefix, char *name) {
|
||||
|
||||
char *base;
|
||||
char *ptr;
|
||||
|
||||
if (prefix) {
|
||||
if (prefix[strlen(prefix)-1] == '/') {
|
||||
base = uwsgi_concat3(prefix, name, "/__init__.py");
|
||||
ptr = base + strlen(prefix);
|
||||
}
|
||||
else {
|
||||
base = uwsgi_concat4(prefix, "/", name, "/__init__.py");
|
||||
ptr = base + strlen(prefix) + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
base = uwsgi_concat2(name, "/__init__.py");
|
||||
ptr = base;
|
||||
}
|
||||
|
||||
while(*ptr != 0) {
|
||||
if (*ptr == '.') {
|
||||
*ptr = '/';
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// fix .py
|
||||
ptr-=3;
|
||||
*ptr = '.';
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static char *name_to_symbol(char *name, char *what) {
|
||||
|
||||
char *symbol = uwsgi_concat4("_binary_", name, "_", what);
|
||||
char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol);
|
||||
free(symbol);
|
||||
return sym_ptr_start;
|
||||
}
|
||||
|
||||
|
||||
static char *name_to_symbol_module(char *name, char *what) {
|
||||
|
||||
char *symbol = uwsgi_concat4("_binary_", name, "_py_", what);
|
||||
@@ -38,6 +126,127 @@ static char *name_to_symbol_pkg(char *name, char *what) {
|
||||
return sym_ptr_start;
|
||||
}
|
||||
|
||||
int py_list_has_string(PyObject *obj, char *name) {
|
||||
|
||||
Py_ssize_t i, len = PyList_Size(obj);
|
||||
int found = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
PyObject *current = PyList_GetItem(obj, i);
|
||||
char *filename = PyString_AsString(current);
|
||||
if (!strcmp(filename, name)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static PyObject* symzipimporter_find_module(PyObject *self, PyObject *args) {
|
||||
|
||||
char *fullname;
|
||||
PyObject *path = NULL;
|
||||
struct _symzipimporter *this = (struct _symzipimporter *) self;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|O:find_module", &fullname, &path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *filename = name_to_py(this->prefix, fullname);
|
||||
|
||||
if (py_list_has_string(this->items, filename)) {
|
||||
free(filename);
|
||||
return self;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
free(filename);
|
||||
|
||||
filename = name_to_init_py(this->prefix, fullname);
|
||||
|
||||
if (py_list_has_string(this->items, filename)) {
|
||||
free(filename);
|
||||
return self;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
free(filename);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
|
||||
|
||||
char *fullname;
|
||||
char *modname;
|
||||
struct _symzipimporter *this = (struct _symzipimporter *) self;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:load_module", &fullname)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *filename = name_to_py(this->prefix, fullname);
|
||||
|
||||
if (py_list_has_string(this->items, filename)) {
|
||||
PyObject *mod = PyImport_AddModule(fullname);
|
||||
if (!mod) goto clear;
|
||||
PyObject *dict = PyModule_GetDict(mod);
|
||||
if (!dict) goto clear;
|
||||
|
||||
PyDict_SetItemString(dict, "__loader__", self);
|
||||
|
||||
modname = uwsgi_concat2("symzip://", fullname);
|
||||
|
||||
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
|
||||
free(filename);
|
||||
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
Py_DECREF(source);
|
||||
free(modname);
|
||||
return mod;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
free(filename);
|
||||
|
||||
filename = name_to_init_py(this->prefix, fullname);
|
||||
|
||||
if (py_list_has_string(this->items, filename)) {
|
||||
PyObject *mod = PyImport_AddModule(fullname);
|
||||
if (!mod) goto clear;
|
||||
PyObject *dict = PyModule_GetDict(mod);
|
||||
if (!dict) goto clear;
|
||||
|
||||
modname = uwsgi_concat2("symzip://", fullname);
|
||||
|
||||
PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname));
|
||||
|
||||
PyDict_SetItemString(dict, "__path__", pkgpath);
|
||||
PyDict_SetItemString(dict, "__loader__", self);
|
||||
|
||||
|
||||
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
|
||||
free(filename);
|
||||
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
Py_DECREF(source);
|
||||
free(modname);
|
||||
return mod;
|
||||
}
|
||||
|
||||
clear:
|
||||
PyErr_Clear();
|
||||
free(filename);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* symimporter_find_module(PyObject *self, PyObject *args) {
|
||||
|
||||
char *fullname;
|
||||
@@ -142,12 +351,19 @@ clear:
|
||||
}
|
||||
|
||||
static PyMethodDef symimporter_methods[] = {
|
||||
{"find_module", symimporter_find_module, METH_VARARGS},
|
||||
{"load_module", symimporter_load_module, METH_VARARGS},
|
||||
{"find_module", symimporter_find_module, METH_VARARGS},
|
||||
{"load_module", symimporter_load_module, METH_VARARGS},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static PyMethodDef symzipimporter_methods[] = {
|
||||
{"find_module", symzipimporter_find_module, METH_VARARGS},
|
||||
{"load_module", symzipimporter_load_module, METH_VARARGS},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static void uwsgi_symimporter_free(struct _symimporter *self) {
|
||||
PyObject_Del(self);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
|
||||
@@ -190,9 +406,302 @@ static PyTypeObject SymImporter_Type = {
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
static int
|
||||
zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
||||
|
||||
char *name;
|
||||
char *prefix = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return -1;
|
||||
|
||||
// avoid GC !!!
|
||||
name = uwsgi_concat2(name, "");
|
||||
|
||||
if (uwsgi_check_scheme(name)) {
|
||||
prefix = uwsgi_get_last_char(name, '/');
|
||||
prefix = uwsgi_get_last_char(prefix, ':');
|
||||
}
|
||||
else {
|
||||
prefix = uwsgi_get_last_char(name, ':');
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
prefix[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
char *body = uwsgi_open_and_read(name, &len, 0, NULL);
|
||||
if (!body) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *stringio = PyImport_ImportModule("StringIO");
|
||||
if (!stringio) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *stringio_dict = PyModule_GetDict(stringio);
|
||||
if (!stringio_dict) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
|
||||
if (!stringio_stringio) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *stringio_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(body, len));
|
||||
|
||||
|
||||
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
|
||||
if (!source_code) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *zipfile = PyImport_ImportModule("zipfile");
|
||||
|
||||
if (!zipfile) {
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
|
||||
if (!zipfile_dict) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
|
||||
if (!zipfile_zipfile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PyObject *zipfile_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(zipfile_args, 0, source_code);
|
||||
|
||||
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
|
||||
if (!self->zip) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(self->zip);
|
||||
|
||||
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
|
||||
if (!self->items) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(self->items);
|
||||
|
||||
self->prefix = NULL;
|
||||
if (prefix) {
|
||||
self->prefix = prefix+1;
|
||||
prefix[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
||||
|
||||
char *name;
|
||||
char *prefix = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return -1;
|
||||
|
||||
// avoid GC !!!
|
||||
name = uwsgi_concat2(name, "");
|
||||
|
||||
prefix = strchr(name, ':');
|
||||
if (prefix) {
|
||||
prefix[0] = 0;
|
||||
}
|
||||
|
||||
char *code_start = name_to_symbol(name, "start");
|
||||
if (!code_start) {
|
||||
PyErr_Format(PyExc_ValueError, "unable to find symbol");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *code_end = name_to_symbol(name, "end");
|
||||
if (!code_end) {
|
||||
PyErr_Format(PyExc_ValueError, "unable to find symbol");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *stringio = PyImport_ImportModule("StringIO");
|
||||
if (!stringio) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *stringio_dict = PyModule_GetDict(stringio);
|
||||
if (!stringio_dict) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO");
|
||||
if (!stringio_stringio) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *stringio_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(code_start, code_end-code_start));
|
||||
|
||||
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
|
||||
if (!source_code) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *zipfile = PyImport_ImportModule("zipfile");
|
||||
if (!zipfile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
|
||||
if (!zipfile_dict) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile");
|
||||
if (!zipfile_zipfile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *zipfile_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(zipfile_args, 0, source_code);
|
||||
|
||||
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
|
||||
if (!self->zip) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(self->zip);
|
||||
|
||||
self->items = PyObject_CallMethod(self->zip, "namelist", NULL);
|
||||
if (!self->items) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(self->items);
|
||||
|
||||
self->prefix = NULL;
|
||||
if (prefix) {
|
||||
self->prefix = prefix+1;
|
||||
prefix[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyTypeObject SymZipImporter_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"uwsgi.SymbolsZipImporter",
|
||||
sizeof(struct _symzipimporter),
|
||||
0, /* tp_itemsize */
|
||||
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT,
|
||||
"uwsgi symbols zip importer", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
symzipimporter_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc) symzipimporter_init, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
static PyTypeObject ZipImporter_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"uwsgi.ZipImporter",
|
||||
sizeof(struct _symzipimporter),
|
||||
0, /* tp_itemsize */
|
||||
(destructor) uwsgi_symimporter_free, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT,
|
||||
"uwsgi zip importer", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
symzipimporter_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc) zipimporter_init, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
|
||||
|
||||
int uwsgi_init_symbol_import() {
|
||||
|
||||
|
||||
@@ -202,6 +711,18 @@ int uwsgi_init_symbol_import() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PyType_Ready(&ZipImporter_Type) < 0) {
|
||||
PyErr_Print();
|
||||
uwsgi_log("unable to initialize zip importer module\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PyType_Ready(&SymZipImporter_Type) < 0) {
|
||||
PyErr_Print();
|
||||
uwsgi_log("unable to initialize symbols zip importer module\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PyObject *uwsgi_em = PyImport_ImportModule("uwsgi");
|
||||
if (!uwsgi_em) {
|
||||
PyErr_Print();
|
||||
@@ -209,6 +730,7 @@ int uwsgi_init_symbol_import() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Py_INCREF((PyObject *)&SymImporter_Type);
|
||||
if (PyModule_AddObject(uwsgi_em, "SymbolsImporter",
|
||||
(PyObject *)&SymImporter_Type) < 0) {
|
||||
PyErr_Print();
|
||||
@@ -216,7 +738,25 @@ int uwsgi_init_symbol_import() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Py_INCREF((PyObject *)&ZipImporter_Type);
|
||||
if (PyModule_AddObject(uwsgi_em, "ZipImporter",
|
||||
(PyObject *)&ZipImporter_Type) < 0) {
|
||||
PyErr_Print();
|
||||
uwsgi_log("unable to initialize zip importer object\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Py_INCREF((PyObject *)&SymZipImporter_Type);
|
||||
if (PyModule_AddObject(uwsgi_em, "SymbolsZipImporter",
|
||||
(PyObject *)&SymZipImporter_Type) < 0) {
|
||||
PyErr_Print();
|
||||
uwsgi_log("unable to initialize symbols zip importer object\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+758
-97
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,22 @@
|
||||
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
|
||||
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
|
||||
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
|
||||
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
|
||||
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
|
||||
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
|
||||
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
|
||||
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
|
||||
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
|
||||
|
||||
#define PYTHON_APP_TYPE_WSGI 0
|
||||
#define PYTHON_APP_TYPE_WEB3 1
|
||||
#define PYTHON_APP_TYPE_WSGI2 2
|
||||
#define PYTHON_APP_TYPE_PUMP 3
|
||||
#define PYTHON_APP_TYPE_WSGI_LITE 4
|
||||
|
||||
#if PY_MINOR_VERSION == 4 && PY_MAJOR_VERSION == 2
|
||||
#define Py_ssize_t ssize_t
|
||||
#define UWSGI_PYTHON_OLD
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7
|
||||
@@ -83,6 +96,18 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
|
||||
#define LOADER_MAX 8
|
||||
|
||||
#define UWSGI_PY_READLINE_BUFSIZE 1024
|
||||
|
||||
typedef struct uwsgi_Input {
|
||||
PyObject_HEAD
|
||||
char readline[UWSGI_PY_READLINE_BUFSIZE];
|
||||
size_t readline_size;
|
||||
size_t readline_max_size;
|
||||
size_t readline_pos;
|
||||
size_t pos;
|
||||
struct wsgi_request *wsgi_req;
|
||||
} uwsgi_Input;
|
||||
|
||||
struct uwsgi_python {
|
||||
|
||||
char *home;
|
||||
@@ -104,8 +129,11 @@ struct uwsgi_python {
|
||||
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
|
||||
struct uwsgi_string_list *python_path;
|
||||
struct uwsgi_string_list *import_list;
|
||||
struct uwsgi_string_list *spooler_import_list;
|
||||
struct uwsgi_string_list *post_pymodule_alias;
|
||||
|
||||
PyObject *loader_dict;
|
||||
@@ -116,6 +144,9 @@ struct uwsgi_python {
|
||||
char *paste;
|
||||
char *eval;
|
||||
|
||||
char *web3;
|
||||
char *pump;
|
||||
char *wsgi_lite;
|
||||
|
||||
char *callable;
|
||||
|
||||
@@ -152,6 +183,7 @@ struct uwsgi_python {
|
||||
void (*extension)(void);
|
||||
|
||||
int reload_os_env;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -165,7 +197,7 @@ void uwsgi_paste_config(char *);
|
||||
void uwsgi_file_config(char *);
|
||||
void uwsgi_eval_config(char *);
|
||||
|
||||
int init_uwsgi_app(int, void *, struct wsgi_request *wsgi_req, PyThreadState *);
|
||||
int init_uwsgi_app(int, void *, struct wsgi_request *, PyThreadState *, int);
|
||||
|
||||
|
||||
PyObject *py_eventfd_read(PyObject *, PyObject *);
|
||||
@@ -174,7 +206,7 @@ PyObject *py_eventfd_write(PyObject *, PyObject *);
|
||||
|
||||
int manage_python_response(struct wsgi_request *);
|
||||
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
|
||||
PyObject *python_call(PyObject *, PyObject *, int);
|
||||
PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
|
||||
@@ -187,10 +219,11 @@ PyObject *py_uwsgi_spit(PyObject *, PyObject *);
|
||||
|
||||
void init_pyargv(void);
|
||||
|
||||
#ifdef UWSGI_WEB3
|
||||
void *uwsgi_request_subhandler_web3(struct wsgi_request *, struct uwsgi_app *);
|
||||
int uwsgi_response_subhandler_web3(struct wsgi_request *);
|
||||
#endif
|
||||
|
||||
void *uwsgi_request_subhandler_pump(struct wsgi_request *, struct uwsgi_app *);
|
||||
int uwsgi_response_subhandler_pump(struct wsgi_request *);
|
||||
|
||||
PyObject *uwsgi_uwsgi_loader(void *);
|
||||
PyObject *uwsgi_dyn_loader(void *);
|
||||
@@ -220,6 +253,7 @@ void init_uwsgi_module_spooler(PyObject *);
|
||||
void init_uwsgi_module_sharedarea(PyObject *);
|
||||
void init_uwsgi_module_cache(PyObject *);
|
||||
void init_uwsgi_module_queue(PyObject *);
|
||||
void init_uwsgi_module_snmp(PyObject *);
|
||||
|
||||
PyObject *uwsgi_pyimport_by_filename(char *, char *);
|
||||
|
||||
@@ -232,6 +266,14 @@ int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
|
||||
void uwsgi_python_reset_random_seed(void);
|
||||
|
||||
char *uwsgi_pythonize(char *);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
#endif
|
||||
|
||||
#define uwsgi_pyexit {PyErr_Print();exit(1);}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef PYTHREE
|
||||
int uwsgi_init_symbol_import(void);
|
||||
|
||||
@@ -3,29 +3,37 @@ import os,sys
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='python'
|
||||
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter']
|
||||
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter']
|
||||
#OBJ_LIST = ['/usr/lib/libpython2.6.a']
|
||||
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
|
||||
|
||||
if 'pypy_version_info' in sys.__dict__:
|
||||
CFLAGS.append('-DUWSGI_PYPY')
|
||||
|
||||
LDFLAGS = []
|
||||
|
||||
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
|
||||
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
|
||||
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
|
||||
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||
LIBS.append('-L' + sysconfig.get_config_var('LIBPL'))
|
||||
else:
|
||||
try:
|
||||
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
|
||||
os.environ['LD_RUN_PATH'] = "%s" % (sysconfig.get_config_var('LIBDIR'))
|
||||
except:
|
||||
LDFLAGS.append("-L%s/lib" % sysconfig.PREFIX)
|
||||
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
|
||||
|
||||
|
||||
version = sysconfig.get_config_var('VERSION')
|
||||
try:
|
||||
version = version + sys.abiflags
|
||||
except:
|
||||
pass
|
||||
LIBS.append('-lpython' + version)
|
||||
else:
|
||||
try:
|
||||
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
|
||||
os.environ['LD_RUN_PATH'] = "%s" % (sysconfig.get_config_var('LIBDIR'))
|
||||
except:
|
||||
LDFLAGS.append("-L%s/lib" % sysconfig.PREFIX)
|
||||
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
|
||||
|
||||
|
||||
version = sysconfig.get_config_var('VERSION')
|
||||
try:
|
||||
version = version + sys.abiflags
|
||||
except:
|
||||
pass
|
||||
LIBS.append('-lpython' + version)
|
||||
LIBS = []
|
||||
|
||||
#if str(PYLIB_PATH) != '':
|
||||
# libs.insert(0,'-L' + PYLIB_PATH)
|
||||
|
||||
@@ -1,20 +1,70 @@
|
||||
#include "uwsgi.h"
|
||||
#include "uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
PyObject *zero, *wsgi_socket;
|
||||
PyObject *zero;
|
||||
|
||||
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_socket);
|
||||
Py_DECREF(wsgi_socket);
|
||||
int i;
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
char *path_info;
|
||||
|
||||
zero = PyTuple_New(2);
|
||||
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
|
||||
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", zero);
|
||||
Py_DECREF(zero);
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
#ifdef PYTHREE
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
|
||||
#else
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
#endif
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
wsgi_req->uh.modifier1 = 0;
|
||||
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
|
||||
if (pydictkey) {
|
||||
if (PyString_Check(pydictkey)) {
|
||||
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
|
||||
if (pydictvalue) {
|
||||
if (PyString_Check(pydictvalue)) {
|
||||
path_info = PyString_AsString(pydictvalue);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "web3_input", "rb", 0, NULL, NULL, NULL, 0);
|
||||
#else
|
||||
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "web3_input", "r", NULL);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// create wsgi.input custom object
|
||||
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
|
||||
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
|
||||
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_req->async_input);
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.version", wi->gateway_version);
|
||||
|
||||
zero = PyFile_FromFile(stderr, "web3_input", "w", NULL);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.errors", zero);
|
||||
@@ -31,35 +81,53 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
}
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
else if (wsgi_req->https_len > 0) {
|
||||
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
|
||||
zero = PyString_FromString("https");
|
||||
zero = UWSGI_PYFROMSTRING("https");
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
zero = UWSGI_PYFROMSTRING("http");
|
||||
}
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
zero = UWSGI_PYFROMSTRING("http");
|
||||
}
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "web3.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
|
||||
wsgi_req->async_app = wi->wsgi_callable;
|
||||
wsgi_req->async_app = wi->callable;
|
||||
|
||||
PyDict_SetItemString(uwsgi.embedded_dict, "env", wsgi_req->async_environ);
|
||||
// export .env only in non-threaded mode
|
||||
if (uwsgi.threads < 2) {
|
||||
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
|
||||
}
|
||||
|
||||
// TODO: fix this
|
||||
//PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", uwsgi_version);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
|
||||
|
||||
if (uwsgi.cores > 1) {
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
|
||||
}
|
||||
|
||||
// cache this ?
|
||||
if (uwsgi.cluster_fd >= 0) {
|
||||
zero = PyString_FromString(uwsgi.cluster);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
|
||||
Py_DECREF(zero);
|
||||
zero = PyString_FromString(uwsgi.hostname);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
|
||||
|
||||
|
||||
// call
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,16 +136,7 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
|
||||
// return or yield ? (PyString on python2 PyBytes on python3)
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
@@ -86,19 +145,51 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("invalid Web3 response.\n");
|
||||
goto clear;
|
||||
}
|
||||
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
|
||||
|
||||
|
||||
|
||||
wsgi_req->async_placeholder = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
|
||||
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
PyObject *spit_args = PyTuple_New(2);
|
||||
|
||||
PyObject *status = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 1);
|
||||
Py_INCREF(status);
|
||||
PyTuple_SetItem(spit_args, 0, status);
|
||||
|
||||
PyObject *headers = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
|
||||
Py_INCREF(headers);
|
||||
PyTuple_SetItem(spit_args, 1, headers);
|
||||
|
||||
if (py_uwsgi_spit(NULL, spit_args) == Py_None) {
|
||||
Py_DECREF(spit_args);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0);
|
||||
|
||||
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_result );
|
||||
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;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
|
||||
|
||||
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
|
||||
|
||||
Py_DECREF(tmp);
|
||||
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
goto clear2;
|
||||
goto clear;
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
@@ -119,9 +210,8 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
@@ -131,34 +221,22 @@ int uwsgi_response_subhandler_web3(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);
|
||||
}
|
||||
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
|
||||
fclose(wsgi_req->async_post);
|
||||
if (!uwsgi.post_buffering || wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
clear2:
|
||||
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
if (wsgi_req->async_placeholder) {
|
||||
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
|
||||
}
|
||||
if (wsgi_req->async_result) {
|
||||
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
|
||||
}
|
||||
if (wsgi_req->async_app) {
|
||||
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
|
||||
}
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
+49
-145
@@ -4,16 +4,6 @@ extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
|
||||
typedef struct uwsgi_Input {
|
||||
PyObject_HEAD
|
||||
char readline[1024];
|
||||
size_t readline_size;
|
||||
size_t readline_max_size;
|
||||
size_t readline_pos;
|
||||
size_t pos;
|
||||
struct wsgi_request *wsgi_req;
|
||||
} uwsgi_Input;
|
||||
|
||||
PyObject *uwsgi_Input_iter(PyObject *self) {
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
@@ -56,13 +46,13 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
|
||||
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
|
||||
}
|
||||
|
||||
if (self->readline_max_size > 0 && self->readline_max_size < 1024) {
|
||||
if (self->readline_max_size > 0 && self->readline_max_size < UWSGI_PY_READLINE_BUFSIZE) {
|
||||
rlen = read(wsgi_req->poll.fd, self->readline, self->readline_max_size);
|
||||
}
|
||||
else {
|
||||
rlen = read(wsgi_req->poll.fd, self->readline, 1024);
|
||||
rlen = read(wsgi_req->poll.fd, self->readline, UWSGI_PY_READLINE_BUFSIZE);
|
||||
}
|
||||
if (rlen < 0) {
|
||||
if (rlen <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
|
||||
}
|
||||
@@ -166,7 +156,7 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
|
||||
}
|
||||
|
||||
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
|
||||
if (rlen < 0) {
|
||||
if (rlen <= 0) {
|
||||
free(tmp_buf);
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
|
||||
@@ -221,12 +211,18 @@ static PyObject *uwsgi_Input_close(uwsgi_Input *self, PyObject *args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *uwsgi_Input_fileno(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
return PyInt_FromLong(self->wsgi_req->poll.fd);
|
||||
}
|
||||
|
||||
static PyMethodDef uwsgi_Input_methods[] = {
|
||||
{ "read", (PyCFunction)uwsgi_Input_read, METH_VARARGS, 0 },
|
||||
{ "readline", (PyCFunction)uwsgi_Input_readline, METH_VARARGS, 0 },
|
||||
{ "readlines", (PyCFunction)uwsgi_Input_readlines, METH_VARARGS, 0 },
|
||||
// add close to allow mod_wsgi compatibility
|
||||
{ "close", (PyCFunction)uwsgi_Input_close, METH_VARARGS, 0 },
|
||||
{ "fileno", (PyCFunction)uwsgi_Input_fileno, METH_VARARGS, 0 },
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -327,16 +323,10 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
|
||||
|
||||
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
|
||||
char *path_info;
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
int tmp_stderr;
|
||||
char *what;
|
||||
int what_len;
|
||||
int free_appid = 0;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
@@ -363,7 +353,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
/* Standard WSGI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log( "Invalid WSGI request. skip.\n");
|
||||
uwsgi_log( "Empty python request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -372,76 +362,59 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
if (!up.ignore_script_name) {
|
||||
|
||||
if (!wsgi_req->script_name)
|
||||
wsgi_req->script_name = "";
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!up.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
what = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
what_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
|
||||
wsgi_req->appid = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
wsgi_req->appid_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost SCRIPT_NAME=%s\n", what);
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
|
||||
#endif
|
||||
free_appid = 1;
|
||||
}
|
||||
else {
|
||||
what = wsgi_req->script_name;
|
||||
what_len = wsgi_req->script_name_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(what, what_len, 0)) == -1) {
|
||||
if (wsgi_req->script_name_len > 1 || uwsgi.default_app < 0 || uwsgi.vhost) {
|
||||
/* unavailable app for this SCRIPT_NAME */
|
||||
wsgi_req->app_id = -1;
|
||||
if (wsgi_req->script_len > 0
|
||||
|| wsgi_req->module_len > 0
|
||||
|| wsgi_req->file_len > 0
|
||||
|| wsgi_req->paste_len > 0
|
||||
) {
|
||||
// this part must be heavy locked in threaded modes
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&up.lock_pyloaders);
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
if (uwsgi.single_interpreter) {
|
||||
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread);
|
||||
}
|
||||
else {
|
||||
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL);
|
||||
}
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_unlock(&up.lock_pyloaders);
|
||||
}
|
||||
}
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
if (uwsgi.no_default_app) {
|
||||
wsgi_req->app_id = -1;
|
||||
}
|
||||
if (wsgi_req->dynamic) {
|
||||
// this part must be heavy locked in threaded modes
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&up.lock_pyloaders);
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
if (uwsgi.single_interpreter) {
|
||||
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
wsgi_req->app_id = init_uwsgi_app(LOADER_DYN, (void *) wsgi_req, wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_unlock(&up.lock_pyloaders);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
free(what);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
wsgi_req->app_id = 0;
|
||||
}
|
||||
|
||||
if (free_appid) {
|
||||
free(wsgi_req->appid);
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
// use default app ?
|
||||
if (!uwsgi.no_default_app && uwsgi.default_app >= 0) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
else {
|
||||
internal_server_error(wsgi_req, "wsgi application not found");
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
internal_server_error(wsgi_req, "Python application not found");
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
wi = &uwsgi.apps[wsgi_req->app_id];
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
up.swap_ts(wsgi_req, wi);
|
||||
|
||||
@@ -455,21 +428,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->protocol_len < 5) {
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
|
||||
goto clear;
|
||||
|
||||
}
|
||||
|
||||
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(wsgi_req, "invalid HTTP protocol !!!");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
wsgi_req->async_environ = wi->environ[wsgi_req->async_id];
|
||||
wsgi_req->async_args = wi->args[wsgi_req->async_id];
|
||||
@@ -485,60 +443,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
Py_INCREF((PyObject *)wsgi_req->async_environ);
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
#ifdef PYTHREE
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
|
||||
#else
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
#endif
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
wsgi_req->uh.modifier1 = 0;
|
||||
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
|
||||
if (pydictkey) {
|
||||
if (PyString_Check(pydictkey)) {
|
||||
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
|
||||
if (pydictvalue) {
|
||||
if (PyString_Check(pydictvalue)) {
|
||||
path_info = PyString_AsString(pydictvalue);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
|
||||
#else
|
||||
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// create wsgi.input custom object
|
||||
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
|
||||
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
|
||||
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
|
||||
|
||||
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
@@ -38,7 +38,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
// in this way, error will be reported to the log
|
||||
PyErr_Restore(exc_type, exc_val, exc_tb);
|
||||
|
||||
goto clear;
|
||||
// the error is reported, let's continue...
|
||||
//goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,9 +191,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
UWSGI_RELEASE_GIL
|
||||
iov_ret = wsgi_req->socket->proto_writev_header(wsgi_req, iov_ptr, iov_size);
|
||||
UWSGI_GET_GIL
|
||||
if (iov_ret < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += iov_ret;
|
||||
iov_ptr += iov_size;
|
||||
remains -= iov_size;
|
||||
@@ -201,9 +199,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, j + 1);
|
||||
UWSGI_GET_GIL
|
||||
if (wsgi_req->headers_size < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
#endif
|
||||
|
||||
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
|
||||
|
||||
@@ -2,19 +2,74 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
PyObject *zero;
|
||||
int i;
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
char *path_info;
|
||||
|
||||
//static PyObject *uwsgi_version = NULL;
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
#ifdef PYTHREE
|
||||
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
|
||||
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
|
||||
#else
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
#endif
|
||||
|
||||
/*
|
||||
if (uwsgi_version == NULL) {
|
||||
uwsgi_version = PyString_FromString(UWSGI_VERSION);
|
||||
}
|
||||
*/
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%p %d %p %d\n", pydictkey, wsgi_req->hvec[i].iov_len, pydictvalue, wsgi_req->hvec[i + 1].iov_len);
|
||||
#endif
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
wsgi_req->uh.modifier1 = 0;
|
||||
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
|
||||
if (pydictkey) {
|
||||
if (PyString_Check(pydictkey)) {
|
||||
pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
|
||||
if (pydictvalue) {
|
||||
if (PyString_Check(pydictvalue)) {
|
||||
path_info = PyString_AsString(pydictvalue);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
|
||||
#else
|
||||
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// create wsgi.input custom object
|
||||
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
|
||||
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
|
||||
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
@@ -28,19 +83,18 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
}
|
||||
#endif
|
||||
|
||||
// cache this
|
||||
zero = PyTuple_New(2);
|
||||
PyTuple_SetItem(zero, 0, PyInt_FromLong(1));
|
||||
PyTuple_SetItem(zero, 1, PyInt_FromLong(0));
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", zero);
|
||||
Py_DECREF(zero);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
|
||||
|
||||
zero = PyFile_FromFile(stderr, "wsgi_input", "w", NULL);
|
||||
#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);
|
||||
|
||||
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_True);
|
||||
}
|
||||
@@ -55,18 +109,18 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
}
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
else if (wsgi_req->https_len > 0) {
|
||||
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
|
||||
zero = PyString_FromString("https");
|
||||
zero = UWSGI_PYFROMSTRING("https");
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
zero = UWSGI_PYFROMSTRING("http");
|
||||
}
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromString("http");
|
||||
zero = UWSGI_PYFROMSTRING("http");
|
||||
}
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
@@ -74,19 +128,23 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
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
|
||||
|
||||
zero = PyString_FromString(UWSGI_VERSION);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", zero);
|
||||
Py_DECREF(zero);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
|
||||
|
||||
if (uwsgi.cores > 1) {
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
|
||||
zero = PyInt_FromLong(wsgi_req->async_id);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
// cache this ?
|
||||
if (uwsgi.cluster_fd >= 0) {
|
||||
zero = PyString_FromString(uwsgi.cluster);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
|
||||
@@ -96,9 +154,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
zero = PyString_FromString(uwsgi.hostname);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", zero);
|
||||
Py_DECREF(zero);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
|
||||
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
@@ -113,7 +169,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
|
||||
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);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
@@ -138,7 +194,11 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
#ifdef __FreeBSD__
|
||||
if ( ((wsgi_req->sendfile_obj == wsgi_req->async_result) || ( wsgi_req->sendfile_fd_size > 0 && wsgi_req->response_size < wsgi_req->sendfile_fd_size)) && wsgi_req->sendfile_fd != -1) {
|
||||
#else
|
||||
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
|
||||
#endif
|
||||
sf_len = uwsgi_sendfile(wsgi_req);
|
||||
if (sf_len < 1) goto clear;
|
||||
wsgi_req->response_size += sf_len;
|
||||
@@ -180,6 +240,7 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
PyErr_Print();
|
||||
}
|
||||
goto clear;
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python24'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python25'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python26'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python27'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python30'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.0-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python31'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.1-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -2,7 +2,7 @@ import os,sys
|
||||
|
||||
NAME='python32'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'gil', 'uwsgi_pymodule', 'profiler'])
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.2-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
PyObject *u_run(PyObject *self, PyObject *args) {
|
||||
|
||||
char **argv;
|
||||
size_t size = 2;
|
||||
int i;
|
||||
|
||||
if (PyTuple_Size(args) < 1) {
|
||||
return PyErr_Format(PyExc_ValueError, "you have to specify at least one uWSGI option to run() it");
|
||||
}
|
||||
|
||||
PyObject *the_arg = PyTuple_GetItem(args, 0);
|
||||
|
||||
if (PyList_Check(the_arg)) {
|
||||
size = PyList_Size(the_arg) + 2;
|
||||
}
|
||||
else if (PyTuple_Check(the_arg)) {
|
||||
size = PyTuple_Size(the_arg) + 2;
|
||||
}
|
||||
else if (PyString_Check(the_arg)) {
|
||||
size = 3;
|
||||
}
|
||||
|
||||
argv = uwsgi_malloc(sizeof(char *) * size);
|
||||
memset(argv, 0, sizeof(char *) * size);
|
||||
|
||||
// will be overwritten
|
||||
argv[0] = "uwsgi";
|
||||
|
||||
if (PyList_Check(the_arg)) {
|
||||
for(i=0;i<PyList_Size(the_arg);i++) {
|
||||
argv[i+1] = PyString_AsString( PyList_GetItem(the_arg, i) );
|
||||
}
|
||||
}
|
||||
else if (PyTuple_Check(the_arg)) {
|
||||
for(i=0;i<PyTuple_Size(the_arg);i++) {
|
||||
argv[i+1] = PyString_AsString( PyTuple_GetItem(the_arg, i) );
|
||||
}
|
||||
}
|
||||
else if (PyString_Check(the_arg)) {
|
||||
argv[1] = PyString_AsString( the_arg );
|
||||
}
|
||||
|
||||
uwsgi_init(size-1, argv, environ);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyMethodDef methods[] = {
|
||||
{"run", u_run, METH_VARARGS, "run the uWSGI server"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initpyuwsgi()
|
||||
{
|
||||
(void) Py_InitModule("pyuwsgi", methods);
|
||||
}
|
||||
|
||||
|
||||
int pyuwsgi_init() { return 0; }
|
||||
|
||||
struct uwsgi_plugin pyuwsgi_plugin = {
|
||||
|
||||
.name = "pyuwsgi",
|
||||
.init = pyuwsgi_init,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from distutils import sysconfig
|
||||
import os
|
||||
|
||||
os.environ['UWSGI_PYTHON_NOLIB'] = '1'
|
||||
|
||||
NAME='pyuwsgi'
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['pyuwsgi']
|
||||
+193
-52
@@ -9,6 +9,7 @@ struct option uwsgi_rack_options[] = {
|
||||
{"rails", required_argument, 0, LONG_ARGS_RAILS},
|
||||
{"rack", required_argument, 0, LONG_ARGS_RACK},
|
||||
{"ruby-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
|
||||
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -32,53 +33,7 @@ void uwsgi_ruby_exception(void) {
|
||||
|
||||
|
||||
|
||||
/* statistically ordered */
|
||||
static struct http_status_codes hsc[] = {
|
||||
|
||||
{"200", "OK"},
|
||||
{"302", "Found"},
|
||||
{"404", "Not Found"},
|
||||
{"500", "Internal Server Error"},
|
||||
{"301", "Moved Permanently"},
|
||||
{"304", "Not Modified"},
|
||||
{"303", "See Other"},
|
||||
{"403", "Forbidden"},
|
||||
{"307", "Temporary Redirect"},
|
||||
{"401", "Unauthorized"},
|
||||
{"400", "Bad Request"},
|
||||
{"405", "Method Not Allowed"},
|
||||
{"408", "Request Timeout"},
|
||||
|
||||
{"100", "Continue"},
|
||||
{"101", "Switching Protocols"},
|
||||
{"201", "Created"},
|
||||
{"202", "Accepted"},
|
||||
{"203", "Non-Authoritative Information"},
|
||||
{"204", "No Content"},
|
||||
{"205", "Reset Content"},
|
||||
{"206", "Partial Content"},
|
||||
{"300", "Multiple Choices"},
|
||||
{"305", "Use Proxy"},
|
||||
{"402", "Payment Required"},
|
||||
{"406", "Not Acceptable"},
|
||||
{"407", "Proxy Authentication Required"},
|
||||
{"409", "Conflict"},
|
||||
{"410", "Gone"},
|
||||
{"411", "Length Required"},
|
||||
{"412", "Precondition Failed"},
|
||||
{"413", "Request Entity Too Large"},
|
||||
{"414", "Request-URI Too Long"},
|
||||
{"415", "Unsupported Media Type"},
|
||||
{"416", "Requested Range Not Satisfiable"},
|
||||
{"417", "Expectation Failed"},
|
||||
{"501", "Not Implemented"},
|
||||
{"502", "Bad Gateway"},
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{ "", NULL },
|
||||
};
|
||||
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
|
||||
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
|
||||
@@ -186,6 +141,142 @@ VALUE require_rails(VALUE arg) {
|
||||
|
||||
VALUE init_rack_app(VALUE);
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
|
||||
if (uwsgi_signal_registered(uwsgi_signal)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
char *signal_kind = RSTRING_PTR(sigkind);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_gc_register_address(&rbhandler);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
|
||||
if (rlen != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_call_signal_handler(VALUE args) {
|
||||
|
||||
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
|
||||
}
|
||||
|
||||
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
VALUE rbhandler = (VALUE) handler;
|
||||
VALUE args = rb_ary_new2(2);
|
||||
rb_ary_store(args, 0, rbhandler);
|
||||
VALUE rbsig = INT2NUM(sig);
|
||||
rb_ary_store(args, 1, rbsig);
|
||||
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int minute = NUM2INT(rbmin);
|
||||
int hour = NUM2INT(rbhour);
|
||||
int day = NUM2INT(rbday);
|
||||
int month = NUM2INT(rbmon);
|
||||
int week = NUM2INT(rbweek);
|
||||
|
||||
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add cron");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
|
||||
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
char *filename = RSTRING_PTR(rbfilename);
|
||||
|
||||
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add file monitor");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
@@ -253,13 +344,13 @@ int uwsgi_rack_init(){
|
||||
char **argv = sargv;
|
||||
#endif
|
||||
|
||||
int error;
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = (int) strlen(http_sc->message);
|
||||
}
|
||||
|
||||
ur.unprotected = 0;
|
||||
|
||||
#ifdef RUBY19
|
||||
ruby_sysinit(&argc, &argv);
|
||||
@@ -281,6 +372,20 @@ int uwsgi_rack_init(){
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_cron", rack_uwsgi_add_cron, 6);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_timer", rack_uwsgi_add_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_rb_timer", rack_uwsgi_add_rb_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_file_monitor", rack_uwsgi_add_file_monitor, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_rack_init_apps(void) {
|
||||
|
||||
int error;
|
||||
|
||||
if (ur.rack) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
|
||||
@@ -289,9 +394,12 @@ int uwsgi_rack_init(){
|
||||
exit(1);
|
||||
}
|
||||
if (ur.dispatcher == Qnil) {
|
||||
uwsgi_log("unable to find RACK entry point\n");
|
||||
exit(1);
|
||||
}
|
||||
rb_gc_register_address(&ur.dispatcher);
|
||||
|
||||
goto ready;
|
||||
}
|
||||
else if (ur.rails) {
|
||||
if (chdir(ur.rails)) {
|
||||
@@ -314,10 +422,18 @@ int uwsgi_rack_init(){
|
||||
uwsgi_log("unable to load rails dispatcher\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
goto ready;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
ready:
|
||||
ur.call = rb_intern("call");
|
||||
if (!ur.call) {
|
||||
uwsgi_log("unable to find RACK entry point\n");
|
||||
return;
|
||||
}
|
||||
rb_gc_register_address(&ur.call);
|
||||
|
||||
|
||||
@@ -332,8 +448,6 @@ int uwsgi_rack_init(){
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
VALUE call_dispatch(VALUE env) {
|
||||
@@ -521,7 +635,21 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
rb_ary_store(rbv, 1, INT2NUM(1));
|
||||
rb_hash_aset(env, rb_str_new2("rack.version"), rbv);
|
||||
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new(wsgi_req->scheme, wsgi_req->scheme_len));
|
||||
}
|
||||
else if (wsgi_req->https_len > 0) {
|
||||
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("https"));
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
|
||||
}
|
||||
|
||||
|
||||
rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse);
|
||||
rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue);
|
||||
@@ -625,7 +753,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
|
||||
if (wsgi_req->response_size > 0) {
|
||||
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
|
||||
uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
|
||||
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
}
|
||||
}
|
||||
@@ -692,11 +820,16 @@ void uwsgi_rack_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int uwsgi_rack_manage_options(int i, char *optarg) {
|
||||
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_RAILS:
|
||||
// HACK: can be overridden with --post-buffering
|
||||
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
|
||||
ur.rails = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_RACK:
|
||||
// HACK: can be overridden with --post-buffering
|
||||
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
|
||||
ur.rack = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_RUBY_GC_FREQ:
|
||||
@@ -788,6 +921,9 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
}
|
||||
*/
|
||||
|
||||
void uwsgi_rack_hijack(void) {
|
||||
}
|
||||
|
||||
struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.name = "rack",
|
||||
@@ -798,6 +934,11 @@ struct uwsgi_plugin rack_plugin = {
|
||||
.request = uwsgi_rack_request,
|
||||
.after_request = uwsgi_rack_after_request,
|
||||
|
||||
.signal_handler = uwsgi_rack_signal_handler,
|
||||
|
||||
.hijack = uwsgi_rack_hijack,
|
||||
|
||||
.init_apps = uwsgi_rack_init_apps,
|
||||
//.mount_app = uwsgi_rack_mount_app,
|
||||
.manage_xml = uwsgi_rack_xml,
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define LONG_ARGS_RAILS LONG_ARGS_RACK_BASE + 1
|
||||
#define LONG_ARGS_RUBY_GC_FREQ LONG_ARGS_RACK_BASE + 2
|
||||
#define LONG_ARGS_RACK LONG_ARGS_RACK_BASE + 3
|
||||
#define LONG_ARGS_RUBY_SHELL LONG_ARGS_RACK_BASE + 4
|
||||
|
||||
#ifndef RUBY19
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
@@ -59,6 +60,8 @@ struct uwsgi_rack {
|
||||
|
||||
pthread_mutex_t gvl;
|
||||
|
||||
int rb_shell;
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_ruby_exception(void);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int (*symcall_function)(struct wsgi_request *);
|
||||
|
||||
int uwsgi_symcall_init(){
|
||||
symcall_function = dlsym(RTLD_DEFAULT, "pypy_uwsgi_request");
|
||||
uwsgi_log("symcall function ptr: %p\n", symcall_function);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
return symcall_function(wsgi_req);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_symcall_after_request(struct wsgi_request *wsgi_req) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin symcall_plugin = {
|
||||
|
||||
.name = "symcall",
|
||||
.modifier1 = 18,
|
||||
.init = uwsgi_symcall_init,
|
||||
.request = uwsgi_symcall_request,
|
||||
.after_request = uwsgi_symcall_after_request,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='symcall'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['symcall_plugin']
|
||||
+72
-6
@@ -42,6 +42,20 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, i
|
||||
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
keylen += 5;
|
||||
prefix = 1;
|
||||
if (!uwsgi_strncmp("IF_MODIFIED_SINCE", 17, hh, keylen)) {
|
||||
wsgi_req->if_modified_since = val;
|
||||
wsgi_req->if_modified_since_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("X_FORWARDED_SSL", 15, hh, keylen)) {
|
||||
if (vallen == 2 && val[0] == 'o' && val[1] == 'n') {
|
||||
wsgi_req->scheme = "https";
|
||||
wsgi_req->scheme_len = 5;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.vhost_host && !uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
wsgi_req->host = val;
|
||||
wsgi_req->host_len = vallen;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
wsgi_req->post_cl = uwsgi_str_num(val, vallen);
|
||||
@@ -92,10 +106,14 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
char ip[INET_ADDRSTRLEN+1];
|
||||
struct sockaddr_in *http_sin = (struct sockaddr_in *) &wsgi_req->c_addr;
|
||||
|
||||
wsgi_req->path_info_pos = -1;
|
||||
|
||||
// REQUEST_METHOD
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == ' ') {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, base, ptr - base);
|
||||
wsgi_req->method = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->method_len = ptr - base;
|
||||
ptr++;
|
||||
break;
|
||||
}
|
||||
@@ -106,17 +124,46 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
base = ptr;
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == '?' && !query_string) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
|
||||
wsgi_req->path_info = watermark;
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
wsgi_req->path_info_pos = 3;
|
||||
query_string = ptr + 1;
|
||||
}
|
||||
else if (*ptr == ' ') {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, base, ptr - base);
|
||||
wsgi_req->uri = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->uri_len = ptr - base;
|
||||
|
||||
if (!query_string) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
|
||||
wsgi_req->path_info = watermark;
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
wsgi_req->path_info_pos = 5;
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, query_string, ptr - query_string);
|
||||
wsgi_req->query_string = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - query_string);
|
||||
wsgi_req->query_string_len = ptr - query_string;
|
||||
}
|
||||
ptr++;
|
||||
break;
|
||||
@@ -133,6 +180,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
if (*(ptr + 1) != '\n')
|
||||
return 0;
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, base, ptr - base);
|
||||
wsgi_req->protocol = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->protocol_len = ptr - base;
|
||||
ptr += 2;
|
||||
break;
|
||||
}
|
||||
@@ -140,18 +189,31 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
}
|
||||
|
||||
// SCRIPT_NAME
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);
|
||||
if (!uwsgi.manage_script_name) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);
|
||||
}
|
||||
|
||||
|
||||
// SERVER_NAME
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);
|
||||
wsgi_req->host = uwsgi.hostname;
|
||||
wsgi_req->host_len = uwsgi.hostname_len;
|
||||
|
||||
// SERVER_PORT
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "3031", 4);
|
||||
char *server_port = strchr(wsgi_req->socket->name, ':');
|
||||
if (server_port) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, server_port+1, strlen(server_port+1));
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
|
||||
}
|
||||
|
||||
// REMOTE_ADDR
|
||||
memset(ip, 0, INET_ADDRSTRLEN+1);
|
||||
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
|
||||
wsgi_req->remote_addr = (wsgi_req->buffer + wsgi_req->uh.pktsize) - strlen(ip);
|
||||
wsgi_req->remote_addr_len = strlen(ip);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("inet_ntop()");
|
||||
@@ -230,7 +292,11 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
len = read(wsgi_req->poll.fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, uwsgi.buffer_size - wsgi_req->proto_parser_pos);
|
||||
if (len <= 0) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
uwsgi_error("recv()");
|
||||
if (len < 0) {
|
||||
uwsgi_error("recv()");
|
||||
}
|
||||
// this is simple ping packet
|
||||
else { return -2; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -253,7 +319,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
remains = len - (j + 1);
|
||||
http_parse(wsgi_req, ptr);
|
||||
//is there a Content_Length ?
|
||||
if (wsgi_req->post_cl) {
|
||||
if (wsgi_req->post_cl > 0) {
|
||||
wsgi_req->async_post = tmpfile();
|
||||
if (!wsgi_req->async_post) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
|
||||
+24
-4
@@ -115,17 +115,37 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_uwsgi_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 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 writev(wsgi_req->poll.fd, iovec, 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_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
return write(wsgi_req->poll.fd, buf, 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 write(wsgi_req->poll.fd, buf, len);
|
||||
ssize_t wlen = write(wsgi_req->poll.fd, buf, len);
|
||||
if (wlen < 0) {
|
||||
uwsgi_req_error("write()");
|
||||
return 0;
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
@@ -454,7 +454,6 @@ ssize_t uwsgi_proto_zeromq_sendfile(struct wsgi_request * wsgi_req) {
|
||||
|
||||
wsgi_req->sendfile_fd_chunk = 65536;
|
||||
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
len = read(wsgi_req->sendfile_fd, buf, UMIN(remains, wsgi_req->sendfile_fd_chunk));
|
||||
if (len != (int) UMIN(remains, wsgi_req->sendfile_fd_chunk)) {
|
||||
|
||||
+176
-24
@@ -355,7 +355,7 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
|
||||
exit(1);
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
uwsgi_log( "timeout waiting for header. skip request.\n");
|
||||
uwsgi_log( "timeout. skip request.\n");
|
||||
//close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -366,7 +366,10 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
|
||||
status = uwsgi_proto_uwsgi_parser(wsgi_req);
|
||||
}
|
||||
if (status < 0) {
|
||||
uwsgi_log("error parsing request\n");
|
||||
if (status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
else if (status == -2)
|
||||
uwsgi_log("open-close packet (ping/check) received\n");
|
||||
//close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -405,7 +408,7 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
|
||||
*argc = *argc + 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "invalid uwsgi array. skip this request.\n");
|
||||
uwsgi_log( "invalid uwsgi array. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -419,6 +422,73 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_simple_parse_vars(struct wsgi_request *wsgi_req, char *ptrbuf, char *bufferend) {
|
||||
|
||||
uint16_t strsize;
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
/* key cannot be null */
|
||||
if (!strsize) {
|
||||
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize < bufferend) {
|
||||
// var key
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
ptrbuf += strsize;
|
||||
// value can be null (even at the end) so use <=
|
||||
if (ptrbuf + 2 <= bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
|
||||
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "max vec size reached. skip this header.\n");
|
||||
return -1;
|
||||
}
|
||||
// var value
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
|
||||
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "max vec size reached. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
ptrbuf += strsize;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *buffer = wsgi_req->buffer;
|
||||
@@ -429,10 +499,19 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + wsgi_req->uh.pktsize;
|
||||
int i, script_name= -1, path_info= -1;
|
||||
int i, script_name= -1;
|
||||
|
||||
/* set an HTTP 500 status as default */
|
||||
wsgi_req->status = 500;
|
||||
|
||||
// has the protocol already parsed the request ?
|
||||
if (wsgi_req->uri_len > 0) {
|
||||
i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend);
|
||||
if (i == 0) goto next;
|
||||
return i;
|
||||
}
|
||||
|
||||
wsgi_req->path_info_pos = -1;
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
@@ -442,7 +521,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
#endif
|
||||
/* key cannot be null */
|
||||
if (!strsize) {
|
||||
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
|
||||
uwsgi_log( "uwsgi key cannot be null. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -472,7 +551,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
else if (!uwsgi_strncmp("PATH_INFO", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->path_info = ptrbuf;
|
||||
wsgi_req->path_info_len = strsize;
|
||||
path_info = wsgi_req->var_cnt + 1;
|
||||
wsgi_req->path_info_pos = wsgi_req->var_cnt + 1;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
@@ -493,7 +572,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->method = ptrbuf;
|
||||
wsgi_req->method_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi.log_x_forwarded_for && !uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_addr = ptrbuf;
|
||||
wsgi_req->remote_addr_len = strsize;
|
||||
}
|
||||
@@ -508,14 +587,17 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
else if (!uwsgi_strncmp("UWSGI_SCRIPT", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
|
||||
wsgi_req->script = ptrbuf;
|
||||
wsgi_req->script_len = strsize;
|
||||
wsgi_req->dynamic = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_MODULE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->module = ptrbuf;
|
||||
wsgi_req->module_len = strsize;
|
||||
wsgi_req->dynamic = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_CALLABLE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->callable = ptrbuf;
|
||||
wsgi_req->callable_len = strsize;
|
||||
wsgi_req->dynamic = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_PYHOME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->pyhome = ptrbuf;
|
||||
@@ -525,9 +607,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->chdir = ptrbuf;
|
||||
wsgi_req->chdir_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_APPID", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->appid = ptrbuf;
|
||||
wsgi_req->appid_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->file = ptrbuf;
|
||||
wsgi_req->file_len = strsize;
|
||||
wsgi_req->dynamic = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->touch_reload = ptrbuf;
|
||||
@@ -570,6 +657,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->if_modified_since = ptrbuf;
|
||||
wsgi_req->if_modified_since_len = strsize;
|
||||
}
|
||||
else if (uwsgi.log_x_forwarded_for && !uwsgi_strncmp("HTTP_X_FORWARDED_FOR", 20, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_addr = ptrbuf;
|
||||
wsgi_req->remote_addr_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("CONTENT_TYPE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->content_type = ptrbuf;
|
||||
wsgi_req->content_type_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
|
||||
if (uwsgi.limit_post) {
|
||||
@@ -585,7 +680,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "max vec size reached. skip this header.\n");
|
||||
uwsgi_log( "max vec size reached. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
// var value
|
||||
@@ -596,7 +691,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "max vec size reached. skip this header.\n");
|
||||
uwsgi_log( "max vec size reached. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
ptrbuf += strsize;
|
||||
@@ -618,6 +713,8 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
|
||||
if (uwsgi.post_buffering > 0 && !wsgi_req->body_as_file && !wsgi_req->async_post) {
|
||||
// read to disk if post_cl > post_buffering (it will eventually do upload progress...)
|
||||
if (wsgi_req->post_cl >= (size_t) uwsgi.post_buffering) {
|
||||
@@ -661,7 +758,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (uwsgi.manage_script_name) {
|
||||
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
|
||||
if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len > 1 && wsgi_req->path_info_pos != -1) {
|
||||
// starts with 1 as the 0 app is the default (/) one
|
||||
int best_found = 0;
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
@@ -669,30 +766,33 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
// if SCRIPT_NAME is not allocated, add a slot for it
|
||||
if (script_name == -1) {
|
||||
if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
|
||||
uwsgi_log( "max vec size reached. skip this header.\n");
|
||||
uwsgi_log( "max vec size reached. skip this var.\n");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->var_cnt++;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = "SCRIPT_NAME";
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11;
|
||||
wsgi_req->var_cnt++;
|
||||
script_name = wsgi_req->var_cnt;
|
||||
wsgi_req->hvec[script_name].iov_base = "";
|
||||
wsgi_req->hvec[script_name].iov_len = 0;
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
for(i=0;i<uwsgi.apps_cnt;i++) {
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint);
|
||||
if (orig_path_info_len >= uwsgi.apps[i].mountpoint_len) {
|
||||
if (!uwsgi_startswith(orig_path_info, uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len) && uwsgi.apps[i].mountpoint_len > best_found) {
|
||||
best_found = uwsgi.apps[i].mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi.apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi.apps[i].mountpoint_len;
|
||||
|
||||
for(i=0;i<uwsgi_apps_cnt;i++) {
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
|
||||
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
|
||||
best_found = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info+wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len-wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[script_name].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[script_name].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[path_info].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[path_info].iov_len = wsgi_req->path_info_len;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
@@ -1236,6 +1336,48 @@ int uwsgi_simple_send_string(char *socket_name, uint8_t modifier1, uint8_t modif
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
char *ext = NULL;
|
||||
for(i=namelen-1;i>=0;i--) {
|
||||
if (!isalnum( (int)name[i])) {
|
||||
if (name[i] == '.') {
|
||||
ext = name+(namelen-count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
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, char *orig_document_root, uint16_t orig_document_root_len) {
|
||||
|
||||
@@ -1260,6 +1402,8 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
return -1;
|
||||
}
|
||||
if (!stat(real_filename, &st)) {
|
||||
int mime_type_size = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
|
||||
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) {
|
||||
@@ -1292,11 +1436,19 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
while(ah) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
wsgi_req->header_cnt++;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
wsgi_req->header_cnt++;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "Content-Type: ", 14);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, mime_type, mime_type_size);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
}
|
||||
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
wsgi_req->header_cnt = 2;
|
||||
wsgi_req->header_cnt += 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
|
||||
if (orig_document_root[orig_document_root_len-1] != '/') {
|
||||
@@ -1308,7 +1460,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
}
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
wsgi_req->header_cnt = 2;
|
||||
wsgi_req->header_cnt += 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Sendfile: ", 12);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
|
||||
if (orig_document_root[orig_document_root_len-1] != '/') {
|
||||
@@ -1320,7 +1472,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
}
|
||||
else {
|
||||
wsgi_req->header_cnt = 1;
|
||||
wsgi_req->header_cnt += 1;
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import sys
|
||||
import os
|
||||
import pyuwsgi
|
||||
|
||||
orig_args = sys.argv
|
||||
orig_executable = sys.executable
|
||||
orig_args.insert(0, orig_executable)
|
||||
|
||||
uwsgi_args = []
|
||||
|
||||
for arg in sys.argv[2:]:
|
||||
uwsgi_args.append(arg)
|
||||
|
||||
#pyuwsgi.run('welcome.ini')
|
||||
pyuwsgi.run(uwsgi_args)
|
||||
|
||||
# if you are here uWSGI has been reloaded
|
||||
os.execv(orig_executable, orig_args)
|
||||
@@ -0,0 +1,22 @@
|
||||
import sys
|
||||
import os
|
||||
import pyuwsgi
|
||||
|
||||
orig_args = sys.argv
|
||||
orig_executable = sys.executable
|
||||
orig_args.insert(0, orig_executable)
|
||||
|
||||
uwsgi_args = []
|
||||
|
||||
uwsgi_args.append('--socket')
|
||||
uwsgi_args.append(':3031')
|
||||
#uwsgi_args.append('--master')
|
||||
uwsgi_args.append('--module')
|
||||
#uwsgi_args.append('welcome')
|
||||
uwsgi_args.append('hello')
|
||||
|
||||
#pyuwsgi.run('welcome.ini')
|
||||
pyuwsgi.run(uwsgi_args)
|
||||
|
||||
# if you are here uWSGI has been reloaded
|
||||
os.execv(orig_executable, orig_args)
|
||||
@@ -6,17 +6,15 @@ void uwsgi_init_queue() {
|
||||
if (!uwsgi.queue_blocksize)
|
||||
uwsgi.queue_blocksize = 8192;
|
||||
|
||||
if (uwsgi.queue_blocksize % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid queue blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
|
||||
if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
uwsgi.shared->queue_pos = 0;
|
||||
uwsgi.shared->queue_pull_pos = 0;
|
||||
|
||||
if (uwsgi.queue_store) {
|
||||
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size;
|
||||
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
|
||||
int queue_fd;
|
||||
struct stat qst;
|
||||
|
||||
@@ -45,16 +43,26 @@ void uwsgi_init_queue() {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
|
||||
uwsgi_queue_fix();
|
||||
|
||||
// fix header
|
||||
uwsgi.queue_header = uwsgi.queue;
|
||||
uwsgi.queue+=16;
|
||||
}
|
||||
else {
|
||||
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size)+16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
// fix header
|
||||
uwsgi.queue_header = uwsgi.queue;
|
||||
uwsgi.queue+=16;
|
||||
uwsgi.queue_header->pos = 0;
|
||||
uwsgi.queue_header->pull_pos = 0;
|
||||
}
|
||||
if (!uwsgi.queue) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uwsgi.queue_lock = uwsgi_mmap_shared_rwlock();
|
||||
uwsgi_rwlock_init(uwsgi.queue_lock);
|
||||
|
||||
@@ -78,33 +86,20 @@ char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_queue_fix() {
|
||||
|
||||
uint64_t i;
|
||||
char *value;
|
||||
uint64_t size;
|
||||
|
||||
for(i=0;i< uwsgi.queue_size;i++) {
|
||||
// valid record ?
|
||||
value = uwsgi_queue_get(i, &size);
|
||||
if (value && size) {
|
||||
uwsgi.shared->queue_pos++;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_queue_pop(uint64_t *size) {
|
||||
|
||||
struct uwsgi_queue_item *uqi;
|
||||
char *ptr = (char *) uwsgi.queue;
|
||||
|
||||
if (uwsgi.shared->queue_pos > 0) uwsgi.shared->queue_pos--;
|
||||
if (uwsgi.queue_header->pos == 0) {
|
||||
uwsgi.queue_header->pos = uwsgi.queue_size-1;
|
||||
}
|
||||
else {
|
||||
uwsgi.queue_header->pos--;
|
||||
}
|
||||
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
|
||||
uqi = (struct uwsgi_queue_item *) ptr;
|
||||
|
||||
if (!uqi->size) return NULL;
|
||||
@@ -122,16 +117,16 @@ char *uwsgi_queue_pull(uint64_t *size) {
|
||||
struct uwsgi_queue_item *uqi;
|
||||
char *ptr = (char *) uwsgi.queue;
|
||||
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pull_pos);
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pull_pos);
|
||||
uqi = (struct uwsgi_queue_item *) ptr;
|
||||
|
||||
if (!uqi->size) return NULL;
|
||||
|
||||
*size = uqi->size;
|
||||
|
||||
uwsgi.shared->queue_pull_pos++;
|
||||
uwsgi.queue_header->pull_pos++;
|
||||
|
||||
if (uwsgi.shared->queue_pull_pos >= uwsgi.queue_size) uwsgi.shared->queue_pull_pos = 0;
|
||||
if (uwsgi.queue_header->pull_pos >= uwsgi.queue_size) uwsgi.queue_header->pull_pos = 0;
|
||||
|
||||
// remove item
|
||||
uqi->size = 0;
|
||||
@@ -150,7 +145,7 @@ int uwsgi_queue_push(char *message, uint64_t size) {
|
||||
|
||||
if (!size) return 0;
|
||||
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
|
||||
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
|
||||
uqi = (struct uwsgi_queue_item *) ptr;
|
||||
|
||||
ptr += sizeof(struct uwsgi_queue_item);
|
||||
@@ -159,9 +154,34 @@ int uwsgi_queue_push(char *message, uint64_t size) {
|
||||
uqi->ts = time(NULL);
|
||||
memcpy(ptr, message, size);
|
||||
|
||||
uwsgi.shared->queue_pos++;
|
||||
uwsgi.queue_header->pos++;
|
||||
|
||||
if (uwsgi.shared->queue_pos >= uwsgi.queue_size) uwsgi.shared->queue_pos = 0;
|
||||
if (uwsgi.queue_header->pos >= uwsgi.queue_size) uwsgi.queue_header->pos = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
|
||||
|
||||
struct uwsgi_queue_item *uqi;
|
||||
char *ptr = (char *) uwsgi.queue;
|
||||
|
||||
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
|
||||
return 0;
|
||||
|
||||
if (!size) return 0;
|
||||
|
||||
if (pos >= uwsgi.queue_size) return 0;
|
||||
|
||||
ptr = ptr + (uwsgi.queue_blocksize*pos);
|
||||
uqi = (struct uwsgi_queue_item *) ptr;
|
||||
|
||||
ptr += sizeof(struct uwsgi_queue_item);
|
||||
|
||||
uqi->size = size;
|
||||
uqi->ts = time(NULL);
|
||||
memcpy(ptr, message, size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,30 @@
|
||||
#ifdef UWSGI_PCRE
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
#include <pcre.h>
|
||||
void uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
|
||||
|
||||
const char *errstr;
|
||||
int erroff;
|
||||
|
||||
*pattern = pcre_compile( (const char *)re, 0, &errstr, &erroff, NULL);
|
||||
if (!*pattern) {
|
||||
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
|
||||
if (!*pattern_extra) {
|
||||
uwsgi_log("pcre (study) error: %s\n", errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length) {
|
||||
|
||||
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
+5
-3
@@ -56,9 +56,11 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
|
||||
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
|
||||
}
|
||||
|
||||
if (sf_ret) {
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
if (sf_ret < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
uwsgi_error("sendfile()");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sf_len;
|
||||
|
||||
@@ -6,8 +6,17 @@ import shutil
|
||||
from setuptools import setup
|
||||
from setuptools.dist import Distribution
|
||||
from setuptools.command.install import install
|
||||
from setuptools.command.install_lib import install_lib
|
||||
from setuptools.command.build_ext import build_ext
|
||||
|
||||
def get_profile():
|
||||
profile = os.environ.get('UWSGI_PROFILE','buildconf/default.ini')
|
||||
if not profile.endswith('.ini'):
|
||||
profile = "%s.ini" % profile
|
||||
if not '/' in profile:
|
||||
profile = "buildconf/%s" % profile
|
||||
|
||||
return profile
|
||||
|
||||
def patch_bin_path(cmd, conf):
|
||||
|
||||
@@ -26,7 +35,7 @@ def patch_bin_path(cmd, conf):
|
||||
class uWSGIBuilder(build_ext):
|
||||
|
||||
def run(self):
|
||||
conf = uc.uConf('buildconf/default.ini')
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
|
||||
@@ -34,11 +43,16 @@ class uWSGIBuilder(build_ext):
|
||||
class uWSGIInstall(install):
|
||||
|
||||
def run(self):
|
||||
# hack, hack and still hack. We need to find a solution...
|
||||
if self.record:
|
||||
record_file = open(self.record,'w')
|
||||
|
||||
conf = uc.uConf('buildconf/default.ini')
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
install.run(self)
|
||||
|
||||
class uWSGIInstallLib(install_lib):
|
||||
|
||||
def run(self):
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
|
||||
@@ -47,9 +61,9 @@ class uWSGIDistribution(Distribution):
|
||||
def __init__(self, *attrs):
|
||||
Distribution.__init__(self, *attrs)
|
||||
self.cmdclass['install'] = uWSGIInstall
|
||||
self.cmdclass['install_lib'] = uWSGIInstallLib
|
||||
self.cmdclass['build_ext'] = uWSGIBuilder
|
||||
|
||||
|
||||
setup(name='uWSGI',
|
||||
version=uc.uwsgi_version,
|
||||
description='The uWSGI server',
|
||||
|
||||
@@ -12,7 +12,55 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
|
||||
// set harakiri here (if required and if i am a worker)
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 1;
|
||||
uwsgi.workers[uwsgi.mywid].signum = sig;
|
||||
uwsgi.workers[uwsgi.mywid].signals++;
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].sig = 1;
|
||||
uwsgi.mules[uwsgi.muleid-1].signum = sig;
|
||||
uwsgi.mules[uwsgi.muleid-1].signals++;
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
if(uwsgi.workers[uwsgi.mywid].harakiri > 0) {
|
||||
set_harakiri(0);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].sig = 0;
|
||||
if(uwsgi.mules[uwsgi.muleid-1].harakiri > 0) {
|
||||
set_mule_harakiri(0);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_signal_registered(uint8_t sig) {
|
||||
@@ -166,7 +214,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
// send to all workers
|
||||
else if (!strcmp(use->receiver, "workers")) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
@@ -178,7 +226,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
if (i > uwsgi.numproc) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
if (write(uwsgi.signal_pipe[i][0], &sig, 1) != 1) {
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
@@ -187,6 +235,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
else if (!strcmp(use->receiver, "subscribed")) {
|
||||
}
|
||||
// route to spooler
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (!strcmp(use->receiver, "spooler")) {
|
||||
if (ushared->worker_signal_pipe[0] != -1) {
|
||||
if (write(ushared->spooler_signal_pipe[0], &sig, 1) != 1) {
|
||||
@@ -195,6 +244,47 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(use->receiver, "mules")) {
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (write(uwsgi.mules[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp(use->receiver, "mule", 4)) {
|
||||
i = atoi(use->receiver+4);
|
||||
if (i > uwsgi.mules_cnt) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else if (i == 0) {
|
||||
if (write(ushared->mule_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to a mule\n", sig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(uwsgi.mules[i-1].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(use->receiver, "farm", 4)) {
|
||||
i = atoi(use->receiver+4);
|
||||
if (i > uwsgi.farms_cnt || i <= 0) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else {
|
||||
if (write(uwsgi.farms[i-1].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// unregistered signal, sending it to all the workers
|
||||
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/* this is a skeleton to use libuwsgi in external projects */
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
int main(int argc, char **argv, char **environ) {
|
||||
|
||||
uwsgi_init(argc, argv, environ);
|
||||
}
|
||||
@@ -350,123 +350,6 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_set_counter32", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bK:snmp_set_counter64", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_set_gauge", &oid_num, &oid_val)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_community(PyObject * self, PyObject * args) {
|
||||
|
||||
char *snmp_community;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:snmp_set_community", &snmp_community)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(snmp_community) > 72) {
|
||||
uwsgi_log( "*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
|
||||
memcpy(uwsgi.shared->snmp_community, snmp_community, 72);
|
||||
}
|
||||
else {
|
||||
memcpy(uwsgi.shared->snmp_community, snmp_community, strlen(snmp_community) + 1);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
static PyMethodDef uwsgi_snmp_methods[] = {
|
||||
{"snmp_set_counter32", py_snmp_counter32, METH_VARARGS, ""},
|
||||
{"snmp_set_counter64", py_snmp_counter64, METH_VARARGS, ""},
|
||||
{"snmp_set_gauge", py_snmp_gauge, METH_VARARGS, ""},
|
||||
{"snmp_set_community", py_snmp_community, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
void snmp_init() {
|
||||
|
||||
PyMethodDef *uwsgi_function;
|
||||
|
||||
for (uwsgi_function = uwsgi_snmp_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
|
||||
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
|
||||
PyDict_SetItemString(uwsgi.embedded_dict, uwsgi_function->ml_name, func);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
uwsgi_log( "SNMP python functions initialized.\n");
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
#warning "*** SNMP support is disabled ***"
|
||||
#endif
|
||||
|
||||
@@ -474,7 +474,13 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *s
|
||||
sin_addr->sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
sin_addr->sin_addr.s_addr = inet_addr(socket_name);
|
||||
char *resolved = uwsgi_resolve_ip(socket_name);
|
||||
if (resolved) {
|
||||
sin_addr->sin_addr.s_addr = inet_addr(resolved);
|
||||
}
|
||||
else {
|
||||
sin_addr->sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
return sizeof(struct sockaddr_in);
|
||||
@@ -500,6 +506,17 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef IP_FREEBIND
|
||||
if (uwsgi.freebind) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi.reuse_port) {
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
@@ -738,6 +755,20 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
|
||||
|
||||
if (!name) return uwsgi_sock;
|
||||
|
||||
if (name[0] == '=') {
|
||||
int shared_socket = atoi(uwsgi_sock->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
struct uwsgi_socket *uss = uwsgi_get_shared_socket_by_num(shared_socket);
|
||||
if (!uss) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock->shared = 1;
|
||||
uwsgi_sock->from_shared = shared_socket;
|
||||
return uwsgi_sock;
|
||||
}
|
||||
}
|
||||
char *tcp_port = strchr(name, ':');
|
||||
if (tcp_port) {
|
||||
// INET socket, check for 0 port
|
||||
@@ -758,7 +789,25 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
|
||||
|
||||
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
|
||||
uwsgi_sock->name = uwsgi_concat3n(name, tcp_port-name, ":", 1, auto_port, strlen(auto_port));
|
||||
}
|
||||
}
|
||||
// is it fd 0 ?
|
||||
else if (tcp_port[1] == ':') {
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->family = AF_INET;
|
||||
uwsgi_sock->bound = 1;
|
||||
|
||||
socket_type_len = sizeof(struct sockaddr_in);
|
||||
|
||||
if (getsockname(0, (struct sockaddr *)&sin, &socket_type_len)) {
|
||||
uwsgi_error("getsockname()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
|
||||
char *auto_ip = inet_ntoa(sin.sin_addr);
|
||||
uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
|
||||
}
|
||||
}
|
||||
|
||||
return uwsgi_sock;
|
||||
@@ -790,7 +839,12 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock->name = uwsgi_concat2(usa.sa_un.sun_path+abstract, "");
|
||||
uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path+abstract, uwsgi_sock->fd);
|
||||
if (uwsgi.zerg) {
|
||||
uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path+abstract, uwsgi_sock->fd);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("uwsgi socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path+abstract, uwsgi_sock->fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!strcmp(usa.sa_un.sun_path+abstract, uwsgi_sock->name+abstract)) {
|
||||
@@ -825,7 +879,12 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
uwsgi_sock->family = AF_INET;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock->name = uwsgi_concat2(computed_addr, "");
|
||||
uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
|
||||
if (uwsgi.zerg) {
|
||||
uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("uwsgi socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
|
||||
}
|
||||
free(computed_addr);
|
||||
return;
|
||||
}
|
||||
@@ -912,6 +971,29 @@ int uwsgi_get_shared_socket_fd_by_num(int num) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_socket *uwsgi_get_shared_socket_by_num(int num) {
|
||||
|
||||
int counter = 0;
|
||||
|
||||
struct uwsgi_socket *found_sock = NULL, *uwsgi_sock = uwsgi.shared_sockets;
|
||||
|
||||
while(uwsgi_sock) {
|
||||
if (counter == num) {
|
||||
found_sock = uwsgi_sock;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (found_sock) {
|
||||
return found_sock;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_add_sockets_to_queue(int queue) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
@@ -9,43 +9,52 @@ static void spooler_scandir(char *);
|
||||
#endif
|
||||
void spooler_manage_task(char *, char *);
|
||||
|
||||
// fake function to allow waking the spooler
|
||||
void spooler_wakeup() {}
|
||||
|
||||
pid_t spooler_start() {
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
|
||||
// setup internal signalling system
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->spooler_signal_pipe)) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t pid = uwsgi_fork("uWSGI spooler");
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
}
|
||||
else if (pid == 0) {
|
||||
// USR1 will be used to wake up the spooler
|
||||
signal(SIGUSR1, spooler_wakeup);
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
// avoid race conditions !!!
|
||||
uwsgi.shared->spooler_pid = uwsgi.mypid;
|
||||
|
||||
uwsgi_fixup_fds(0, 0);
|
||||
uwsgi_close_all_sockets();
|
||||
if (uwsgi.master_process) {
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.signal_pipe[i][0] != -1) {
|
||||
close(uwsgi.signal_pipe[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
if (uwsgi.master_process) {
|
||||
close(uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uwsgi.spool_dir, pid);
|
||||
}
|
||||
|
||||
@@ -160,13 +169,20 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size, c
|
||||
|
||||
uwsgi_unlock(uwsgi.spooler_lock);
|
||||
|
||||
/* wake up the spooler ... (HACKY) */
|
||||
if (uwsgi.shared->spooler_pid > 0 ) {
|
||||
(void) kill(uwsgi.shared->spooler_pid, SIGUSR1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
clear:
|
||||
uwsgi_unlock(uwsgi.spooler_lock);
|
||||
uwsgi_error("write()");
|
||||
unlink(filename);
|
||||
if (unlink(filename)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -220,6 +236,8 @@ void spooler() {
|
||||
if (uwsgi.spooler_ordered) {
|
||||
#ifdef __linux__
|
||||
spooler_scandir(uwsgi.spool_dir);
|
||||
#else
|
||||
spooler_readdir(uwsgi.spool_dir);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
@@ -231,10 +249,8 @@ void spooler() {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
|
||||
uint8_t uwsgi_signal;
|
||||
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -333,7 +349,12 @@ void spooler_manage_task(char *dir, char *task) {
|
||||
if (!access(task, R_OK | W_OK)) {
|
||||
uwsgi_log("managing spool request %s ...\n", task);
|
||||
|
||||
#ifdef __sun__
|
||||
// lockf needs write permission
|
||||
spool_fd = open(task, O_RDWR);
|
||||
#else
|
||||
spool_fd = open(task, O_RDONLY);
|
||||
#endif
|
||||
if (spool_fd < 0) {
|
||||
uwsgi_error_open(task);
|
||||
return;
|
||||
@@ -382,16 +403,29 @@ void spooler_manage_task(char *dir, char *task) {
|
||||
|
||||
close(spool_fd);
|
||||
|
||||
if (uwsgi.spooler_chdir) {
|
||||
if (chdir(uwsgi.spooler_chdir)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
}
|
||||
|
||||
int callable_found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
if (uwsgi.p[i]->spooler) {
|
||||
time_t now = time(NULL);
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
if (body) {
|
||||
free(body);
|
||||
}
|
||||
if (ret == 0) continue;
|
||||
callable_found = 1;
|
||||
if (ret == -2) {
|
||||
|
||||
uwsgi_log("done with task/spool %s after %d seconds\n", task, time(NULL)-now);
|
||||
destroy_spool(dir, task);
|
||||
}
|
||||
@@ -399,6 +433,9 @@ void spooler_manage_task(char *dir, char *task) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!callable_found) {
|
||||
uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -416,7 +453,6 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("managing spool request...\n");
|
||||
i = spool_request(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;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
- case 1
|
||||
|
||||
single static app
|
||||
|
||||
- case 2
|
||||
|
||||
single static multiapp
|
||||
|
||||
- case 3
|
||||
|
||||
multi app static mountpoint
|
||||
|
||||
- case 4
|
||||
|
||||
dynamic apps with UWSGI_APPID
|
||||
|
||||
- case 5
|
||||
|
||||
dynamic apps with SCRIPT_NAME
|
||||
|
||||
- case 6
|
||||
|
||||
dynamic apps with vhost mode
|
||||
@@ -0,0 +1,22 @@
|
||||
from picasso import *
|
||||
|
||||
def home(req):
|
||||
if not req["session"].get("user"):
|
||||
return redirect("/login")
|
||||
return "<h1>Welcome back, %s!</h1>" % req["session"]["user"]
|
||||
|
||||
def login(req):
|
||||
return "<form method='post'><input type='submit' name='foo' value='login' /></form>"
|
||||
|
||||
def login_post(req):
|
||||
print req
|
||||
req["session"]["user"] = "James"
|
||||
return redirect("/")
|
||||
|
||||
routes = setup_routes(
|
||||
GET("/", home),
|
||||
GET("/login", login),
|
||||
POST("/login", login_post),
|
||||
routing.not_found("<h1>Not Found</h1>"))
|
||||
|
||||
app = setup_app(routes)
|
||||
@@ -0,0 +1,7 @@
|
||||
def app(req):
|
||||
print(req)
|
||||
ret = {"status": 200,
|
||||
"headers": {"content_type": "text/html", "foo":['bar0','bar1','bar2']},
|
||||
"body": "<h1>Hello!</h1>"}
|
||||
print(ret)
|
||||
return ret
|
||||
@@ -0,0 +1,48 @@
|
||||
# uwsgi --queue 10 --queue-store test.queue --master --module tests.queue --socket :3031
|
||||
|
||||
import uwsgi
|
||||
import os
|
||||
from flask import Flask,render_template,request,redirect,flash
|
||||
|
||||
app = Flask(__name__)
|
||||
app.debug = True
|
||||
app.secret_key = os.urandom(24)
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
|
||||
return render_template('queue.html', uwsgi=uwsgi)
|
||||
|
||||
@app.route('/push', methods=['POST'])
|
||||
def push_item():
|
||||
if uwsgi.queue_push(request.form['body']):
|
||||
flash('item enqueued')
|
||||
return redirect('/')
|
||||
else:
|
||||
flash('unable to enqueue item')
|
||||
return render_template('queue.html', uwsgi=uwsgi)
|
||||
|
||||
@app.route('/get', methods=['POST'])
|
||||
def get_item():
|
||||
flash( "slot %s value = %s" % (request.form['slot'], uwsgi.queue_get( int(request.form['slot']) )))
|
||||
return redirect('/')
|
||||
|
||||
@app.route('/pop', methods=['POST'])
|
||||
def pop_item():
|
||||
flash( "popped value = %s" % uwsgi.queue_pop() )
|
||||
return redirect('/')
|
||||
|
||||
@app.route('/pull', methods=['POST'])
|
||||
def pull_item():
|
||||
flash( "pulled value = %s" % uwsgi.queue_pull() )
|
||||
return redirect('/')
|
||||
|
||||
|
||||
@app.route('/set', methods=['POST'])
|
||||
def set_item():
|
||||
if uwsgi.queue_set(int(request.form['pos']), request.form['body']):
|
||||
flash('item set')
|
||||
return redirect('/')
|
||||
else:
|
||||
flash('unable to set item')
|
||||
return render_template('queue.html', uwsgi=uwsgi)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user