Compare commits

...
80 Commits
Author SHA1 Message Date
Unbit 4644578276 file monitor support for OpenBSD,NetBSD,DragonFly 2013-07-21 16:38:48 +02:00
Unbit f1d450c12f updated gemspec 2013-07-21 08:08:48 +02:00
Roberto De Ioris 6624f75ec7 added kqueue support to the fsmon interface 2013-07-21 07:40:47 +02:00
Unbit 8941505ea0 inotify-based fsmon implementation 2013-07-21 07:34:56 +02:00
Unbit 18b177db25 added fsmon skel 2013-07-20 00:07:40 +02:00
Unbit 27421f3642 atexit hook is not needed in the xmldir router 2013-07-19 19:27:22 +02:00
unbit 30f9479e85 Merge pull request #343 from gber/master
Improvements to router_xmldir
2013-07-20 08:40:39 -07:00
Guido Berhoerster a9f7631ab4 Add example configuration and XSL stylesheet 2013-07-20 00:35:11 +02:00
Guido Berhoerster cb8519510f Fix style in router_xmldir 2013-07-20 00:35:11 +02:00
Guido Berhoerster f7881bfb78 Improve router_xmldir output
Root element is now <index> instead of <tree> since the output is not a tree.
Add a path attribute to <index> which contains the content of PATH_INFO.
Only show files and directories and add attributes for their mtime and size.
2013-07-20 00:35:11 +02:00
Guido Berhoerster 4cf4c75d5d Convert filenames from codeset of the current locale to UTF-8 encoding 2013-07-20 00:35:11 +02:00
Guido Berhoerster 91bcbc77b3 Include hidden files in router_xmldir directory listing
Hidden files can be filtered out through a XSL stylesheet if needed.
2013-07-20 00:35:11 +02:00
Guido Berhoerster b1db4d35c3 Return meaningful responses from router_xmldir in case of errors 2013-07-20 00:35:11 +02:00
Guido Berhoerster 060462b849 Fix portability issue in the router_xmldir plugin
Use the portable alphasort(3) insead of the versionsort(3) GNU extension.
2013-07-20 00:35:11 +02:00
Unbit 0e08c0211c Unbit-specific workaround for broken robust mutexes 2013-07-19 13:21:34 +02:00
Unbit e69cc2bcd5 fixed python modifier management 2013-07-18 16:43:37 +02:00
Unbit 996af7d46c fixed hex2num 2013-07-17 20:42:14 +02:00
Unbit e8e66f15da fixed check_hex 2013-07-17 20:41:07 +02:00
Unbit cd09b4a55d more user-friendly error message for undeletable unix sockets 2013-07-17 16:30:25 +02:00
Unbit f4a1d76396 try to fix auto chunking in http router 2013-07-17 16:21:13 +02:00
Unbit ab8cc168e5 fixed #339 2013-07-17 08:38:32 +02:00
Unbit 5e43ef6fae rbthreads improvements 2013-07-17 08:36:49 +02:00
Roberto De Ioris caa3614f78 rbthreads osx fixes 2013-07-17 07:22:58 +02:00
Unbit a81ca89ae9 use ruby2 profile when available 2013-07-17 07:14:45 +02:00
Unbit 5861705cd6 preliminary rbthreads support 2013-07-17 07:08:47 +02:00
Unbit 4e68dacad3 microoptimzation for --reload-on-fd 2013-07-16 10:22:06 +02:00
Unbit 4f8f15a3b6 fixed --safe-fd 2013-07-16 09:12:46 +02:00
Unbit aa6b86fbdf force the emperor to honour --safe-fd 2013-07-16 08:50:51 +02:00
Unbit 7a18ff48ba added --reload-on-fd and --brutal-reload-on-fd 2013-07-16 08:27:56 +02:00
Unbit e354de9f5e fixed sendfile and fastfile headers management 2013-07-15 10:49:28 +02:00
Unbit 10073bc4ae jsp prototype working 2013-07-15 10:06:33 +02:00
Unbit 6fd051b248 more servlet definitions 2013-07-15 07:20:43 +02:00
Unbit 1cf034881e more servlet definitions 2013-07-15 07:20:08 +02:00
Unbit 1393281c74 added prototype servlet plugin 2013-07-14 09:15:12 +02:00
Unbit edf95a4b0a added fastfile routing action 2013-07-13 17:37:26 +02:00
Unbit 8887f83f7f use the right sendfile abstraction 2013-07-13 17:26:43 +02:00
Unbit 7513d80440 added sendfile routing action 2013-07-13 17:21:13 +02:00
Unbit 67289b7cf1 added setdocroot 2013-07-13 11:26:24 +02:00
Unbit a88f478fac support for rb_reserved_fd_p 2013-07-13 05:55:40 +02:00
Roberto De Ioris d385661a93 removed typo on osx 2013-07-12 20:06:48 +02:00
Unbit e8895ba773 better thunder_lock usage on unbit 2013-07-11 09:39:30 +02:00
Unbit 5a23a8d457 better computation of listen queue load 2013-07-11 08:45:46 +02:00
Roberto De Ioris e01a3d8bd2 second attempt of Tiger support 2013-07-10 21:34:28 +02:00
Roberto De Ioris b270bd24d7 first attempt of Tiger support 2013-07-10 21:30:36 +02:00
unbit ab989ebf16 Merge pull request #336 from xrmx/debian-fixes
A couple of patches from debian packaging
2013-07-09 08:34:31 -07:00
Riccardo Magliocchetti 7c31b6657f uwsgiconfig: force no-format-security too
It may happen that a plugin is using -Wformat -Wformat-security so need to remove
both otherwise as seen in emperor_pg plugin:

 cc1: error: -Wformat-security ignored without -Wformat [-Werror=format-security]

Based on a debian patch of Janos Guljas.
2013-07-09 09:58:35 +02:00
Riccardo Magliocchetti ba7d322aaf plugins: try harder to compile alarm_speech on linux
Using GNUStep. Modified from a debian patch of Janos Guljas.
2013-07-09 09:57:15 +02:00
Unbit 537187b7f8 added daemontools envdir support 2013-07-08 19:15:22 +02:00
Unbit d22a7c7223 added UWSGI_DEBUG_BUFFER to catch bugs related to uwsgi_buffer structures 2013-07-08 17:59:56 +02:00
Unbit c9f986fa59 improved v8 build 2013-07-08 13:27:02 +02:00
Unbit d7388ca5e7 fixed pypy rpc 2013-07-08 11:34:09 +02:00
Unbit df5ad62ebf improved http proxy internal router 2013-07-08 10:50:03 +02:00
Unbit 41dab14020 improved chunked api 2013-07-07 10:14:06 +02:00
Unbit 744e166e9d Revert "uwsgi.is_locked raises an exception"
This reverts commit 5a3b93f763.
2013-07-03 15:41:57 +02:00
Unbit 5a3b93f763 uwsgi.is_locked raises an exception 2013-07-03 14:53:55 +02:00
Unbit 656de924eb fixed latin1 encoding with python3 2013-07-02 16:19:12 +02:00
Unbit 703444dd40 added v8 build profile 2013-07-01 17:21:51 +02:00
Roberto De Ioris ff8ca18e8f added --emperor-nofollow 2013-06-29 21:57:10 +02:00
unbit 1f90be1ae1 Merge pull request #328 from anaconda/py-spooler-pass-args
[Python] Added option to pass arguments to spooled function
2013-06-29 03:50:29 -07:00
unbit ee95c2eb0b Merge pull request #329 from anaconda/master
Adding my name to CONTRIBUTORS, as requested in #327.
2013-06-29 03:48:36 -07:00
anaconda 6606f3f0dc Implement pass_arguments parameter for spool* decorators.
Let's say you have a heavily used function or method.  Until now you
had to:
a) change all calls, the spooler dictionary only accepted strings;
b) change the code of your function to read its parameters from a
dictionary and convert them from str.

From now on you just need to add `@spool[forever](pass_arguments=True)` to your
function.
2013-06-25 23:54:07 +02:00
anaconda bcd97f7247 Adding my name to CONTRIBUTORS, as requested in #327. 2013-06-25 23:38:46 +02:00
unbit 271e7f8f4c Merge pull request #327 from anaconda/fix-spooler-ordered
Fix --spooler-ordered, was actually reverse ordered.
2013-06-25 09:31:23 -07:00
Unbit e78d8594a8 avoid mess on 32bit 2013-06-25 18:28:30 +02:00
Unbit 659360b366 fixed php status line 2013-06-25 18:23:33 +02:00
anaconda 6c1c86ea79 --spooler-ordered was actually reverse ordered. 2013-06-25 16:58:22 +02:00
Unbit 5da36b7199 1.9.14 development cycle starts 2013-06-25 11:52:34 +02:00
Unbit 294452eef7 added support for retry in http router 2013-06-25 07:56:01 +02:00
Unbit 3ac0e28d9c added Natanael Copa to CONTRIBUTORS 2013-06-24 16:59:58 +02:00
Unbit ce22b69a2f completed uclibc support 2013-06-24 14:55:59 +00:00
unbit 8b31a998ed Merge pull request #325 from ncopa/master
Support for Lua 5.2
2013-06-24 07:44:24 -07:00
Natanael Copa dad97bc104 add support for lua5.2
The default is still lua5.1 but 5.2 can be picked at compile time
but setting UWSGICONFIG_LUAPC=lua5.2
2013-06-24 14:35:31 +00:00
Natanael Copa e20e43eee0 add support for pkg-config for lua
Allow select what pkg-config module to use with UWSGICONFIG_LUAPC but
let the old LUAINC/LUALIB and LUALIBPATH override the pkg-config
for backwards compatibility.
2013-06-24 14:35:31 +00:00
Unbit aafd4e757d another uclibc fix 2013-06-24 16:15:17 +02:00
Unbit 575fc26bd7 try to support uclibc correctly 2013-06-24 16:01:43 +02:00
Unbit 5743eb2575 refactored lua build 2013-06-24 15:05:34 +02:00
Unbit 31972ded93 moved opt login in core/config.c 2013-06-23 08:18:33 +02:00
Unbit 28321a0f94 more python api static functions 2013-06-23 07:59:36 +02:00
Unbit 406dfbc770 added setscheme routing action 2013-06-23 07:22:09 +02:00
Unbit c59595cefc updated gemspec 2013-06-22 12:10:40 +02:00
62 changed files with 3037 additions and 611 deletions
+2
View File
@@ -22,3 +22,5 @@ Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
Natanael Copa
Roberto Leandrini
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack,rbthreads,fiber
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = jvm,servlet
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = v8
inherit = base
+6
View File
@@ -270,6 +270,12 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
#ifdef UWSGI_DEBUG_BUFFER
if (ub->freed) {
uwsgi_log("[BUG] buffer at %p already destroyed !!!\n", ub);
}
ub->freed = 1;
#endif
if (ub->buf)
free(ub->buf);
free(ub);
+21
View File
@@ -498,6 +498,27 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
char *uwsgi_cache_get4(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *hits) {
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
if (index) {
struct uwsgi_cache_item *uci = cache_item(index);
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uci->valsize;
if (hits)
*hits = uci->hits;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
return NULL;
}
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
+12 -9
View File
@@ -84,7 +84,7 @@ static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
char *ret;
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
@@ -96,14 +96,18 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
return wsgi_req->chunked_input_buf->buf;
}
if (wsgi_req->chunked_input_decapitate > 0) {
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
wsgi_req->chunked_input_decapitate = 0;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
@@ -122,6 +126,7 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
wsgi_req->chunked_input_need++;
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
@@ -139,19 +144,17 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
return ret;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
return wsgi_req->chunked_input_buf->buf;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
wsgi_req->chunked_input_parser_status = 0;
return ret;
return wsgi_req->chunked_input_buf->buf;
}
}
+430
View File
@@ -31,3 +31,433 @@ struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(
return uc;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
uopt++;
}
return count;
}
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
op++;
}
return NULL;
}
void add_exported_option(char *key, char *value, int configured) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
}
+68 -21
View File
@@ -234,11 +234,18 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(de->d_name, &st))
continue;
if (!S_ISLNK(st.st_mode) && !S_ISREG(st.st_mode))
continue;
}
else {
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(de->d_name);
@@ -294,16 +301,30 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -328,11 +349,18 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
continue;
}
else {
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(g.gl_pathv[i]);
@@ -389,16 +417,30 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -867,11 +909,15 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
#ifdef UNSETENV_VOID
unsetenv(oe);
#else
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
#endif
free(oe);
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
@@ -992,6 +1038,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// close all of the unneded fd
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
+213
View File
@@ -0,0 +1,213 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
#include <sys/inotify.h>
#endif
#endif
void uwsgi_fsmon_setup() {
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
char *copy = uwsgi_str(usl->value);
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
goto next;
}
*space = 0;
usl->value = copy;
usl->len = strlen(copy);
usl->custom_ptr = space+1;
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
next:
usl = usl->next;
}
}
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
static int inotify_fd = -1;
if (inotify_fd == -1) {
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
return -1;
}
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
return -1;
}
}
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
if (wd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
return -1;
}
usl->custom = inotify_fd;
usl->custom2 = wd;
return 0;
#endif
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
struct kevent kev;
int fd = open(usl->value, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(usl->value);
uwsgi_error("uwsgi_register_fsmon()/open()");
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("uwsgi_register_fsmon()/kevent()");
return -1;
}
usl->custom = fd;
usl->custom2 = fd;
return 0;
#endif
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
return 1;
}
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
int found_fd = -1;
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
found:
if (found_fd == -1) return NULL;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
unsigned int isize = 0;
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
return 0;
}
if (isize == 0) return NULL;
struct inotify_event *ie = uwsgi_malloc(isize);
// read from the inotify descriptor
ssize_t len = read(found_fd, ie, isize);
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
found_fd = ie->wd;
free(ie);
#endif
#endif
// search for the item id and print it
usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_brutal_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return usl;
}
usl = usl->next;
}
return NULL;
}
int uwsgi_fsmon_event(int interesting_fd) {
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
if (!usl) return 0;
if (usl == uwsgi.fs_reload) {
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 1;
}
if (usl == uwsgi.fs_brutal_reload) {
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 1;
}
// fallback to signal
uwsgi_route_signal(atoi(usl->custom_ptr));
return 1;
}
+6
View File
@@ -449,6 +449,12 @@ void sanitize_args() {
exit(1);
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
uwsgi.use_thunder_lock = 1;
}
#endif
}
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
+34
View File
@@ -610,6 +610,32 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
#ifdef UNBIT
/*
Unbit-specific workaround for robust-mutexes
*/
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
}
return NULL;
}
void uwsgi_robust_mutexes_watchdog() {
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 32K should be more than enough...
pthread_attr_setstacksize(&attr, 32 * 1024);
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
exit(1);
}
}
#endif
void uwsgi_setup_locking() {
@@ -689,6 +715,14 @@ ready:
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
#ifdef UNBIT
// we have a serious bug on Unbit (and very probably on older libc)
// when all of the workers die in the same moment the pthread robust mutes is left
// in inconsistent state and we have no way to recover
// we span a thread in the master constantly ensuring the lock is ok
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
uwsgi_robust_mutexes_watchdog();
#endif
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
+12
View File
@@ -375,6 +375,8 @@ int master_loop(char **argv, char **environ) {
uwsgi_start_legions();
#endif
uwsgi_add_reload_fds();
uwsgi_cache_start_sweepers();
uwsgi_cache_start_sync_servers();
@@ -498,6 +500,9 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_check_touches(uwsgi.touch_signal);
// fsmon
uwsgi_fsmon_setup();
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
@@ -698,6 +703,7 @@ int master_loop(char **argv, char **environ) {
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
int tmp_queue = 0;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
@@ -709,8 +715,14 @@ int master_loop(char **argv, char **environ) {
}
#endif
#endif
if (uwsgi_sock->queue > tmp_queue) {
tmp_queue = uwsgi_sock->queue;
}
uwsgi_sock = uwsgi_sock->next;
}
// fix queue size on multiple sockets
uwsgi.shared->load = tmp_queue;
// check if some worker has to die (harakiri, evil checks...)
uwsgi_master_check_workers_deadline();
+73
View File
@@ -42,6 +42,79 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
if (uwsgi_fsmon_event(interesting_fd)) {
return 0;
}
// reload on fd
if (uwsgi.reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 0;
}
usl = usl->next;
}
}
// brutal reload on fd
if (uwsgi.brutal_reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[brutal-reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 0;
}
usl = usl->next;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
+27
View File
@@ -1458,3 +1458,30 @@ int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int
}
static void add_reload_fds(struct uwsgi_string_list *list, char *type) {
struct uwsgi_string_list *usl = list;
while(usl) {
char *strc = uwsgi_str(usl->value);
char *space = strchr(strc, ' ');
if (space) {
*space = 0;
usl->custom_ptr = space+1;
}
char *colon = strchr(strc, ':');
if (colon) {
*colon = 0;
usl->custom2 = strtoul(colon+1, NULL, 10);
}
usl->custom = strtoul(strc, NULL, 10);
if (!usl->custom2) usl->custom2 = 1;
event_queue_add_fd_read(uwsgi.master_queue, usl->custom);
uwsgi_add_safe_fd(usl->custom);
uwsgi_log("added %s reload monitor for fd %d (read size: %llu)\n", type, (int) usl->custom, usl->custom2);
usl = usl->next;
}
}
void uwsgi_add_reload_fds() {
add_reload_fds(uwsgi.reload_on_fd, "graceful");
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
}
+1 -1
View File
@@ -345,7 +345,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t len = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
// transfer finished
+12 -5
View File
@@ -24,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
}
#endif
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -33,7 +33,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.p[i]->alias) {
@@ -41,7 +41,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
@@ -53,7 +53,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.gp[i]->alias) {
@@ -61,14 +61,21 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
return NULL;
}
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
if (up) return 1;
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
+51
View File
@@ -936,6 +936,30 @@ static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
ur->data_len = strlen(arg);
return 0;
}
// setdocroot route
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "DOCUMENT_ROOT", 13, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->document_root = ptr;
wsgi_req->document_root_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setdocroot(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setdocroot_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setpathinfo route
static int uwsgi_router_setpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -961,6 +985,31 @@ static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
return 0;
}
// setscheme route
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_SCHEME", 12, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->scheme = ptr;
wsgi_req->scheme_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setscheme_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setuser route
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -1593,6 +1642,8 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
+2 -1
View File
@@ -10,7 +10,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t sf_len = len;
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
@@ -71,5 +71,6 @@ int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, siz
return -1;
}
}
return 0;
}
+1 -1
View File
@@ -74,7 +74,7 @@ int bind_to_unix_dgram(char *socket_name) {
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("unlink()");
uwsgi_error("error removing unix socket, unlink()");
}
uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
+15 -4
View File
@@ -241,6 +241,16 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
}
if (at > 0) {
#ifdef __UCLIBC__
struct timespec ts[2];
ts[0].tv_sec = at;
ts[0].tv_nsec = 0;
ts[1].tv_sec = at;
ts[1].tv_nsec = 0;
if (futimens(fd, ts)) {
uwsgi_error("futimens()");
}
#else
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_usec = 0;
@@ -253,6 +263,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
uwsgi_error("futimes()");
}
#endif
}
// here the file will be unlocked too
@@ -380,7 +391,7 @@ void spooler(struct uwsgi_spooler *uspool) {
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
int n, i;
if (!dir)
dir = uspool->dir;
@@ -391,9 +402,9 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
return;
}
while (n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
for (i = 0; i < n; i++) {
spooler_manage_task(uspool, dir, tasklist[i]->d_name);
free(tasklist[i]);
}
free(tasklist);
+41
View File
@@ -1,5 +1,46 @@
#include <uwsgi.h>
char *uwsgi_str_split_nget(char *str, size_t len, char what, size_t pos, size_t *rlen) {
size_t i;
size_t current = 0;
char *choosen = str;
size_t choosen_len = 0;
*rlen = 0;
for(i=0;i<len;i++) {
if (!choosen) choosen = str + i;
if (str[i] == what) {
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
current++;
choosen = NULL;
choosen_len = 0;
}
else {
choosen_len ++;
}
}
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
return NULL;
}
size_t uwsgi_str_occurence(char *str, size_t len, char what) {
size_t count = 0;
size_t i;
for(i=0;i<len;i++) {
if (str[i] == what) count++;
}
return count;
}
// check if a string_list contains an item
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
struct uwsgi_string_list *usl = list;
+113 -432
View File
@@ -1241,34 +1241,6 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
return -1;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
uopt++;
}
return count;
}
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
op++;
}
return NULL;
}
char *uwsgi_substitute(char *src, char *what, char *with) {
int count = 0;
@@ -1347,408 +1319,6 @@ int uwsgi_is_link(char *filename) {
return 0;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
void add_exported_option(char *key, char *value, int configured) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
}
void *uwsgi_malloc(size_t size) {
char *ptr = malloc(size);
@@ -1987,6 +1557,9 @@ static char hex2num(char *str) {
else if (str[0] >= 'A' && str[0] <= 'F') {
val += (str[0] & 0x0F) + 9;
}
else if (str[0] >= 'a' && str[0] <= 'f') {
val += (str[0] & 0x0F) + 9;
}
else {
return 0;
}
@@ -1999,6 +1572,9 @@ static char hex2num(char *str) {
else if (str[1] >= 'A' && str[1] <= 'F') {
val += (str[1] & 0x0F) + 9;
}
else if (str[1] >= 'a' && str[1] <= 'f') {
val += (str[1] & 0x0F) + 9;
}
else {
return 0;
}
@@ -2597,11 +2173,13 @@ char *uwsgi_get_binary_path(char *argvzero) {
uint32_t len = uwsgi.page_size;
if (_NSGetExecutablePath(buf, &len) == 0) {
// return only absolute path
#ifndef OLD_REALPATH
char *newbuf = realpath(buf, NULL);
if (newbuf) {
free(buf);
return newbuf;
}
#endif
}
free(buf);
#elif defined(__sun__)
@@ -3263,10 +2841,14 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
}
char *uwsgi_chomp(char *str) {
size_t i;
for (i = 0; i < strlen(str); i++) {
ssize_t slen = (ssize_t) strlen(str), i ;
if (!slen) return str;
slen--;
for (i = slen; i >= 0; i--) {
if (str[i] == '\r' || str[i] == '\n') {
str[i] = 0;
}
else {
return str;
}
}
@@ -3274,6 +2856,24 @@ char *uwsgi_chomp(char *str) {
return str;
}
char *uwsgi_chomp2(char *str) {
ssize_t slen = (ssize_t) strlen(str), i ;
if (!slen) return str;
slen--;
for (i = slen; i >= 0; i--) {
if (str[i] == '\r' || str[i] == '\n' || str[i] == '\t' || str[i] == ' ') {
str[i] = 0;
}
else {
return str;
}
}
return str;
}
int uwsgi_tmpfd() {
char *tmpdir = getenv("TMPDIR");
if (!tmpdir) {
@@ -4055,3 +3655,84 @@ void create_msg_pipe(int *fd, int bufsize) {
char *uwsgi_binary_path() {
return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
}
void uwsgi_envdir(char *edir) {
DIR *d = opendir(edir);
if (!d) {
uwsgi_error("[uwsgi-envdir] opendir()");
exit(1);
}
struct dirent *de;
while ((de = readdir(d)) != NULL) {
// skip hidden files
if (de->d_name[0] == '.') continue;
struct stat st;
char *filename = uwsgi_concat3(edir, "/", de->d_name);
if (stat(filename, &st)) {
uwsgi_log("[uwsgi-envdir] error stating %s\n", filename);
uwsgi_error("[uwsgi-envdir] stat()");
exit(1);
}
if (!S_ISREG(st.st_mode)) {
free(filename);
continue;
}
// unsetenv
if (st.st_size == 0) {
#ifdef UNSETENV_VOID
unsetenv(de->d_name);
#else
if (unsetenv(de->d_name)) {
uwsgi_log("[uwsgi-envdir] unable to unset %s\n", de->d_name);
uwsgi_error("[uwsgi-envdir] unsetenv");
exit(1);
}
#endif
free(filename);
continue;
}
// read the content of the file
size_t size = 0;
char *content = uwsgi_open_and_read(filename, &size, 1, NULL);
if (!content) {
uwsgi_log("[uwsgi-envdir] unable to open %s\n", filename);
uwsgi_error_open(filename);
exit(1);
}
free(filename);
// HACK, envdir states we only need to strip the end of the string ....
uwsgi_chomp2(content);
// ... and substitute 0 with \n
size_t slen = strlen(content);
size_t i;
for(i=0;i<slen;i++) {
if (content[i] == 0) {
content[i] = '\n';
}
}
if (setenv(de->d_name, content, 1)) {
uwsgi_log("[uwsgi-envdir] unable to set %s\n", de->d_name);
uwsgi_error("[uwsgi-envdir] setenv");
exit(1);
}
free(content);
}
}
void uwsgi_envdirs(struct uwsgi_string_list *envdirs) {
struct uwsgi_string_list *usl = envdirs;
while(usl) {
uwsgi_envdir(usl->value);
usl = usl->next;
}
}
void uwsgi_opt_envdir(char *opt, char *value, void *foobar) {
uwsgi_envdir(value);
}
+21 -3
View File
@@ -171,6 +171,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
@@ -221,8 +222,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
@@ -335,6 +336,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
#ifdef __linux__
#ifdef MADV_MERGEABLE
{"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
@@ -351,6 +355,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
{"fs-reload", required_argument, 0, "graceful reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_reload, UWSGI_OPT_MASTER},
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
@@ -641,6 +650,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
{"early-envdir", required_argument, 0, "load a daemontools compatible envdir ASAP", uwsgi_opt_envdir, NULL, UWSGI_OPT_IMMEDIATE},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
@@ -1493,7 +1504,7 @@ void uwsgi_plugins_atexit(void) {
void uwsgi_backtrace(int depth) {
#if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
#if defined(__linux__) || (defined(__APPLE__) && !defined(NO_EXECINFO)) || defined(UWSGI_HAS_EXECINFO)
#include <execinfo.h>
@@ -1894,6 +1905,9 @@ int main(int argc, char *argv[], char *envp[]) {
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
// manage envdirs ASAP
uwsgi_envdirs(uwsgi.envdirs);
// --get management
struct uwsgi_string_list *get_list = uwsgi.get_list;
while(get_list) {
@@ -3662,9 +3676,13 @@ void uwsgi_opt_set_env(char *opt, char *value, void *none) {
}
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
#ifdef UNSETENV_VOID
unsetenv(value);
#else
if (unsetenv(value)) {
uwsgi_error("unsetenv()");
}
#endif
}
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:html="http://www.w3.org/TR/html4/"
xmlns="http://www.w3.org/TR/html4/"
exclude-result-prefixes="html">
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Strict//EN"
indent="yes" doctype-system="http://www.w3.org/TR/html4/strict.dtd"
encoding="UTF-8" />
<xsl:template name="format-date">
<xsl:param name="date" />
<xsl:value-of select="substring-before($date, 'T')" />
<xsl:text> </xsl:text>
<xsl:value-of select="substring-after($date, 'T')" />
</xsl:template>
<xsl:template match="index">
<html>
<head>
<xsl:choose>
<xsl:when test="$stylesheet">
<link rel="stylesheet" type="text/css" media="all" href="{$stylesheet}" />
</xsl:when>
<xsl:otherwise>
<style type="text/css">
html {
color: #000000;
background-color: #fefefe;
font-family: sans-serif;
}
h1 {
font-size: 1.5em;
font-weight: bold;
margin: .67em 0;
}
th {
text-align: left;
}
td {
font-family: mono;
}
td, th {
padding: 0 1em;
}
td.size {
text-align: right;
}
:link, :visited {
text-decoration: none;
}
:link {
color: #000099;
}
:visited {
color: #6600cc;
}
:link:hover,
:visited:hover {
text-decoration: underline;
}
:link:focus,
:visited:focus {
text-decoration: underline;
}
:link:active,
:visited:active {
text-decoration: underline;
}
</style>
</xsl:otherwise>
</xsl:choose>
<title>Index of <xsl:value-of select="@path" /></title>
</head>
<body>
<h1>Index of <xsl:value-of select="@path" /></h1>
<table>
<tr>
<th class="name">Name</th>
<th class="mtime">Last Modified</th>
<th class="size">Size</th>
</tr>
<tr>
<td class="name" colspan="3"><a href=".." title="Parent">Parent directory</a></td>
</tr>
<xsl:apply-templates select="directory" />
<xsl:apply-templates select="file" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="directory">
<tr class="directory">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
<xsl:template match="file">
<tr class="file">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:value-of select="." />
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
+17
View File
@@ -0,0 +1,17 @@
[uwsgi]
plugin = 0:notfound, router_xmldir, xslt
http-socket = :8080
docroot = .
check-static = %(docroot)
route-if = isdir:%(docroot)/${PATH_INFO} goto:index
route-run = last:
route-label = index
; uncomment to link CSS stylesheet /css/default.css
;route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=/css/default.css,content_type=text/html
; use embedded CSS
route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=,content_type=text/html
route-run = xmldir:%(docroot)/${PATH_INFO}
+6 -1
View File
@@ -7,7 +7,12 @@ Net::HTTP.start("uwsgi.it") do |http|
end
end
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
major,minor = RUBY_VERSION.split('.')
if major.to_i >= 2 or (major.to_i == 1 and minor.to_i >= 9)
system("bash install.sh ruby2 #{Dir.pwd}/uwsgi.ruby")
else
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
end
open("Makefile", "w") do |file|
file.write("all:\n")
+11 -2
View File
@@ -1,6 +1,15 @@
import os
NAME='alarm_speech'
CFLAGS = []
uwsgi_os = os.uname()[0]
LDFLAGS = []
LIBS = ['-framework appkit']
if uwsgi_os == "Darwin":
CFLAGS = []
LIBS = ['-framework appkit']
else:
CFLAGS = ['-I /usr/include/GNUstep']
LIBS = []
GCC_LIST = ['alarm_speech.m']
+1 -1
View File
@@ -10,7 +10,7 @@
*/
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
+17 -2
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include "cr.h"
@@ -9,13 +9,28 @@ int uwsgi_cr_map_use_void(struct uwsgi_corerouter *ucr, struct corerouter_peer *
}
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
uint64_t hits = 0;
uwsgi_rlock(ucr->cache->lock);
peer->instance_address = uwsgi_cache_get2(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len);
char *value = uwsgi_cache_get4(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len, &hits);
if (!value) goto end;
peer->tmp_socket_name = uwsgi_concat2n(value, peer->instance_address_len, "", 0);
size_t nodes = uwsgi_str_occurence(peer->tmp_socket_name, peer->instance_address_len, '|');
if (nodes > 0) {
size_t choosen_node = hits % (nodes+1);
size_t choosen_node_len = 0;
peer->instance_address = uwsgi_str_split_nget(peer->tmp_socket_name, peer->instance_address_len, '|', choosen_node, &choosen_node_len);
if (!peer->instance_address) goto end;
peer->instance_address_len = choosen_node_len;
}
else {
peer->instance_address = peer->tmp_socket_name;
}
char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
if (cs_mod) {
peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
peer->instance_address_len = (cs_mod - peer->instance_address);
}
end:
uwsgi_rwunlock(ucr->cache->lock);
return 0;
}
+7 -2
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
extern struct uwsgi_plugin rack_plugin;
static struct uwsgi_plugin *rack_plugin;
struct ufib {
int enabled;
@@ -53,7 +53,7 @@ static void fiber_schedule_to_req() {
}
if (error) {
rack_plugin.exception_log(NULL);
rack_plugin->exception_log(NULL);
rb_gc_unregister_address(&ufiber.fib[id]);
}
@@ -72,6 +72,11 @@ static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
}
static int fiber_init() {
rack_plugin = uwsgi_plugin_get("rack");
if (!rack_plugin) {
uwsgi_log("[ruby-fiber] rack plugin is not loaded !!!\n");
exit(1);
}
return 0;
}
+30 -1
View File
@@ -430,6 +430,9 @@ ssize_t hr_instance_connected(struct corerouter_peer* peer) {
cr_peer_connected(peer, "hr_instance_connected()");
// we are connected, we cannot retry anymore
peer->can_retry = 0;
// prepare for write
peer->out_pos = 0;
@@ -566,8 +569,10 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
}
#endif
else if (hr->force_chunked) {
peer->in->limit = 0;
if (uwsgi_buffer_insert_chunked(peer->in, 0, len)) return -1;
if (uwsgi_buffer_append(peer->in, "\r\n", 2)) return -1;
peer->in->len = UMIN(peer->in->len, UMAX16);
}
}
@@ -705,7 +710,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
hr->raw_body = 1;
}
new_peer->can_retry = 1;
cr_connect(new_peer, hr_instance_connected);
break;
}
@@ -775,7 +780,31 @@ ssize_t hr_recv_stud4(struct corerouter_peer * main_peer) {
}
// retry connection to the backend
static int hr_retry(struct corerouter_peer *peer) {
struct uwsgi_corerouter *ucr = peer->session->corerouter;
if (peer->instance_address_len > 0) goto retry;
if (ucr->mapper(ucr, peer)) {
return -1;
}
if (peer->instance_address_len == 0) {
return -1;
}
retry:
// start async connect (again)
cr_connect(peer, hr_instance_connected);
return 0;
}
int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
// set the retry hook
cs->retry = hr_retry;
struct http_session *hr = (struct http_session *) cs;
// set the modifier1
cs->main_peer->modifier1 = uhttp.modifier1;
+2
View File
@@ -568,6 +568,8 @@ static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
new_peer->can_retry = 1;
cr_connect(new_peer, hr_instance_connected);
return 1;
+8 -3
View File
@@ -4,6 +4,11 @@
#include <lualib.h>
#include <lauxlib.h>
#if LUA_VERSION_NUM < 502
# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
# define lua_rawlen lua_objlen
#endif
extern struct uwsgi_server uwsgi;
struct uwsgi_lua {
@@ -347,7 +352,7 @@ static int uwsgi_api_unlock(lua_State *L) {
return 0;
}
static const luaL_reg uwsgi_api[] = {
static const luaL_Reg uwsgi_api[] = {
{"log", uwsgi_api_log},
{"connection_fd", uwsgi_api_req_fd},
@@ -411,7 +416,7 @@ static void uwsgi_lua_app() {
for(i=0;i<uwsgi.cores;i++) {
ulua.L[i] = luaL_newstate();
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
luaL_newlib(ulua.L[i], uwsgi_api);
lua_pushstring(ulua.L[i], UWSGI_VERSION);
lua_setfield(ulua.L[i], -2, "version");
@@ -711,7 +716,7 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
static void uwsgi_lua_configurator_array(lua_State *L) {
int i;
int n = luaL_getn(L, -3);
int n = lua_rawlen(L, -3);
for(i=1;i<=n;i++) {
lua_rawgeti(L, 1, i);
+26 -15
View File
@@ -1,22 +1,33 @@
import os,sys
try:
LUALIB = os.environ['UWSGICONFIG_LUALIB']
except:
LUALIB = 'lua5.1'
LUAINC = os.environ.get('UWSGICONFIG_LUAINC')
LUALIB = os.environ.get('UWSGICONFIG_LUALIB')
LUALIBPATH = os.environ.get('UWSGICONFIG_LUALIBPATH')
LUAPC = os.environ.get('UWSGICONFIG_LUAPC', 'lua5.1')
try:
LUAINC = os.environ['UWSGICONFIG_LUAINC']
except:
LUAINC = '/usr/include/lua5.1'
# we LUAINC/LUALIB/LUALIBPATH override the LUAPC for backwards compat
if LUAINC:
CFLAGS = ['-I%s' % LUAINC]
else:
try:
CFLAGS = os.popen('pkg-config --cflags %s' % LUAPC).read().rstrip().split()
except:
CFLAGS = ['-I/usr/include/lua5.1']
try:
LUALIBPATH = os.environ['UWSGICONFIG_LUALIBPATH']
except:
LUALIBPATH = '/usr/lib/lua5.1'
if LUALIB:
LIBS = ['-l%s' % LUALIB]
else:
try:
LIBS = os.popen('pkg-config --libs %s' % LUAPC).read().rstrip().split()
except:
LIBS = ['-llua5.1']
if LUALIBPATH:
LDFLAGS = ['-L%s' % LUALIBPATH]
else:
LDFLAGS = []
NAME='lua'
CFLAGS = ['-I%s' % LUAINC]
LDFLAGS = ['-L%s' % LUALIBPATH]
GCC_LIST = ['lua_plugin']
LIBS = ['-l%s' % LUALIB]
+1 -1
View File
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
}
else {
char *sl = SG(sapi_headers).http_status_line;
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
uwsgi_response_prepare_headers(wsgi_req, sl + 9 , strlen(sl + 9));
}
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+4 -3
View File
@@ -152,7 +152,7 @@ struct uwsgi_server {
};
struct uwsgi_server uwsgi;
struct uwsgi_plugin *pypy_plugin;
struct uwsgi_plugin pypy_plugin;
const char *uwsgi_pypy_version;
@@ -228,7 +228,7 @@ const char *uwsgi_pypy_version = UWSGI_VERSION;
%s
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin *pypy_plugin;
extern struct uwsgi_plugin pypy_plugin;
%s
''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks)
@@ -473,7 +473,8 @@ def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
uwsgi_gc.append(cb)
if lib.uwsgi_register_rpc(ffi.new("char[]", name), lib.pypy_plugin, argc, cb) < 0:
print lib.pypy_plugin
if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
+2
View File
@@ -10,6 +10,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern char **environ;
@@ -94,6 +95,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->modifier1 = python_plugin.modifier1;
wi->mountpoint_len = wsgi_req->appid_len < 0xff ? wsgi_req->appid_len : (0xff-1);
strncpy(wi->mountpoint, wsgi_req->appid, wi->mountpoint_len);
+3 -3
View File
@@ -1732,7 +1732,7 @@ int uwsgi_python_mule_msg(char *message, size_t len) {
return 1;
}
void uwsgi_python_harakiri(int wid) {
static void uwsgi_python_harakiri(int wid) {
if (up.tracebacker) {
@@ -1762,7 +1762,7 @@ void uwsgi_python_harakiri(int wid) {
import logging
logging.basicConfig(filename='/tmp/pippo.log')
*/
ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
static ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!Py_IsInitialized()) return -1;
UWSGI_GET_GIL
@@ -1800,7 +1800,7 @@ clear:
return -1;
}
void uwsgi_python_on_load() {
static void uwsgi_python_on_load() {
uwsgi_register_logger("python", uwsgi_python_logger);
}
+9 -9
View File
@@ -4,7 +4,7 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
int wait_for_specific_signal = 0;
@@ -41,7 +41,7 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
return PyString_FromString("");
}
PyObject *py_uwsgi_signal_received(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_signal_received(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
@@ -172,12 +172,12 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
}
PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
}
PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
int fd;
@@ -193,7 +193,7 @@ PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int minute, hour, day, month, week;
@@ -211,7 +211,7 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int secs;
@@ -819,7 +819,7 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
}
#ifdef PYTHREE
else if (PyUnicode_Check(what)) {
filename = PyBytes_AsString(PyUnicode_AsASCIIString(what));
filename = PyBytes_AsString(PyUnicode_AsLatin1String(what));
fd = open(filename, O_RDONLY);
if (fd < 0) {
@@ -3477,7 +3477,7 @@ clear:
return Py_None;
}
PyObject *py_snmp_decr_gauge(PyObject * self, PyObject * args) {
static PyObject *py_snmp_decr_gauge(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint64_t oid_val = 1;
@@ -3510,7 +3510,7 @@ clear:
return Py_None;
}
PyObject *py_snmp_set_community(PyObject * self, PyObject * args) {
static PyObject *py_snmp_set_community(PyObject * self, PyObject * args) {
char *snmp_community;
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
@@ -29,7 +30,7 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->uh->modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh->modifier1 = 0;
wsgi_req->uh->modifier1 = python_plugin.modifier1;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
+3 -3
View File
@@ -61,7 +61,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *zero = NULL;
PyObject *zero2 = NULL;
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(head);
zero = PyUnicode_AsLatin1String(head);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http status string must be encodable in latin1");
}
@@ -135,7 +135,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(h_key);
zero = PyUnicode_AsLatin1String(h_key);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
@@ -153,7 +153,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero2 = PyUnicode_AsASCIIString(h_value);
zero2 = PyUnicode_AsLatin1String(h_value);
if (!zero2) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern PyTypeObject uwsgi_InputType;
/*
@@ -71,7 +72,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->uh->modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh->modifier1 = 0;
wsgi_req->uh->modifier1 = python_plugin.modifier1;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
+20 -9
View File
@@ -48,12 +48,6 @@ struct uwsgi_option uwsgi_rack_options[] = {
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_rbshell, NULL, 0},
{"rbshell-oneshot", no_argument, 0, "set ruby/irb shell (one shot)", uwsgi_opt_rbshell, NULL, 0},
#ifdef RUBY19
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
{"rbthreads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
{"ruby-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
#endif
{0, 0, 0, 0, 0, 0 ,0},
};
@@ -861,6 +855,10 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
rb_hash_aset(env, rb_str_new2("uwsgi.core"), INT2NUM(wsgi_req->async_id));
rb_hash_aset(env, rb_str_new2("uwsgi.version"), rb_str_new2(UWSGI_VERSION));
rb_hash_aset(env, rb_str_new2("uwsgi.node"), rb_str_new2(uwsgi.hostname));
// remove HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE
rb_hash_delete(env, rb_str_new2("HTTP_CONTENT_LENGTH"));
rb_hash_delete(env, rb_str_new2("HTTP_CONTENT_TYPE"));
@@ -1240,11 +1238,22 @@ void uwsgi_ruby_init_thread(int core_id) {
}
void uwsgi_rack_postinit_apps(void) {
if (ur.rb_threads > 1) {
}
}
/*
If the ruby VM has rb_reserved_fd_p, we avoid closign the filedescriptor needed by
modern ruby (the Matz ones) releases.
*/
static void uwsgi_ruby_cleanup() {
int (*uptr_rb_reserved_fd_p)(int) = dlsym(RTLD_DEFAULT, "rb_reserved_fd_p");
if (!uptr_rb_reserved_fd_p) return;
int i;
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uptr_rb_reserved_fd_p(i)) {
uwsgi_add_safe_fd(i);
}
}
}
struct uwsgi_plugin rack_plugin = {
@@ -1287,5 +1296,7 @@ struct uwsgi_plugin rack_plugin = {
.exception_repr = uwsgi_ruby_exception_repr,
.exception_log = uwsgi_ruby_exception_log,
.backtrace = uwsgi_ruby_backtrace,
.master_cleanup = uwsgi_ruby_cleanup,
};
-5
View File
@@ -41,9 +41,6 @@ struct uwsgi_rack {
VALUE dispatcher;
VALUE rb_uwsgi_io_class;
ID call;
VALUE fibers[200];
pthread_mutex_t gvl;
char *rbshell;
int rb_shell_oneshot;
@@ -57,8 +54,6 @@ struct uwsgi_rack {
char *gemset;
int rb_threads;
};
void uwsgi_rack_init_api(void);
+194
View File
@@ -0,0 +1,194 @@
#include <uwsgi.h>
#include <ruby.h>
/*
Author: Roberto De Ioris
Why a loop engine ???
The ruby 1.9/2.x threading model is very unique
First of all we cannot attach to already spawned pthread, for this reason
the "rbthreads" loop engine must create pthreads with rb_thread_create()
The second reason is for how the GVL is managed. We do not have
functions (like in CPython) to explicitely release and acquire it.
All happens via a function (rb_thread_call_without_gvl) calling the specified hook
whenever the code blocks.
Fortunately, thanks to the 1.9 async api, we can "patch" all of the server blocking parts
with 2 simple hooks: uwsgi.wait_write_hook and uwsgi.wait_read_hook
in addition to this we need to release the GVL in the accept() loop (but this is really easy)
*/
extern struct uwsgi_server uwsgi;
/*
for some strange reason, some version of ruby 1.9 does not expose this declaration...
*/
void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
rb_unblock_function_t *ubf, void *data2);
struct uwsgi_rbthreads {
int rbthreads;
int (*orig_wait_write_hook) (int, int);
int (*orig_wait_read_hook) (int, int);
} urbts;
static struct uwsgi_option rbthreads_options[] = {
{"rbthreads", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rb-threads", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rbthread", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rb-thread", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
// this structure is passed between threads
struct uwsgi_rbthread {
int queue;
int core_id;
struct wsgi_request *wsgi_req;
// return value
int ret;
// fd to monitor
int fd;
// non-blockign timeout
int timeout;
};
// this is called without the gvl
static void * uwsgi_rb_thread_accept(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = 0;
if (wsgi_req_accept(urbt->queue, urbt->wsgi_req)) {
urbt->ret = -1;
}
return NULL;
}
static VALUE uwsgi_rb_thread_core(void *arg) {
long core_id = (long) arg;
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
uwsgi_setup_thread_req(core_id, wsgi_req);
struct uwsgi_rbthread *urbt = uwsgi_malloc(sizeof(struct uwsgi_rbthread));
// initialize the main event queue to monitor sockets
urbt->queue = event_queue_init();
urbt->wsgi_req = wsgi_req;
uwsgi_add_sockets_to_queue(urbt->queue, (int)core_id);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(urbt->queue, uwsgi.signal_socket);
event_queue_add_fd_read(urbt->queue, uwsgi.my_signal_socket);
}
// ok we are ready, let's start managing requests and signals
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, (int)core_id, NULL);
rb_thread_call_without_gvl(uwsgi_rb_thread_accept, urbt, NULL, NULL);
// accept failed ?
if (urbt->ret) continue;
if (wsgi_req_recv(urbt->queue, wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
uwsgi_close_request(wsgi_req);
}
return Qnil;
}
static void rbthread_noop0() {
}
static void rbthread_noop(int core_id) {
}
static void *rbthreads_wait_fd_write_do(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = urbts.orig_wait_write_hook(urbt->fd, urbt->timeout);
return NULL;
}
static int rbthreads_wait_fd_write(int fd, int timeout) {
struct uwsgi_rbthread urbt;
urbt.fd = fd;
urbt.timeout = timeout;
rb_thread_call_without_gvl(rbthreads_wait_fd_write_do, &urbt, NULL, NULL);
return urbt.ret;
}
static void *rbthreads_wait_fd_read_do(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = urbts.orig_wait_read_hook(urbt->fd, urbt->timeout);
return NULL;
}
static int rbthreads_wait_fd_read(int fd, int timeout) {
struct uwsgi_rbthread urbt;
urbt.fd = fd;
urbt.timeout = timeout;
rb_thread_call_without_gvl(rbthreads_wait_fd_read_do, &urbt, NULL, NULL);
return urbt.ret;
}
static void rbthreads_loop() {
struct uwsgi_plugin *rup = uwsgi_plugin_get("rack");
// disable init_thread warning
if (rup) {
rup->init_thread = rbthread_noop;
}
// override read/write nb hooks
urbts.orig_wait_write_hook = uwsgi.wait_write_hook;
urbts.orig_wait_read_hook = uwsgi.wait_read_hook;
uwsgi.wait_write_hook = rbthreads_wait_fd_write;
uwsgi.wait_read_hook = rbthreads_wait_fd_read;
int i;
for(i=1;i<uwsgi.threads;i++) {
long y = i;
rb_thread_create(uwsgi_rb_thread_core, (void *) y);
}
long y = 0;
uwsgi_rb_thread_core((void *) y);
// never here
}
static void rbthreads_setup() {
uwsgi_register_loop( (char *) "rbthreads", rbthreads_loop);
}
static int rbthreads_init() {
if (urbts.rbthreads) {
if (uwsgi.threads < 2) {
uwsgi_log("you have to spawn at least 2 threads for effective rbthreads support\n");
exit(1);
}
struct uwsgi_plugin *rup = uwsgi_plugin_get("rack");
// disable enable_threads warning
if (rup) {
rup->enable_threads = rbthread_noop0;
}
// set loop engine
uwsgi.loop = "rbthreads";
}
return 0;
}
struct uwsgi_plugin rbthreads_plugin = {
.name = "rbthreads",
.on_load = rbthreads_setup,
.init = rbthreads_init,
.options = rbthreads_options,
};
+31
View File
@@ -0,0 +1,31 @@
import os
NAME='rbthreads'
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = []
LIBS = []
GCC_LIST = ['rbthreads']
+2 -2
View File
@@ -2,7 +2,7 @@
#ifdef UWSGI_ROUTING
#ifdef __linux__
#if defined(__linux__) && !defined(__UCLIBC__)
#include <crypt.h>
#elif defined(__CYGWIN__)
#include <crypt.h>
@@ -34,7 +34,7 @@ static uint16_t htpasswd_check(char *filename, char *auth) {
if (clen > 13) cpwd[13] = 0;
#ifdef __linux__
#if defined(__linux__) && !defined(__UCLIBC__)
struct crypt_data cd;
cd.initialized = 0;
// we do as nginx here
+17 -10
View File
@@ -9,14 +9,16 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
// mark a route request
wsgi_req->via = UWSGI_VIA_ROUTE;
// get the http address from the route
char *addr = ur->data;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_addr) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub_url = NULL;
if (ur->data3_len) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
ub_url = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data3, ur->data3_len);
uwsgi_buffer_destroy(ub_addr);
if (!ub_url) return UWSGI_ROUTE_BREAK;
}
@@ -25,7 +27,8 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
if (!ub) {
if (ub_url) uwsgi_buffer_destroy(ub_url);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
@@ -37,7 +40,8 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
if (wsgi_req->proto_parser_remains > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
wsgi_req->proto_parser_remains = 0;
@@ -49,22 +53,25 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
}
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_BREAK;
}
}
if (uwsgi_proxy_nb(wsgi_req, addr, ub, remains, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_log("error routing request to http server %s\n", addr);
if (uwsgi_proxy_nb(wsgi_req, ub_addr->buf, ub, remains, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_log("error routing request to http server %s\n", ub_addr->buf);
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_BREAK;
+165
View File
@@ -94,6 +94,142 @@ end:
return ret;
}
int uwsgi_routing_func_sendfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct stat st;
int ret = UWSGI_ROUTE_BREAK;
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->filename, urfc->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
int fd = open(ub->buf, O_RDONLY);
if (fd < 0) {
if (ur->custom)
ret = UWSGI_ROUTE_NEXT;
goto end;
}
if (fstat(fd, &st)) {
goto end2;
}
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
if (!ub_s) goto end2;
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
uwsgi_buffer_destroy(ub_s);
goto end2;
}
uwsgi_buffer_destroy(ub_s);
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
if (urfc->mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
if (!wsgi_req->headers_sent) {
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
}
if (!uwsgi_simple_sendfile(wsgi_req, fd, 0, st.st_size)) {
wsgi_req->via = UWSGI_VIA_SENDFILE;
wsgi_req->response_size += st.st_size;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct stat st;
int ret = UWSGI_ROUTE_BREAK;
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->filename, urfc->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
int fd = open(ub->buf, O_RDONLY);
if (fd < 0) {
if (ur->custom)
ret = UWSGI_ROUTE_NEXT;
goto end;
}
if (fstat(fd, &st)) {
goto end2;
}
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
if (!ub_s) goto end2;
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
uwsgi_buffer_destroy(ub_s);
goto end2;
}
uwsgi_buffer_destroy(ub_s);
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
if (urfc->mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
if (!wsgi_req->headers_sent) {
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
}
if (wsgi_req->socket->can_offload) {
if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, st.st_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += st.st_size;
// the fd will be closed by the offload engine
goto end;
}
}
if (!uwsgi_simple_sendfile(wsgi_req, fd, 0, st.st_size)) {
wsgi_req->via = UWSGI_VIA_SENDFILE;
wsgi_req->response_size += st.st_size;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
static int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
@@ -143,12 +279,41 @@ static int uwsgi_router_file_next(struct uwsgi_route *ur, char *args) {
return uwsgi_router_file(ur, args);
}
static int uwsgi_router_sendfile(struct uwsgi_route *ur, char *args) {
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_sendfile;
return ret;
}
static int uwsgi_router_sendfile_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_sendfile;
return ret;
}
static int uwsgi_router_fastfile(struct uwsgi_route *ur, char *args) {
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_fastfile;
return ret;
}
static int uwsgi_router_fastfile_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_fastfile;
return ret;
}
static void router_static_register(void) {
uwsgi_register_router("static", uwsgi_router_static);
uwsgi_register_router("file", uwsgi_router_file);
uwsgi_register_router("file-next", uwsgi_router_file_next);
uwsgi_register_router("sendfile", uwsgi_router_sendfile);
uwsgi_register_router("sendfile-next", uwsgi_router_sendfile_next);
uwsgi_register_router("fastfile", uwsgi_router_fastfile);
uwsgi_register_router("fastfile-next", uwsgi_router_fastfile_next);
}
struct uwsgi_plugin router_static_plugin = {
+221 -38
View File
@@ -1,4 +1,27 @@
/*
* Copyright (C) 2013 Unbit S.a.s. <info@unbit.it>
* Copyright (C) 2013 Guido Berhoerster <guido+uwsgi@berhoerster.name>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <uwsgi.h>
#include <locale.h>
#include <iconv.h>
#include <langinfo.h>
#ifndef UWSGI_XML_LIBXML2
#error you need a libxml2-enabled build of uWSGI to use the router_xmldir plugin
@@ -6,67 +29,227 @@
#include <libxml/tree.h>
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
static struct router_xmldir_conf {
char *codeset;
} conf;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
void *xrealloc(void *ptr, size_t size) {
void *tmp;
struct dirent **tasklist;
int n = scandir(ub->buf, &tasklist, 0, versionsort);
uwsgi_buffer_destroy(ub);
if (n < 0) return UWSGI_ROUTE_BREAK;
int i;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *rtree = xmlNewNode(NULL, BAD_CAST "tree");
xmlDocSetRootElement(rdoc, rtree);
tmp = realloc(ptr, size);
if (tmp == NULL) {
uwsgi_error("realloc()");
exit(1);
}
for(i=0;i<n;i++) {
if (tasklist[i]->d_name[0] == '.') goto next;
switch (tasklist[i]->d_type) {
case DT_DIR:
xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST tasklist[i]->d_name);
return (tmp);
}
char *to_utf8(char *codeset, char *in) {
size_t buf_size;
size_t buf_offset;
size_t in_remaining;
size_t buf_remaining;
size_t ret;
char *buf = NULL;
char *buf_ptr;
char *in_ptr = in;
static iconv_t cd = (iconv_t)-1;
/* UTF-8 encoded Unicode replacement char (U+FFFD) */
const char repl[] = "\xef\xbf\xbd";
if (cd == (iconv_t)-1) {
if ((cd = iconv_open("UTF-8", codeset)) == (iconv_t)-1) {
uwsgi_error("iconv_open");
return (NULL);
}
}
in_remaining = strlen(in) + 1;
buf_size = buf_remaining = in_remaining;
buf = buf_ptr = uwsgi_malloc(buf_size);
while (in_remaining > (size_t)0) {
ret = iconv(cd, &in_ptr, &in_remaining, &buf_ptr,
&buf_remaining);
if (ret == (size_t)-1) {
switch (errno) {
case EINVAL:
/* truncate */
in_remaining = 0;
*buf_ptr = '\0';
break;
case DT_LNK:
xmlNewTextChild(rtree, NULL, BAD_CAST "link", BAD_CAST tasklist[i]->d_name);
case EILSEQ:
/*
* insert a replacement character for each
* illegal sequence
*/
in_ptr++;
in_remaining--;
if (buf_remaining < sizeof (repl)) {
buf_size += in_remaining +
sizeof (repl) - 1;
buf_remaining += in_remaining +
sizeof (repl) - 1;
buf_offset = buf_ptr - buf;
buf = xrealloc(buf, buf_size);
buf_ptr = buf + buf_offset;
}
strcat(buf_ptr, repl);
buf_ptr += sizeof (repl) - 1;
buf_remaining -= sizeof (repl) - 1;
break;
case DT_REG:
xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST tasklist[i]->d_name);
case E2BIG:
buf_size += in_remaining;
buf_remaining += in_remaining;
buf_offset = buf_ptr - buf;
buf = xrealloc(buf, buf_size);
buf_ptr = buf + buf_offset;
break;
default:
xmlNewTextChild(rtree, NULL, BAD_CAST "unknown", BAD_CAST tasklist[i]->d_name);
break;
uwsgi_error("iconv");
free(buf);
return (NULL);
}
}
next:
free(tasklist[i]);
}
}
free(tasklist);
buf = xrealloc(buf, strlen(buf) + 1);
return (buf);
}
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
char **subject;
uint16_t *subject_len;
char *dirname;
struct uwsgi_buffer *ub;
char *name = NULL;
char *path = NULL;
int i;
int n;
struct dirent **tasklist;
xmlDoc *rdoc;
xmlNode *rtree;
xmlNodePtr entrynode;
char *path_info = NULL;
struct stat sb;
size_t sizebuf_len;
char *sizebuf;
char timebuf[20];
int xlen = 0;
subject = (char **) (((char *)(wsgi_req))+ur->subject);
subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len,
ur->data, ur->data_len);
if (!ub) {
uwsgi_500(wsgi_req);
return UWSGI_ROUTE_BREAK;
}
dirname = ub->buf;
path_info = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len,
"", 1);
n = scandir(dirname, &tasklist, 0, alphasort);
if (n < 0) {
uwsgi_404(wsgi_req);
goto out;
}
rdoc = xmlNewDoc(BAD_CAST "1.0");
rtree = xmlNewNode(NULL, BAD_CAST "index");
xmlNewProp(rtree, BAD_CAST "path", BAD_CAST path_info);
xmlDocSetRootElement(rdoc, rtree);
for(i = 0; i < n; i++) {
if ((strcmp(tasklist[i]->d_name, ".") == 0) ||
(strcmp(tasklist[i]->d_name, "..") == 0)) {
goto next_entry;
}
path = uwsgi_concat3(dirname, "/", tasklist[i]->d_name);
if (lstat(path, &sb) == -1) {
goto next_entry;
}
name = to_utf8(conf.codeset, tasklist[i]->d_name);
if (name == NULL) {
goto next_entry;
}
if (S_ISDIR(sb.st_mode)) {
entrynode = xmlNewTextChild(rtree, NULL,
BAD_CAST "directory", BAD_CAST name);
} else if (S_ISREG(sb.st_mode)) {
entrynode = xmlNewTextChild(rtree, NULL,
BAD_CAST "file", BAD_CAST name);
} else {
/* skip everything but directories and regular files */
goto next_entry;
}
sizebuf_len = snprintf(NULL, 0, "%jd", (intmax_t) sb.st_size);
sizebuf = uwsgi_malloc(sizebuf_len + 1);
snprintf(sizebuf, sizebuf_len + 1, "%jd", (intmax_t) sb.st_size);
xmlNewProp(entrynode, BAD_CAST "size", BAD_CAST sizebuf);
free(sizebuf);
strftime(timebuf, sizeof (timebuf), "%Y-%m-%dT%H:%M:%S",
localtime(&sb.st_mtime));
xmlNewProp(entrynode, BAD_CAST "mtime", BAD_CAST timebuf);
next_entry:
free(path);
path = NULL;
free(tasklist[i]);
free(name);
name = NULL;
}
free(tasklist);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
out:
uwsgi_buffer_destroy(ub);
free(path_info);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xmldir(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static void router_xmldir_register() {
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
static void router_xmldir_register(void) {
char *codeset;
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
setlocale(LC_ALL, "");
if ((codeset = nl_langinfo(CODESET)) == '\0') {
codeset = "ASCII";
}
conf.codeset = uwsgi_str(codeset);
if (conf.codeset == NULL) {
uwsgi_error("strdup()");
exit(1);
}
}
struct uwsgi_plugin router_xmldir_plugin = {
+65
View File
@@ -399,6 +399,61 @@ end:
return ret;
}
static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
// this is the list of args
char *argv[UMAX8];
// this is the size of each argument
uint16_t argvs[UMAX8];
// this is a placeholder for tmp uwsgi_buffers
struct uwsgi_buffer *ubs[UMAX8];
char **r_argv = (char **) ur->data2;
uint16_t *r_argvs = (uint16_t *) ur->data3;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t i;
for(i=0;i<ur->custom;i++) {
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
if (!ubs[i]) goto end;
argv[i] = ubs[i]->buf;
argvs[i] = ubs[i]->pos;
}
// ok we now need to check it it is a local call or a remote one
char *func = uwsgi_str(ur->data);
char *remote = NULL;
char *at = strchr(func, '@');
if (at) {
*at = 0;
remote = at+1;
}
uint16_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
ret = UWSGI_ROUTE_BREAK;
if (size == 0) goto end;
if (!uwsgi_req_append(wsgi_req, ur->data4, ur->data4_len, response, size)) {
free(response);
goto end;
}
free(response);
ret = UWSGI_ROUTE_NEXT;
end:
for(i=0;i<ur->custom;i++) {
if (ubs[i] != NULL) {
uwsgi_buffer_destroy(ubs[i]);
}
}
return ret;
}
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -497,6 +552,7 @@ end:
ur->custom = the number of arguments
ur->data2 = the pointer to the args
ur->data3 = the pointer to the args sizes
ur->data4 = func specific
*/
static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
ur->custom = 0;
@@ -552,6 +608,14 @@ static int uwsgi_router_rpc_raw(struct uwsgi_route *ur, char *args) {
return uwsgi_router_rpc_base(ur, args);
}
static int uwsgi_router_rpc_var(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_rpc_var;
char *space = strchr(args, ' ');
if (!space) return -1;
ur->data4 = args;
ur->data4_len = space - args;
return uwsgi_router_rpc_base(ur, space+1);
}
static void router_rpc_register() {
uwsgi_register_router("call", uwsgi_router_rpc);
@@ -560,6 +624,7 @@ static void router_rpc_register() {
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcraw", uwsgi_router_rpc_raw);
uwsgi_register_router("rpcvar", uwsgi_router_rpc_var);
}
#endif
+90
View File
@@ -0,0 +1,90 @@
#include <jvm.h>
/*
Servlet 2.5 JVM handler
*/
#define UWSGI_JVM_REQUEST_HANDLER_SERVLET 2
extern struct uwsgi_jvm ujvm;
struct uwsgi_servlet {
} uservlet;
static struct uwsgi_option uwsgi_servlet_options[] = {
{0, 0, 0, 0},
};
// the request handler
static int uwsgi_servlet_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
static int uwsgi_servlet_setup() {
uwsgi_log("loading servlet environment...\n");
jclass servlet = uwsgi_jvm_class("org/apache/jasper/servlet/JspServlet");
uwsgi_log("jclass = %p\n", servlet);
jmethodID mid = uwsgi_jvm_get_method_id(servlet, "<init>", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
jobject instance = (*ujvm_env)->NewObject(ujvm_env, servlet, mid);
if (uwsgi_jvm_exception() || !instance) exit(1);
uwsgi_log("done\n");
jclass uwsgi_servlet_config = uwsgi_jvm_class("uWSGIServletConfig");
mid = uwsgi_jvm_get_method_id(uwsgi_servlet_config, "<init>", "()V");
jobject config = (*ujvm_env)->NewObject(ujvm_env, uwsgi_servlet_config, mid);
mid = uwsgi_jvm_get_method_id(servlet, "init", "(Ljavax/servlet/ServletConfig;)V");
uwsgi_jvm_call_object(instance, mid, config );
uwsgi_log("SERVLET initialized\n");
jclass uwsgi_request = uwsgi_jvm_class("uWSGIServletRequest");
jclass uwsgi_response = uwsgi_jvm_class("uWSGIServletResponse");
uwsgi_log("%p %p\n", uwsgi_request, uwsgi_response);
mid = uwsgi_jvm_get_method_id(uwsgi_request , "<init>", "()V");
uwsgi_jvm_exception();
jobject request = (*ujvm_env)->NewObject(ujvm_env, uwsgi_request, mid);
mid = uwsgi_jvm_get_method_id(uwsgi_response , "<init>", "()V");
uwsgi_jvm_exception();
jobject response = (*ujvm_env)->NewObject(ujvm_env, uwsgi_response, mid);
uwsgi_log("%p %p\n", request, response);
mid = uwsgi_jvm_get_method_id(servlet, "service", "(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V");
if (uwsgi_jvm_exception() || !mid) exit(1);
uwsgi_jvm_call_object(instance, mid, request, response);
uwsgi_log("done\n");
mid = uwsgi_jvm_get_method_id(uwsgi_response, "flushBuffer", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
uwsgi_jvm_call_object(response, mid);
uwsgi_log("servlet loaded\n");
return 0;
}
static int uwsgi_servlet_init() {
if (uwsgi_jvm_register_request_handler(UWSGI_JVM_REQUEST_HANDLER_SERVLET, uwsgi_servlet_setup, uwsgi_servlet_request)) {
exit(1);
}
return 0;
}
struct uwsgi_plugin servlet_plugin = {
.name = "servlet",
.options = uwsgi_servlet_options,
.init = uwsgi_servlet_init,
};
+636
View File
@@ -0,0 +1,636 @@
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
import java.net.*;
/*
uWSGI Servlet 2.5 Container implementation
*/
class uWSGIServletContext implements ServletContext {
public Object getAttribute(String name) {
System.out.println("uWSGIServletContext getAttribute " + name);
return null;
}
public ServletContext getContext(String uripath) {
return this;
}
public String getContextPath() {
System.out.println("uWSGIServletContext getContextPath");
return "/root/uwsgi";
}
public int getMajorVersion() {
return 2;
}
public int getMinorVersion() {
return 5;
}
public String getMimeType(java.lang.String file) {
System.out.println("uWSGIServletContext getMimeType " + file);
return "text/plain";
}
public java.util.Set getResourcePaths(java.lang.String path) {
System.out.println("uWSGIServletContext getResourcePaths " + path);
return null;
}
public java.net.URL getResource(java.lang.String path) {
System.out.println("uWSGIServletContext getResource " + path);
try {
File myFile;
if (path.equals("/WEB-INF/web.xml")) {
myFile = new File("/root/uwsgi/WEB-INF/web.xml");
}
else {
myFile = new File("/root/uwsgi/foo.jsp");
}
return myFile.toURI().toURL();
}
catch(MalformedURLException e) {
System.out.println("uWSGIServletContext ERROR !!!");
return null;
}
}
public RequestDispatcher getNamedDispatcher(java.lang.String name) {
System.out.println("uWSGIServletContext getNamedDispatcher " + name);
return null;
}
public java.io.InputStream getResourceAsStream(java.lang.String path) {
System.out.println("uWSGIServletContext getResourceAsStream " + path);
try {
FileInputStream fis = new FileInputStream(path);
return fis;
}
catch(FileNotFoundException e) {
return null;
}
}
public RequestDispatcher getRequestDispatcher(java.lang.String path) {
System.out.println("uWSGIServletContext getRequestDispatcher " + path);
return null;
}
public Servlet getServlet(java.lang.String name) {
System.out.println("uWSGIServletContext getServlet");
return null;
}
public java.util.Enumeration getServletNames() {
return null;
}
public java.util.Enumeration getServlets() {
return null;
}
public void log(java.lang.String message, java.lang.Throwable throwable) {
System.out.println("LOG " + message);
}
public void log(java.lang.Exception exception, java.lang.String msg) {
System.out.println("LOG " + msg);
}
public void log(java.lang.String msg) {
System.out.println("LOG " + msg);
}
public String getRealPath(java.lang.String path) {
System.out.println("uWSGIServletContext getRealPath " + path);
return path;
}
public String getServerInfo() {
return "uWSGI";
}
public String getInitParameter(java.lang.String name) {
return null;
}
public Enumeration getInitParameterNames() {
System.out.println("uWSGIServletContext getInitParameterNames()");
return null;
}
public java.util.Enumeration getAttributeNames() {
System.out.println("uWSGIServletContext getAttributeNames");
return null;
}
public String getServletContextName() {
System.out.println("uWSGIServletContext getServletContextName");
return "/jsp";
}
public void removeAttribute(java.lang.String name) {
}
public void setAttribute(java.lang.String name, java.lang.Object object) {
System.out.println("uWSGIServletContext setAttribute " + name);
}
}
class uWSGIServletConfig implements ServletConfig {
uWSGIServletContext context;
public uWSGIServletConfig() {
super();
System.out.println("uWSGIServletConfig allocation");
this.context = new uWSGIServletContext();
}
public String getInitParameter(String name) {
System.out.println("ServletConfig getInitParameter " + name);
return null;
}
public Enumeration<java.lang.String> getInitParameterNames() {
System.out.println("ServletConfig getInitParameterNames");
Vector pNames = new Vector();
return pNames.elements();
}
public ServletContext getServletContext() {
System.out.println("ServletConfig getServletContext");
return this.context;
}
public String getServletName() {
return "/jsp";
}
}
class uWSGIServletOutputStream extends ServletOutputStream {
// append a byte to the writing buffer
public void write(int n) {
System.out.print((char)n);
}
// send them to the client
public void flush() {
System.out.println("FLUSHING");
}
}
class uWSGIServletSession implements HttpSession {
HashMap<String,Object> hm;
public uWSGIServletSession() {
this.hm = new HashMap<String,Object>();
}
public String getId() {
return "uwsgi";
}
public int getMaxInactiveInterval() {
return 3600;
}
public long getLastAccessedTime() {
return 1373874485;
}
public long getCreationTime() {
return 1373874485;
}
public void setMaxInactiveInterval(int interval) {
System.out.println("SESSION INTERVAL " + interval );
}
public HttpSessionContext getSessionContext() {
return null;
}
public ServletContext getServletContext() {
return null;
}
public String[] getValueNames() {
return (String[]) this.hm.keySet().toArray();
}
public void invalidate() {
}
public void removeAttribute(String name) {
this.hm.remove(name);
}
public void removeValue(String name) {
this.hm.remove(name);
}
public void putValue(String name, Object value) {
this.hm.put(name, value);
}
public void setAttribute(String name, Object value) {
this.hm.put(name, value);
}
public Enumeration getAttributeNames() {
return Collections.enumeration(this.hm.keySet());
}
public boolean isNew() {
return false;
}
public Object getAttribute(String name) {
return this.hm.get(name);
}
public Object getValue(String name) {
return this.hm.get(name);
}
}
class uWSGIServletRequest implements HttpServletRequest {
uWSGIServletSession session = null;
public Object getAttribute(String name) {
System.out.println("getAttribute " + name);
return null;
}
public Enumeration getAttributeNames() {
return null;
}
public String getCharacterEncoding() {
return "utf-8";
}
public void setCharacterEncoding(String env) {
}
public String getParameter(String name) {
System.out.println("getParameter " + name);
return null;
}
public Enumeration getParameterNames() {
return null;
}
public String[] getParameterValues(String name) {
return null;
}
public int getContentLength() {
return 0;
}
public String getContentType() {
return "text/plain";
}
public ServletInputStream getInputStream() {
return null;
}
public Map getParameterMap() {
return null;
}
public String getProtocol() {
return "HTTP/1.0";
}
public String getScheme() {
System.out.println("getScheme");
return "http";
}
public String getServerName() {
return "quantal64.local";
}
public int getServerPort() {
return 80;
}
public BufferedReader getReader() {
return null;
}
public String getRemoteAddr() {
return "127.0.0.1";
}
public String getRemoteHost() {
return "localhost";
}
public void setAttribute(String name, Object o) {
}
public void removeAttribute(String name) {
}
public Locale getLocale() {
return null;
}
public Enumeration getLocales() {
return null;
}
public boolean isSecure() {
return false;
}
public RequestDispatcher getRequestDispatcher(String path) {
System.out.println("RequestDispatcher getRequestDispatcher " + path);
return null;
}
public String getRealPath(String path) {
System.out.println("getRealPath " + path);
return "/tmp";
}
public int getRemotePort() {
return 1717;
}
public String getLocalName() {
return "localhost";
}
public String getLocalAddr() {
return "127.0.0.1";
}
public int getLocalPort() {
return 80;
}
public String getAuthType() {
return null;
}
public Cookie[] getCookies() {
return null;
}
public long getDateHeader(String name) {
return -1;
}
public String getHeader(String name) {
System.out.println("getHeader " + name);
return null;
}
public Enumeration getHeaders(String name) {
System.out.println("getHeaders " + name);
return null;
}
public Enumeration getHeaderNames() {
return null;
}
public int getIntHeader(String name) {
return -1;
}
public String getMethod() {
System.out.println("getMethod");
return "GET";
}
public String getPathInfo() {
System.out.println("getPathInfo");
return "";
}
public String getPathTranslated() {
System.out.println("getPathTranslated");
return null;
}
public String getContextPath() {
System.out.println("getContextPath");
return "";
}
public String getQueryString() {
return "r=17";
}
public String getRemoteUser() {
return "kratos";
}
public boolean isUserInRole(String role) {
return false;
}
public java.security.Principal getUserPrincipal() {
return null;
}
public String getRequestedSessionId() {
System.out.println("getRequestedSessionId !!!");
return null;
}
public String getRequestURI() {
System.out.println("getRequestURI");
return "/foo.jsp";
}
public StringBuffer getRequestURL() {
System.out.println("getRequestURL");
//return "http://quantal64.local/roberta?r=17";
return null;
}
public String getServletPath() {
System.out.println("getServletPath");
return "/root/uwsgi/foo.jsp";
}
public HttpSession getSession(boolean create) {
System.out.println(" getSession !!!");
return null;
}
public HttpSession getSession() {
System.out.println("!!! getSession !!!");
if (this.session == null) {
this.session = new uWSGIServletSession();
}
return this.session;
}
public boolean isRequestedSessionIdFromURL() {
return false;
}
public boolean isRequestedSessionIdFromUrl() {
return false;
}
public boolean isRequestedSessionIdFromCookie() {
return false;
}
public boolean isRequestedSessionIdValid() {
return false;
}
}
class uWSGIServletResponse implements HttpServletResponse {
PrintWriter pw;
public uWSGIServletResponse() {
this.pw = new PrintWriter(new uWSGIServletOutputStream());
}
public void addCookie(Cookie cookie) {
}
public boolean containsHeader(String name) {
return false;
}
public String encodeURL(String url) {
System.out.println("URL = " + url);
return url;
}
public String encodeRedirectURL(String url) {
return url;
}
public String encodeUrl(String url) {
return url;
}
public String encodeRedirectUrl(String url) {
return url;
}
public void sendError(int sc, String msg) {
}
public void sendError(int sc) {
}
public void sendRedirect(String location) {
}
public void setDateHeader(String name, long date) {
}
public void addDateHeader(String name, long date) {
}
public void setHeader(String name, String value) {
System.out.println("SET_HEADER " + name + " = " + value);
}
public void addHeader(String name, String value) {
System.out.println("ADD_HEADER " + name + " = " + value);
}
public void setIntHeader(String name, int value) {
}
public void addIntHeader(String name, int value) {
}
public void setStatus(int sc) {
System.out.println("STATUS " + sc);
}
public void setStatus(int sc, String sm) {
System.out.println("STATUS " + sc + " " + sm);
}
public void flushBuffer() {
System.out.println("flushBuffer");
this.pw.flush();
}
public void resetBuffer() {
System.out.println("resetBuffer");
}
public boolean isCommitted() {
return true;
}
public void reset() {
}
public void setLocale(Locale loc) {
}
public Locale getLocale() {
return null;
}
public int getBufferSize() {
return 4096;
}
public void setBufferSize(int size) {
}
public void setContentType(String type) {
System.out.println("setContentType " + type);
}
public void setContentLength(int len) {
}
public void setCharacterEncoding(String charset) {
}
public PrintWriter getWriter() {
System.out.println("getWriter()");
return this.pw;
}
public ServletOutputStream getOutputStream() {
System.out.println("getOutputStream()");
return null;
}
public String getContentType() {
return "text/plain";
}
public String getCharacterEncoding() {
return "utf-8";
}
}
+19
View File
@@ -0,0 +1,19 @@
import os
import shutil
jvm_path = 'plugins/jvm'
up = {}
try:
execfile('%s/uwsgiplugin.py' % jvm_path, up)
except:
f = open('%s/uwsgiplugin.py' % jvm_path)
exec(f.read(), up)
f.close()
NAME='servlet'
CFLAGS = up['CFLAGS']
CFLAGS.append('-I%s' % jvm_path)
LDFLAGS = []
LIBS = []
GCC_LIST = ['servlet_plugin']
+7
View File
@@ -2,6 +2,12 @@
#include <uwsgi.h>
#ifdef __UCLIBC__
struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
};
#else
#ifdef __APPLE__
#define _XOPEN_SOURCE
#endif
@@ -130,3 +136,4 @@ struct uwsgi_plugin ugreen_plugin = {
.init = u_green_init,
.options = ugreen_options,
};
#endif
+1 -1
View File
@@ -3,7 +3,7 @@ NAME='v8'
CFLAGS = ['-Wno-deprecated-declarations']
LDFLAGS = []
LIBS = ['-lv8']
LIBS = ['-lstdc++', '-lv8']
engine = os.environ.get('UWSGICONFIG_V8_ENGINE', '')
if engine == 'teajs':
CFLAGS.append('-DUWSGI_V8_TEAJS -fexceptions')
+3
View File
@@ -95,6 +95,9 @@ class uWSGIDistribution(Distribution):
self.cmdclass['install_lib'] = uWSGIInstallLib
self.cmdclass['build_ext'] = uWSGIBuilder
def is_pure(self):
return False
setup(name='uWSGI',
version=uc.uwsgi_version,
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-06-05'
s.date = '2013-07-21'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+42 -3
View File
@@ -141,7 +141,15 @@ extern "C" {
#define __EXTENSIONS__
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#ifdef __UCLIBC__
#include <sched.h>
#endif
#undef _GNU_SOURCE
#include <stdlib.h>
#include <stddef.h>
#include <signal.h>
@@ -212,8 +220,6 @@ extern "C" {
#ifdef __linux__
#include <sched.h>
#include <sys/prctl.h>
#include <linux/limits.h>
@@ -346,6 +352,9 @@ struct uwsgi_buffer {
size_t pos;
size_t len;
size_t limit;
#ifdef UWSGI_DEBUG_BUFFER
int freed;
#endif
};
struct uwsgi_string_list {
@@ -1097,6 +1106,9 @@ struct uwsgi_route {
void *data3;
size_t data3_len;
void *data4;
size_t data4_len;
// 64bit value for custom usage
uint64_t custom;
@@ -1434,6 +1446,7 @@ struct wsgi_request {
ssize_t chunked_input_chunk_len;
size_t chunked_input_need;
uint8_t chunked_input_complete;
size_t chunked_input_decapitate;
uint64_t stream_id;
@@ -1568,6 +1581,9 @@ struct uwsgi_server {
char *procname_master;
char *procname;
// daemontools-like envdir
struct uwsgi_string_list *envdirs;
char *requested_clock;
struct uwsgi_clock *clocks;
struct uwsgi_clock *clock;
@@ -1666,6 +1682,7 @@ struct uwsgi_server {
char *emperor_procname;
int emperor_fd;
int emperor_queue;
int emperor_nofollow;
int emperor_tyrant;
int emperor_tyrant_nofollow;
int emperor_fd_config;
@@ -2000,6 +2017,9 @@ struct uwsgi_server {
rlim_t evil_reload_on_as;
rlim_t evil_reload_on_rss;
struct uwsgi_string_list *reload_on_fd;
struct uwsgi_string_list *brutal_reload_on_fd;
struct uwsgi_string_list *touch_reload;
struct uwsgi_string_list *touch_chain_reload;
struct uwsgi_string_list *touch_workers_reload;
@@ -2009,6 +2029,10 @@ struct uwsgi_server {
struct uwsgi_string_list *touch_exec;
struct uwsgi_string_list *touch_signal;
struct uwsgi_string_list *fs_reload;
struct uwsgi_string_list *fs_brutal_reload;
struct uwsgi_string_list *fs_signal;
int propagate_touch;
// enable grunt mode
@@ -2801,6 +2825,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *, char *, uint16_t, char *, uint64_t, u
int uwsgi_cache_del2(struct uwsgi_cache *, char *, uint16_t, uint64_t, uint16_t);
char *uwsgi_cache_get2(struct uwsgi_cache *, char *, uint16_t, uint64_t *);
char *uwsgi_cache_get3(struct uwsgi_cache *, char *, uint16_t, uint64_t *, uint64_t *);
char *uwsgi_cache_get4(struct uwsgi_cache *, char *, uint16_t, uint64_t *, uint64_t *);
uint32_t uwsgi_cache_exists2(struct uwsgi_cache *, char *, uint16_t);
struct uwsgi_cache *uwsgi_cache_create(char *);
struct uwsgi_cache *uwsgi_cache_by_name(char *);
@@ -2982,7 +3007,7 @@ time_t timegm(struct tm *);
#endif
size_t uwsgi_str_num(char *, int);
size_t uwsgi_str_occurence(char *, size_t, char);
int uwsgi_proto_uwsgi_parser(struct wsgi_request *);
int uwsgi_proto_base_write(struct wsgi_request *, char *, size_t);
@@ -3023,6 +3048,8 @@ char *uwsgi_split3(char *, size_t, char, char **, size_t *, char **, size_t *, c
char *uwsgi_split4(char *, size_t, char, char **, size_t *, char **, size_t *, char **, size_t *, char **, size_t *);
char *uwsgi_netstring(char *, size_t, char **, size_t *);
char *uwsgi_str_split_nget(char *, size_t, char, size_t, size_t *);
int uwsgi_get_socket_num(struct uwsgi_socket *);
struct uwsgi_socket *uwsgi_new_socket(char *);
struct uwsgi_socket *uwsgi_new_shared_socket(char *);
@@ -3395,6 +3422,7 @@ void uwsgi_fixup_routes(struct uwsgi_route *);
void uwsgi_reload(char **);
char *uwsgi_chomp(char *);
char *uwsgi_chomp2(char *);
int uwsgi_file_to_string_list(char *, struct uwsgi_string_list **);
void uwsgi_backtrace(int);
void uwsgi_check_logrotate(void);
@@ -3998,6 +4026,7 @@ void uwsgi_exceptions_handler_thread_start(void);
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *, char *);
int plugin_already_loaded(const char *);
struct uwsgi_plugin *uwsgi_plugin_get(const char *);
struct uwsgi_cache_magic_context {
char *cmd;
@@ -4076,12 +4105,22 @@ int uwsgi_is_again();
void uwsgi_disconnect(struct wsgi_request *);
int uwsgi_ready_fd(struct wsgi_request *);
void uwsgi_envdir(char *);
void uwsgi_envdirs(struct uwsgi_string_list *);
void uwsgi_opt_envdir(char *, char *, void *);
void uwsgi_add_reload_fds();
void uwsgi_add_reload_fds();
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
#endif
int uwsgi_master_check_cron_death(int);
int uwsgi_register_fsmon(struct uwsgi_string_list *);
int uwsgi_fsmon_event(int);
void uwsgi_fsmon_setup();
#ifdef __cplusplus
}
+11 -6
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.13'
uwsgi_version = '1.9.14'
import os
import re
@@ -232,7 +232,7 @@ def build_uwsgi(uc, print_only=False):
continue
p = p.strip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN'):
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN') or (uwsgi_os == 'Darwin' and uwsgi_os_k.startswith('8')):
continue
epc += "UDEP(%s);" % p
eplc += "ULEP(%s);" % p
@@ -316,7 +316,7 @@ def build_uwsgi(uc, print_only=False):
p = p.strip()
if p == 'ugreen':
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN'):
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN') or (uwsgi_os == 'Darwin' and uwsgi_os_k.startswith('8')):
continue
path = 'plugins/%s' % p
path = path.rstrip('/')
@@ -511,7 +511,7 @@ class uConf(object):
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon',
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
@@ -585,7 +585,7 @@ class uConf(object):
if gcc_major >= 4:
self.cflags = self.cflags + [ '-Wextra', '-Wno-unused-parameter', '-Wno-missing-field-initializers' ]
if (gcc_major == 4 and gcc_minor >= 8) or gcc_major > 4:
self.cflags.append('-Wno-format')
self.cflags.append('-Wno-format -Wno-format-security')
self.ldflags = os.environ.get("LDFLAGS", "").split()
self.libs = ['-lpthread', '-lm', '-rdynamic']
@@ -694,6 +694,11 @@ class uConf(object):
self.libs.append('-lroot')
if uwsgi_os == 'Darwin':
if uwsgi_os_k.startswith('8'):
self.cflags.append('-DUNSETENV_VOID')
self.cflags.append('-DNO_SENDFILE')
self.cflags.append('-DNO_EXECINFO')
self.cflags.append('-DOLD_REALPATH')
self.cflags.append('-mmacosx-version-min=10.5')
if GCC in ('clang',):
self.libs.remove('-rdynamic')
@@ -825,7 +830,7 @@ class uConf(object):
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
filemonitor_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD'):
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
filemonitor_mode = 'kqueue'
if filemonitor_mode == 'inotify':
+45 -11
View File
@@ -1,3 +1,4 @@
from functools import partial
import sys
from threading import Thread
@@ -26,7 +27,13 @@ def get_free_signal():
def manage_spool_request(vars):
ret = spooler_functions[vars['ud_spool_func']](vars)
f = spooler_functions[vars['ud_spool_func']]
if 'args' in vars:
args = pickle.loads(vars.pop('args'))
kwargs = pickle.loads(vars.pop('kwargs'))
ret = f(*args, **kwargs)
else:
ret = f(vars)
if not 'ud_spool_ret' in vars:
return ret
return int(vars['ud_spool_ret'])
@@ -45,21 +52,29 @@ class postfork(object):
postfork_chain.append(f)
class spoolraw(object):
class _spoolraw(object):
def __call__(self, *args, **kwargs):
arguments = self.base_dict
if len(args) > 0:
arguments.update(args[0])
if kwargs:
arguments.update(kwargs)
if not self.pass_arguments:
if len(args) > 0:
arguments.update(args[0])
if kwargs:
arguments.update(kwargs)
else:
spooler_args = {}
for key in ('message_dict', 'spooler', 'priority', 'at', 'body'):
if key in kwargs:
spooler_args.update({key: kwargs.pop(key)})
arguments.update(spooler_args)
arguments.update({'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
return uwsgi.spool(arguments)
# For backward compatibility (uWSGI < 1.9.13)
def spool(self, *args, **kwargs):
return self.__class__.__call__(self, *args, **kwargs)
def __init__(self, f):
def __init__(self, f, pass_arguments):
if not 'spooler' in uwsgi.opt:
raise Exception(
"you have to enable the uWSGI spooler to use @%s decorator" % self.__class__.__name__)
@@ -67,21 +82,40 @@ class spoolraw(object):
spooler_functions[self.f.__name__] = self.f
# For backward compatibility (uWSGI < 1.9.13)
self.f.spool = self.__call__
self.pass_arguments = pass_arguments
self.base_dict = {'ud_spool_func': self.f.__name__}
class spool(spoolraw):
class _spool(_spoolraw):
def __call__(self, *args, **kwargs):
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
return spoolraw.__call__(self, *args, **kwargs)
return _spoolraw.__call__(self, *args, **kwargs)
class spoolforever(spoolraw):
class _spoolforever(_spoolraw):
def __call__(self, *args, **kwargs):
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
return spoolraw.__call__(self, *args, **kwargs)
return _spoolraw.__call__(self, *args, **kwargs)
def spool_decorate(f=None, pass_arguments=False, _class=_spoolraw):
if not f:
return partial(_class, pass_arguments=pass_arguments)
return _class(f, pass_arguments)
def spoolraw(f=None, pass_arguments=False):
return spool_decorate(f, pass_arguments)
def spool(f=None, pass_arguments=False):
return spool_decorate(f, pass_arguments, _spool)
def spoolforever(f=None, pass_arguments=False):
return spool_decorate(f, pass_arguments, _spoolforever)
class mulefunc(object):