Compare commits

..
106 Commits
Author SHA1 Message Date
Unbit cb603682e4 updated gemspec for the new release 2013-05-26 08:08:32 +02:00
Unbit c986a06bf7 more api functions in the uwsgi pypy module, it is enough for 1.9.11 2013-05-26 07:24:57 +02:00
Unbit e2843a6cee fixed static cache paths 2013-05-25 21:03:59 +02:00
Unbit ea1f239807 added memory offload 2013-05-25 20:01:26 +02:00
Unbit 8d7618146a fixed X-Sendfile + gzip 2013-05-25 18:07:41 +02:00
Unbit eb9e419bb0 fixed GC problem with pypy callback 2013-05-25 08:26:52 +02:00
Unbit f98f71ac26 added rbtimer and rpc/call to pypy 2013-05-25 08:09:09 +02:00
Unbit 03baaaebcb only import gevent.select in chat example 2013-05-24 20:41:51 +02:00
Unbit cbca954508 added tests/websockets_chat.py 2013-05-24 20:37:53 +02:00
Unbit 22ba6cc406 added uwsgi.lock/unlock to pypy and fixed --pypy-wsgi-file 2013-05-24 18:10:29 +02:00
Unbit 6bd172acb4 added preinit_apps hook in pypy 2013-05-24 06:59:13 +02:00
unbit 818ba4416f Merge pull request #295 from prymitive/cron_harakiri_fix
send sigkill to whole process group on cron harakiri
2013-05-23 06:50:45 -07:00
Łukasz Mierzwa adff12841c fixed harakiri for cron2 2013-05-23 15:40:02 +02:00
Łukasz Mierzwa 480c306591 send sigkill to whole process group on cron harakiri 2013-05-23 14:52:38 +02:00
unbit cbd1481cb7 Merge pull request #294 from prymitive/cron2
--cron2 option
2013-05-23 04:51:36 -07:00
Łukasz Mierzwa d1c1871222 --cron2 option 2013-05-23 13:44:13 +02:00
Unbit 15a94b8fb0 fixed a typo 2013-05-23 12:10:28 +02:00
unbit 66be54e6a7 Merge pull request #293 from prymitive/cron_stats
cron harakiri and stats
2013-05-23 03:46:24 -07:00
Łukasz Mierzwa 62c85cc2eb cron harakiri and stats 2013-05-23 12:25:02 +02:00
Unbit 1ae05a9ebc avoid loading pypy when python is already loaded 2013-05-23 12:02:35 +02:00
unbit 3457c70f30 Merge pull request #292 from prymitive/unique_crons
unique crons, fixes #227
2013-05-23 02:28:48 -07:00
Łukasz Mierzwa c1ec9126da unique crons, fixes #227 2013-05-23 11:09:56 +02:00
Unbit 398da2fac7 added 'harakiri' routing action 2013-05-23 08:52:19 +02:00
Unbit 47f33d6346 added --print-sym 2013-05-23 08:46:01 +02:00
Unbit 2cad82d537 removed support for SLOW pypy cpyext 2013-05-23 07:48:19 +02:00
Unbit 8d06d78537 preliminary support for GNU HURD 2013-05-23 07:43:01 +00:00
Unbit b61be000de added support for non-file object in pypy wsgi.file_wrapper 2013-05-23 07:03:41 +02:00
Unbit 9ca6de6e7a fixed #291 2013-05-23 06:51:59 +02:00
unbit 5c03c25e96 Merge pull request #237 from prymitive/cgroup_perms
allow setting cgroup dir mode
2013-05-22 05:23:42 -07:00
Roberta Giordano 23843163ad right fix for pipeline requests 2013-05-22 07:41:18 +02:00
Roberta Giordano 8b07fbbedc honour read() method if original file_wrapper object is not a file 2013-05-22 07:16:34 +02:00
Unbit 5bf55220d4 fixed python3 stdout/stderr line buffering 2013-05-21 14:19:33 +02:00
Unbit 0e1de3d6e8 added __name__ and sys.argv[0] in pypy setup script 2013-05-21 00:37:02 +02:00
Unbit 3a7ba3675b better sanity check for http requests 2013-05-20 23:44:05 +02:00
Unbit 5c0deb5bdb correctly handle pep333 exc_info in pypy 2013-05-20 23:31:14 +02:00
Unbit 50dcbc2b01 improved sendfile() on pypy 2013-05-20 23:21:08 +02:00
Unbit 90d72f7843 completed pep3333 vars for pypy 2013-05-20 21:35:02 +02:00
Unbit 90ee59c70d try to automatically set pypy home during compilation 2013-05-20 21:05:41 +02:00
Unbit 59eda11c1b Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-20 18:58:21 +02:00
Unbit 78684a424f support for http keepalive for request with body 2013-05-20 14:27:50 +02:00
unbit 4a936dda6e Merge pull request #289 from edevil/DropInvalid
Drop obvious invalid requests.
2013-05-20 03:04:14 -07:00
Andre Cruz 094d4b99a4 Drop obvious invalid requests. 2013-05-20 10:44:35 +01:00
Unbit 382268308e improved PYTHONPATH management 2013-05-19 23:40:49 +02:00
Unbit 97315d27b9 added osx support to pypy plugin 2013-05-19 23:33:49 +02:00
Unbit 26ae573b72 added cache_get,cache_update and cache_del to pypy 2013-05-19 22:40:47 +02:00
Unbit 803c44d783 added pypy management of .wsgi files and pythonpath manipulation 2013-05-19 22:33:42 +02:00
Unbit 90f3f1037a fixed a leak in uwsgi_get_app_id 2013-05-19 12:01:04 +02:00
Unbit ce39a751d9 improved uwsgi_get_app_id 2013-05-19 12:00:12 +02:00
unbit ceebf7d32d Merge pull request #288 from alex/pypy-cleanups
Some cleanups for the PyPy plugin:
2013-05-18 22:54:53 -07:00
Unbit 8da59bf0ac better __main__ setup in pypy 2013-05-19 07:52:31 +02:00
Unbit d25979502a better auto-detection of pypy paths 2013-05-19 07:45:21 +02:00
Unbit 549bc3bf9f added --pypy-eval --pypy-eval-post-fork --pypy-eval-exec --pypy-eval-exec-post-fork 2013-05-19 07:17:22 +02:00
Alex Gaynor 22b2f325e0 removed a method with a nonsense implementation 2013-05-18 22:09:24 -07:00
Alex Gaynor 6615d1b90c Catch a more precise error 2013-05-18 22:06:36 -07:00
Alex Gaynor 8f045c4254 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-05-18 22:06:04 -07:00
Alex Gaynor a4434349e5 whoops, a few small fixse 2013-05-18 22:03:55 -07:00
Unbit 01272be25f automatically detect pypy in setup.py 2013-05-19 07:02:05 +02:00
Alex Gaynor be0beed403 Some cleanups for the PyPy plugin:
a) pep8 and such
b) Made classes be newstyle
c) Made the classes be created once, not once per request
2013-05-18 21:59:37 -07:00
Unbit 453d2abed5 another micro optimization for pypy 2013-05-19 06:52:01 +02:00
Unbit 57e9ccbef0 added uwsgi.opt to pypy 2013-05-19 06:33:57 +02:00
Unbit 989124772b added wsgi.file_wrapper and improved import in pypy 2013-05-19 06:20:02 +02:00
Unbit 72400e4b91 completed wsgi.input for pypy 2013-05-19 05:33:53 +02:00
Unbit 900cba29a7 fixed python3 pyargv 2013-05-19 04:55:52 +02:00
Unbit f177a65c1e added uwsgi.add_file_monitor to pypy 2013-05-18 20:08:50 +02:00
Unbit b6baf9016d Merge branch 'master' of github.com:unbit/uwsgi 2013-05-18 20:02:37 +02:00
Unbit 86ac6e8044 implemented uwsgi.add_timer for pypy 2013-05-18 20:01:18 +02:00
unbit 66d8fb95db Merge pull request #286 from alex/patch-1
Fixed a clear typo.
2013-05-18 10:55:50 -07:00
Unbit 22da8d9ba2 optimized pypy environ helper 2013-05-18 19:45:18 +02:00
Alex Gaynor 819e9c1b16 Fixed a clear typo.
Only call writer once when the result of a WSGI application is a string.
2013-05-18 11:23:01 -06:00
Unbit dd4b2e8bc2 fixed a typo 2013-05-18 18:29:16 +02:00
Unbit e2f7ac2017 added --mule-msg-size 2013-05-18 18:28:50 +02:00
Unbit 31b5cf6926 fixed mule_msg 2013-05-18 17:52:23 +02:00
Unbit 25fe3035c2 fixed SCRIPT_NAME handling in python 2013-05-18 17:27:51 +02:00
Unbit 0cf56823cd added uwsgi.cache_get to pypy 2013-05-18 15:45:53 +02:00
Unbit c2f36968c3 trying to understand why multirheading is flaky on pypy 2013-05-18 12:17:43 +02:00
Unbit a508c7f53e added signal handling to pypy 2013-05-18 09:59:06 +02:00
Unbit 48de68031d more pypy implementations 2013-05-18 09:20:55 +02:00
Unbit 81ef85af82 added xmlrpc wrapper 2013-05-17 16:42:45 +02:00
Unbit 16b65d7dbe uwsgi RPC http wrapper 2013-05-17 15:45:43 +02:00
Unbit 5a98e6511b prepare for pypy multithreading 2013-05-17 14:28:42 +02:00
unbit 2418f08e22 Update README 2013-05-16 23:31:23 +03:00
Unbit 80a821bc20 updated pypy README 2013-05-16 18:09:36 +02:00
Unbit 378f78bd87 removed uwsgi.py 2013-05-16 18:03:35 +02:00
Unbit f010591e19 more WSGI vars 2013-05-16 17:58:15 +02:00
Unbit 5274abdcca fixed pypy environ 2013-05-16 17:30:29 +02:00
Unbit 48f9e8c5c8 improved PyPy plugin 2013-05-16 16:29:13 +02:00
unbit 5c02117fde Merge pull request #285 from fijal/master
A sketch for a PyPy plugin
2013-05-15 05:21:57 -07:00
Maciej Fijalkowski bc56a188f8 Add a copyright info 2013-05-15 14:18:47 +02:00
Maciej Fijalkowski b6df1b22ab flush the pypy debug file 2013-05-14 23:55:27 +02:00
Maciej Fijalkowski 0fbf2dd5bb Progress - now example wsgi runs 2013-05-14 23:32:05 +02:00
Unbit 38c126d11a fixed file action status 2013-05-14 16:49:22 +02:00
Unbit 7dff602e5e try to fix retry engine 2013-05-14 16:43:44 +02:00
Maciej Fijalkowski e401f32815 This was indeed temporary 2013-05-14 15:19:04 +02:00
Maciej Fijalkowski 12e94b70a7 Merge github.com:fijal/uwsgi 2013-05-14 15:06:48 +02:00
Maciej Fijalkowski 884de3959c initial checkin of pypy plugin 2013-05-14 15:04:17 +02:00
Unbit fe12325e50 fixed goto and pc in error and final routing 2013-05-14 12:19:17 +02:00
Unbit bea86f3f79 fixed a typo 2013-05-13 18:55:48 +02:00
unbit 7a5f3667da Merge pull request #280 from xrmx/warn-ini
core: print a warning if the configuration section can't be read
2013-05-13 07:35:20 -07:00
Riccardo Magliocchetti 0813788c98 core: print a warning if the configuration section can't be read
Fixes #278
2013-05-13 16:21:30 +02:00
Unbit b1ca73e7f0 added file-next action 2013-05-13 07:33:05 +02:00
Unbit ebf9e9b1a3 added ignore_body flag 2013-05-13 07:19:12 +02:00
Unbit b0abab7a1d fixed #277 2013-05-12 22:57:07 +02:00
Unbit 995bb493df preliminary implementation of error routing 2013-05-12 22:48:10 +02:00
Unbit 1b2375fc84 added error routes 2013-05-12 18:02:33 +02:00
Unbit b7315bcb5a added "file" routing action 2013-05-12 17:36:40 +02:00
Łukasz Mierzwa 7c4caef5e7 allow setting cgroup dir mode 2013-04-18 13:13:15 +02:00
51 changed files with 2106 additions and 171 deletions
+2
View File
@@ -2,6 +2,8 @@
*.py[co]
*.class
*.jar
*~
*.so
/uwsgi
/uwsgibuild.*
+9 -1
View File
@@ -194,9 +194,15 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
else {
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
free(value);
}
else {
uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key);
}
next:
usl = usl->next;
}
@@ -1089,7 +1095,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// defaults
uc->blocks = uc->max_items;
uc->blocksize = UMAX16;
uc->max_item_size = uc->blocksize;
uc->keysize = 2048;
uc->hashsize = UMAX16;
uc->hash = uwsgi_hash_algo_get("djb33x");
@@ -1097,6 +1102,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
// customize
if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize);
if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); }
// set the true max size of an item
uc->max_item_size = uc->blocksize;
if (c_blocks) uc->blocks = uwsgi_n64(c_blocks);
if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); }
if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash);
+160 -12
View File
@@ -27,13 +27,22 @@ struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
exit(1);
}
uc->command = crontab + i;
uc->pid = -1;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->unique = 1;
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
@@ -45,9 +54,140 @@ void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->unique = 1;
}
#endif
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
char *c_minute = NULL;
char *c_hour = NULL;
char *c_day = NULL;
char *c_month = NULL;
char *c_week = NULL;
char *c_unique = NULL;
char *c_harakiri = NULL;
char *c_legion = NULL;
char *c_command = value;
char *space = strchr(value, ' ');
if (space) {
if (uwsgi_str_contains(value, space - value, '=')) {
// --cron2 key=val command
*space = 0;
c_command = space + 1;
}
// no point in parsing key=val list if there is none
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
"minute", &c_minute,
"hour", &c_hour,
"day", &c_day,
"month", &c_month,
"week", &c_week,
"unique", &c_unique,
"harakiri", &c_harakiri,
"legion", &c_legion,
NULL)) {
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
else {
if (uwsgi_str_contains(value, strlen(value), '=')) {
// --cron2 key=val
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
uc->command = c_command;
if (!uc->command) {
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
exit(1);
}
// defaults
uc->minute = -1;
uc->hour = -1;
uc->day = -1;
uc->month = -1;
uc->week = -1;
uc->unique = 0;
uc->mercy = 0;
uc->harakiri = 0;
uc->pid = -1;
#ifdef UWSGI_SSL
uc->legion = c_legion;
#endif
if (c_minute)
uc->minute = atoi(c_minute);
if (c_hour)
uc->hour = atoi(c_hour);
if (c_day)
uc->day = atoi(c_day);
if (c_month)
uc->month = atoi(c_month);
if (c_week)
uc->week = atoi(c_week);
if (c_unique)
uc->unique = atoi(c_unique);
if (c_harakiri) {
if (atoi(c_harakiri)) {
// harakiri > 0
uc->mercy = atoi(c_harakiri);
}
else {
// harakiri == 0
uc->mercy = -1;
}
}
else if (uwsgi.cron_harakiri) {
uc->harakiri = uwsgi.cron_harakiri;
}
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
@@ -134,15 +274,16 @@ void uwsgi_manage_command_cron(time_t now) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
current_cron = current_cron->next;
continue;
}
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
goto next;
}
#endif
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
// skip unique crons that are still running
if (current_cron->unique && current_cron->pid >= 0)
goto next;
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
@@ -153,20 +294,27 @@ void uwsgi_manage_command_cron(time_t now) {
current_cron->func(current_cron, now);
}
else {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
}
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
if (pid >= 0) {
current_cron->pid = pid;
current_cron->started_at = now;
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
if (current_cron->mercy) {
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
if (current_cron->mercy > 0)
current_cron->harakiri = now + current_cron->mercy;
}
else if (uwsgi.cron_harakiri)
current_cron->harakiri = now + uwsgi.cron_harakiri;
}
}
}
current_cron->last_job = now;
}
}
next:
current_cron = current_cron->next;
}
}
+17
View File
@@ -376,7 +376,11 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
#ifdef PORT_SOURCE_FILE
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
#else
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
#endif
return (long) pe[id].portev_user;
}
@@ -464,7 +468,11 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
#ifdef PORT_SOURCE_FILE
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
#else
if (pe.portev_source == PORT_SOURCE_TIMER) {
#endif
*interesting_fd = (long) pe.portev_user;
}
else {
@@ -972,6 +980,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
#ifdef PORT_SOURCE_FILE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
@@ -1032,6 +1041,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
#else
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
+6
View File
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
int got_section = 0;
if (uwsgi_check_scheme(file)) {
@@ -147,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
got_section = 1;
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
@@ -161,6 +163,10 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (!got_section) {
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
}
if (colon) {
colon[0] = ':';
}
+5
View File
@@ -161,6 +161,10 @@ void uwsgi_init_default() {
uwsgi.empty = "";
#ifdef __linux__
uwsgi.cgroup_dir_mode = "0700";
#endif
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
@@ -349,6 +353,7 @@ void uwsgi_setup_workers() {
#ifdef UWSGI_ROUTING
uwsgi_fixup_routes(uwsgi.routes);
uwsgi_fixup_routes(uwsgi.error_routes);
uwsgi_fixup_routes(uwsgi.final_routes);
#endif
+10 -2
View File
@@ -764,10 +764,18 @@ nextlock:
}
void uwsgi_user_lock(int lock_num) {
int uwsgi_user_lock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_lock(uwsgi.user_lock[lock_num]);
return 0;
}
void uwsgi_user_unlock(int lock_num) {
int uwsgi_user_unlock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return 0;
}
+2
View File
@@ -706,6 +706,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_gateways_deadline();
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -789,6 +790,7 @@ int master_loop(char **argv, char **environ) {
if (uwsgi_master_check_mules_death(diedpid)) continue;
if (uwsgi_master_check_gateways_death(diedpid)) continue;
if (uwsgi_master_check_daemons_death(diedpid)) continue;
if (uwsgi_master_check_cron_death(diedpid)) continue;
}
+26
View File
@@ -277,3 +277,29 @@ int uwsgi_worker_is_busy(int wid) {
}
return 0;
}
int uwsgi_master_check_cron_death(int diedpid) {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid == (pid_t) diedpid) {
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
uc->pid = -1;
uc->started_at = 0;
return -1;
}
uc = uc->next;
}
return 0;
}
void uwsgi_master_check_crons_deadline() {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
kill(-uc->pid, SIGKILL);
}
uc = uc->next;
}
}
+57
View File
@@ -1079,6 +1079,63 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
}
struct uwsgi_cron *ucron = uwsgi.crons;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "crons"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
while (ucron) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
goto end;
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
goto end;
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
goto end;
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
goto end;
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
if (uwsgi_stats_keyval_comma(us, "command", ucron->command))
goto end;
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
goto end;
#ifdef UWSGI_SSL
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
goto end;
#endif
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
goto end;
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
ucron = ucron->next;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#ifdef UWSGI_SSL
struct uwsgi_legion *legion = NULL;
if (uwsgi.legions) {
+3 -3
View File
@@ -416,12 +416,12 @@ void uwsgi_setup_mules_and_farms() {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
uwsgi.mules[i].id = i + 1;
@@ -451,7 +451,7 @@ void uwsgi_setup_mules_and_farms() {
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
+59
View File
@@ -58,6 +58,23 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
return 0;
}
/*
memory offload engine:
buf -> pointer to the memory to transfer (memory is freed at the end)
len -> amount of data to transfer
*/
int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
}
return 0;
}
/*
transfer offload engine:
@@ -240,6 +257,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
offload memory transfer
uor->len -> the size of the memory chunk
uor->buf -> the memory to transfer
uor->written -> written bytes
status: none
*/
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_memory_do()");
}
return -1;
}
/*
the offload task starts after having acquired the file fd
@@ -490,6 +540,7 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
void uwsgi_offload_engines_register_all() {
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
@@ -507,3 +558,11 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
uor.ubuf = ubuf;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
uor.buf = buf;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+96 -9
View File
@@ -173,15 +173,27 @@ int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_
char *orig_subject = subject;
uint16_t orig_subject_len = subject_len;
uint32_t *r_goto = &wsgi_req->route_goto;
uint32_t *r_pc = &wsgi_req->route_pc;
if (routes == uwsgi.error_routes) {
r_goto = &wsgi_req->error_route_goto;
r_pc = &wsgi_req->error_route_pc;
}
else if (routes == uwsgi.final_routes) {
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
}
while (routes) {
if (routes->label) goto next;
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
if (*r_goto > 0 && *r_pc < *r_goto) {
goto next;
}
wsgi_req->route_goto = 0;
*r_goto = 0;
if (!routes->if_func) {
// could be a "run"
@@ -243,7 +255,7 @@ next:
subject = orig_subject;
subject_len = orig_subject_len;
routes = routes->next;
if (routes) wsgi_req->route_pc++;
if (routes) *r_pc = *r_pc+1;
}
return UWSGI_ROUTE_CONTINUE;
@@ -282,6 +294,18 @@ void uwsgi_apply_final_routes(struct wsgi_request *wsgi_req) {
uwsgi_apply_routes_do(uwsgi.final_routes, wsgi_req, NULL, 0);
}
int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
if (!uwsgi.error_routes) return 0;
// do not forget to check it !!!
if (wsgi_req->is_error_routing) return 0;
wsgi_req->is_error_routing = 1;
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
}
static void *uwsgi_route_get_condition_func(char *name) {
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
@@ -294,6 +318,14 @@ static void *uwsgi_route_get_condition_func(char *name) {
return NULL;
}
static int uwsgi_route_condition_status(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (wsgi_req->status == ur->if_status) {
return 1;
}
return 0;
}
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *space = NULL;
@@ -302,6 +334,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
ur = uwsgi.final_routes;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
ur = uwsgi.error_routes;
}
uint64_t pos = 0;
while(ur) {
old_ur = ur;
@@ -316,6 +351,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
uwsgi.final_routes = ur;
}
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
uwsgi.error_routes = ur;
}
else {
uwsgi.routes = ur;
}
@@ -364,6 +402,11 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
exit(1);
}
}
else if (!strcmp(foobar, "status")) {
ur->if_status = atoi(ur->orig_route);
foobar = ur->orig_route;
ur->if_func = uwsgi_route_condition_status;
}
else if (!strcmp(foobar, "http_host")) {
ur->subject = offsetof(struct wsgi_request, host);
@@ -515,6 +558,21 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
return 0;
}
// harakiri router
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
if (route->custom > 0) {
set_user_harakiri(route->custom);
}
return UWSGI_ROUTE_CONTINUE;
}
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_harakiri_func;
ur->custom = atoi(arg);
return 0;
}
// flush response
static int transform_flush(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
// avoid loops !!!
@@ -628,28 +686,37 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uint32_t *r_goto = &wsgi_req->route_goto;
uint32_t *r_pc = &wsgi_req->route_pc;
// find the label
struct uwsgi_route *routes = uwsgi.routes;
if (wsgi_req->is_final_routing) {
if (wsgi_req->is_error_routing) {
routes = uwsgi.error_routes;
r_goto = &wsgi_req->error_route_goto;
r_pc = &wsgi_req->error_route_pc;
}
else if (wsgi_req->is_final_routing) {
routes = uwsgi.final_routes;
r_goto = &wsgi_req->final_route_goto;
r_pc = &wsgi_req->final_route_pc;
}
while(routes) {
if (!routes->label) goto next;
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
wsgi_req->route_goto = routes->pos;
*r_goto = routes->pos;
goto found;
}
next:
routes = routes->next;
}
wsgi_req->route_goto = ur->custom;
*r_goto = ur->custom;
found:
uwsgi_buffer_destroy(ub);
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
wsgi_req->route_goto = 0;
if (*r_goto <= *r_pc) {
*r_goto = 0;
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
return UWSGI_ROUTE_BREAK;
}
@@ -1453,6 +1520,8 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("flush", uwsgi_router_flush);
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
uwsgi_register_router("harakiri", uwsgi_router_harakiri);
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
@@ -1552,7 +1621,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
void uwsgi_routing_dump() {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return;
if (!routes) goto next;
uwsgi_log("*** dumping internal routing table ***\n");
while(routes) {
if (routes->label) {
@@ -1567,6 +1636,24 @@ void uwsgi_routing_dump() {
routes = routes->next;
}
uwsgi_log("*** end of the internal routing table ***\n");
next:
routes = uwsgi.error_routes;
if (!routes) goto next2;
uwsgi_log("*** dumping internal error routing table ***\n");
while(routes) {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
routes = routes->next;
}
uwsgi_log("*** end of the internal error routing table ***\n");
next2:
routes = uwsgi.final_routes;
if (!routes) return;
uwsgi_log("*** dumping internal final routing table ***\n");
+4 -1
View File
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process) {
uwsgi_log("you cannot register signals without a master\n");
return -1;
}
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register signal handlers\n");
+3
View File
@@ -1552,6 +1552,9 @@ void uwsgi_setup_shared_sockets() {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
if (uwsgi.chown_socket) {
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
}
}
else {
#ifdef AF_INET6
+11 -10
View File
@@ -2,9 +2,9 @@
extern struct uwsgi_server uwsgi;
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
// check for filename size
if (filename_len + 4 > PATH_MAX) return 0;
if (*filename_len + 4 > PATH_MAX) return 0;
// check for supported encodings
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for dirs/prefix
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
while(usl) {
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for ext/suffix
usl = uwsgi.static_gzip_ext;
while(usl) {
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
// check for regexp
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
goto gzip;
}
url = url->next;
@@ -43,12 +43,12 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
gzip:
memcpy(filename + filename_len, ".gz\0", 4);
filename_len += 3;
memcpy(filename + *filename_len, ".gz\0", 4);
*filename_len += 3;
if (stat(filename, st)) {
filename_len -= 3;
filename[filename_len] = 0;
*filename_len -= 3;
filename[*filename_len] = 0;
return 0;
}
@@ -445,7 +445,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
@@ -579,6 +579,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
if (item && item_len > 0 && item_len <= PATH_MAX) {
memcpy(real_filename, item, item_len);
real_filename_len = item_len;
real_filename[real_filename_len] = 0;
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
goto found;
}
+47 -9
View File
@@ -206,14 +206,20 @@ void uwsgi_set_cgroup() {
usl = uwsgi.cgroup;
while (usl) {
if (mkdir(usl->value, 0700)) {
uwsgi_log("using Linux cgroup %s\n", usl->value);
int mode = strtol(uwsgi.cgroup_dir_mode, 0, 8);
if (mkdir(usl->value, mode)) {
if (errno != EEXIST) {
uwsgi_error("mkdir()");
exit(1);
}
if (chmod(usl->value, mode)) {
uwsgi_error("chmod()");
exit(1);
}
uwsgi_log("using Linux cgroup %s with mode %o\n", usl->value, mode);
}
else {
uwsgi_log("created Linux cgroup %s\n", usl->value);
uwsgi_log("created Linux cgroup %s with mode %o\n", usl->value, mode);
}
cgroup_taskfile = uwsgi_concat2(usl->value, "/tasks");
@@ -1146,7 +1152,7 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
char *app_name = key;
uint16_t app_name_len = key_len;
if (!app_name && wsgi_req) {
if (app_name_len == 0 && wsgi_req) {
app_name = wsgi_req->appid;
app_name_len = wsgi_req->appid_len;
if (app_name_len == 0) {
@@ -1208,11 +1214,7 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
}
}
if (!uwsgi.no_default_app) {
if (free_appname) free(app_name);
return uwsgi.default_app;
}
if (free_appname) free(app_name);
return -1;
}
@@ -3956,3 +3958,39 @@ void uwsgi_takeover() {
uwsgi_worker_run();
}
}
// create a message pipe
void create_msg_pipe(int *fd, int bufsize) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
#endif
uwsgi_error("create_msg_pipe()/socketpair()");
exit(1);
}
uwsgi_socket_nb(fd[0]);
uwsgi_socket_nb(fd[1]);
if (bufsize) {
if (setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
}
}
char *uwsgi_binary_path() {
return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
}
+46 -1
View File
@@ -206,6 +206,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"print-sym", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
{"print-symbol", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER, 0},
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS, 0},
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MIN_WORKER_LIFETIME, 0},
@@ -258,6 +261,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
{"mule-msg-size", optional_argument, 0, "set mule message buffer size", uwsgi_opt_set_int, &uwsgi.mule_msg_size, UWSGI_OPT_MASTER},
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
@@ -414,7 +418,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ssl-verbose", no_argument, 0, "be verbose about SSL errors", uwsgi_opt_true, &uwsgi.ssl_verbose, 0},
// force master, as ssl sessions caching initialize locking early
{"ssl-sessions-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-session-use-cache", no_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_true, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-session-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
{"ssl-sessions-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
{"ssl-session-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
@@ -535,6 +539,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"final-route", required_argument, 0, "add a final route", uwsgi_opt_add_route, "path_info", 0},
{"final-route-status", required_argument, 0, "add a final route for the specified status", uwsgi_opt_add_route, "status", 0},
{"final-route-host", required_argument, 0, "add a final route based on Host header", uwsgi_opt_add_route, "http_host", 0},
{"final-route-uri", required_argument, 0, "add a final route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
{"final-route-qs", required_argument, 0, "add a final route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
@@ -547,6 +552,20 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"final-route-if-not", required_argument, 0, "add a final route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"final-route-run", required_argument, 0, "always run the specified final route action", uwsgi_opt_add_route, "run", 0},
{"error-route", required_argument, 0, "add an error route", uwsgi_opt_add_route, "path_info", 0},
{"error-route-status", required_argument, 0, "add an error route for the specified status", uwsgi_opt_add_route, "status", 0},
{"error-route-host", required_argument, 0, "add an error route based on Host header", uwsgi_opt_add_route, "http_host", 0},
{"error-route-uri", required_argument, 0, "add an error route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
{"error-route-qs", required_argument, 0, "add an error route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
{"error-route-remote-addr", required_argument, 0, "add an error route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
{"error-route-user-agent", required_argument, 0, "add an error route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
{"error-route-remote-user", required_argument, 0, "add an error route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
{"error-route-referer", required_argument, 0, "add an error route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
{"error-route-label", required_argument, 0, "add an error routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
{"error-route-if", required_argument, 0, "add an error route based on condition", uwsgi_opt_add_route, "if", 0},
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
#endif
@@ -620,6 +639,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
#ifdef __linux__
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
{"cgroup-dir-mode", required_argument, 0, "set permission for cgroup directory (default is 700)", uwsgi_opt_set_str, &uwsgi.cgroup_dir_mode, 0},
{"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
{"namespace-keep-mount", required_argument, 0, "keep the specified mountpoint in your namespace", uwsgi_opt_add_string_list, &uwsgi.ns_keep_mount, 0},
{"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
@@ -636,9 +656,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
{"cron2", required_argument, 0, "add a cron task (key=val syntax)", uwsgi_opt_add_cron2, NULL, UWSGI_OPT_MASTER},
{"unique-cron", required_argument, 0, "add a unique cron task", uwsgi_opt_add_unique_cron, NULL, UWSGI_OPT_MASTER},
{"cron-harakiri", required_argument, 0, "set the maximum time (in seconds) we wait for cron command to complete", uwsgi_opt_set_int, &uwsgi.cron_harakiri, 0},
#ifdef UWSGI_SSL
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
{"unique-legion-cron", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
{"unique-cron-legion", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
#endif
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
@@ -4080,3 +4105,23 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
};
exit(0);
}
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
char *sym = dlsym(RTLD_DEFAULT, symbol);
if (sym) {
uwsgi_log("%s", sym);
exit(0);
}
char *symbol_start = uwsgi_concat2(symbol, "_start");
char *symbol_end = uwsgi_concat2(symbol, "_end");
char *sym_s = dlsym(RTLD_DEFAULT, symbol_start);
char *sym_e = dlsym(RTLD_DEFAULT, symbol_end);
if (sym_s && sym_e) {
uwsgi_log("%.*s", sym_e - sym_s, sym_s);
}
exit(0);
}
+22 -3
View File
@@ -76,7 +76,19 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
// reset the buffer (could be useful for rollbacks...)
wsgi_req->headers->pos = 0;
// reset headers count
wsgi_req->header_cnt = 0;
struct uwsgi_buffer *hh = NULL;
wsgi_req->status = uwsgi_str3_num(status);
#ifdef UWSGI_ROUTING
// apply error routes
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_error_routing = 0;
#endif
if (status_len <= 4) {
char *new_sc = NULL;
size_t new_sc_len = 0;
@@ -99,7 +111,6 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
if (!hh) {wsgi_req->write_errors++; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
uwsgi_buffer_destroy(hh);
wsgi_req->status = uwsgi_str3_num(status);
return 0;
error:
uwsgi_buffer_destroy(hh);
@@ -208,6 +219,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
@@ -270,8 +282,10 @@ sendbody:
}
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
}
int can_close = 1;
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len, int can_close) {
if (fd == wsgi_req->sendfile_fd) can_close = 0;
@@ -280,6 +294,11 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
return -1;
}
if (wsgi_req->ignore_body) {
if (can_close) close(fd);
return UWSGI_OK;
}
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendfile;
@@ -294,7 +313,7 @@ sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
+3 -3
View File
@@ -214,7 +214,7 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
// "Status: NNN"
if (header_size >= 11) {
if (!strncasecmp("Status: ", key, 8)) {
uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8);
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
status_sent = 1;
key = NULL;
value = NULL;
@@ -229,13 +229,13 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
// Location: X
if (header_size >= 11) {
if (!strncasecmp("Location: ", key, 10)) {
uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9);
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
status_sent = 1;
}
}
if (status_sent == 0) {
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
status_sent = 1;
}
}
-4
View File
@@ -44,10 +44,6 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
peers->in = uwsgi_buffer_new(uwsgi.page_size);
// add timeout
peers->timeout = cr_add_timeout(cs->corerouter, peers);
// check retry
if (cs->retry) {
peers->can_retry = 1;
}
peers->prev = old_peers;
if (old_peers) {
+5
View File
@@ -172,6 +172,9 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
cr_peer_connected(peer, "fr_instance_connected()");
// we are connected, we cannot retry anymore
peer->can_retry = 0;
// fix modifiers
peer->in->buf[0] = peer->session->main_peer->modifier1;
peer->in->buf[3] = peer->session->main_peer->modifier2;
@@ -217,6 +220,8 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
if (new_peer->instance_address_len == 0)
return -1;
new_peer->can_retry = 1;
cr_connect(new_peer, fr_instance_connected);
}
+34 -3
View File
@@ -121,7 +121,6 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
hr->content_length = uwsgi_str_num(val, vallen);
hr->session.can_keepalive = 0;
}
// in the future we could support chunked requests...
@@ -183,19 +182,28 @@ int http_headers_parse(struct corerouter_peer *peer) {
peer->out_pos = 0;
struct uwsgi_buffer *out = peer->out;
int found = 0;
// REQUEST_METHOD
while (ptr < watermark) {
if (*ptr == ' ') {
if (uwsgi_buffer_append_keyval(out, "REQUEST_METHOD", 14, base, ptr - base)) return -1;
ptr++;
found = 1;
break;
}
else if (*ptr == '\r' || *ptr == '\n') break;
ptr++;
}
// ensure we have a method
if (!found) {
return -1;
}
// REQUEST_URI / PATH_INFO / QUERY_STRING
base = ptr;
found = 0;
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
// PATH_INFO must be url-decoded !!!
@@ -221,13 +229,20 @@ int http_headers_parse(struct corerouter_peer *peer) {
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, query_string, ptr - query_string)) return -1;
}
ptr++;
found = 1;
break;
}
ptr++;
}
// ensure we have a URI
if (!found) {
return -1;
}
// SERVER_PROTOCOL
base = ptr;
found = 0;
while (ptr < watermark) {
if (*ptr == '\r') {
if (ptr + 1 >= watermark)
@@ -239,11 +254,17 @@ int http_headers_parse(struct corerouter_peer *peer) {
hr->session.can_keepalive = 1;
}
ptr += 2;
found = 1;
break;
}
ptr++;
}
// ensure we have a protocol
if (!found) {
return -1;
}
// SCRIPT_NAME
if (uwsgi_buffer_append_keyval(out, "SCRIPT_NAME", 11, "", 0)) return -1;
@@ -459,6 +480,8 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
struct http_session *hr = (struct http_session *) peer->session;
ssize_t len = cr_read(peer, "hr_instance_read()");
if (!len) {
// disable keepalive on unread body
if (hr->content_length) hr->session.can_keepalive = 0;
if (hr->session.can_keepalive) {
peer->session->main_peer->disabled = 0;
hr->rnrn = 0;
@@ -575,9 +598,16 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (main_peer->in->pos > hr->content_length) {
main_peer->in->pos = hr->content_length;
hr->content_length = 0;
// on pipeline attempt, disable keepalive
hr->session.can_keepalive = 0;
}
else {
hr->content_length -= main_peer->in->pos;
if (hr->content_length == 0) {
main_peer->disabled = 1;
// stop reading from the client
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
}
}
}
}
@@ -649,10 +679,11 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
if (hr->remains > 0) {
hr->session.can_keepalive = 0;
if (hr->content_length < hr->remains) {
hr->remains = hr->content_length;
hr->content_length = 0;
// we need to avoid problems with pipelined requests
hr->session.can_keepalive = 0;
}
else {
hr->content_length -= hr->remains;
@@ -660,7 +691,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (uwsgi_buffer_append(new_peer->out, main_peer->in->buf + hr->headers_size + 1, hr->remains)) return -1;
}
if (hr->session.can_keepalive) {
if (hr->session.can_keepalive && hr->content_length == 0) {
main_peer->disabled = 1;
// stop reading from the client
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
+1 -1
View File
@@ -547,7 +547,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
pthread_mutex_lock(&umono.lock_loader);
}
// check if the mean time, something changed
// check if in the mean time, something changed
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
if (wsgi_req->app_id == -1) {
+21 -10
View File
@@ -394,33 +394,44 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
if (wsgi_req->script_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
}
else if (wsgi_req->file_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
}
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == psgi_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
}
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1) {
uwsgi_500(wsgi_req);
uwsgi_log("--- unable to find perl application ---\n");
// nothing to clear/free
return UWSGI_OK;
}
}
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
wi->requests++;
@@ -712,7 +723,7 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
STRLEN rlen;
SV *response = POPs;
char *value = SvPV(response, rlen );
ret = UMIN(UMAX16, rlen);
ret = UMIN(UMAX16-1, rlen);
memcpy(buffer, value, ret);
}
+30
View File
@@ -0,0 +1,30 @@
This is a bit convoluted, but you run it (so far) this way:
You have to compile PyPy with strange options. I'll explain them below.
In the pypy checkout, run:
./rpython/bin/rpython -Ojit --shared --gcrootfinder=shadowstack pypy/goal/targetpypystandalone
Options:
-Ojit - standard PyPy build with JIT
--shared - as expected, creates a .so
--gcrootfinder - on linux, the default rootfinder is asmgcc which has trouble
with position independent code. This option is not needed
on OS X or windows.
If for some strange/dangerous/wrong reason your uWSGI binary is linked with cpython you could have name collisions
with pypy cpyext. In such crazy case you can remove cpyext support with:
./rpython/bin/rpython -Ojit --shared --gcrootfinder=shadowstack pypy/goal/targetpypystandalone --withoutmod-cpyext
By default the pypy uWSGI plugin will load the libpypy-c.so library. You should have it in the LD_LIBRARY_PATH, otherwise you can set its path
with --pypy-lib option (pass an absolute path to it)
You have to specify the pypy home too, you can use the --pypy-home option or the PYPY_HOME var
PYPY_HOME=/home/user/pypy/lib_pypy uwsgi --pypy-lib /opt/pypy/libpypy-c.so --http-socket :9090 --pypy-wsgi werkzeug.testapp:test_app
The funny part about the uWSGI pypy plugin is that it is mainly written in python. The pypy_setup.py script is linked to the plugin, but you can override
it with the --pypy-setup option
+360
View File
@@ -0,0 +1,360 @@
/*******************************************************************
This is the C part of the PyPy plugin (with the main logic being in
Python, see pypy_setup.py).
Idea and initial implementation by Maciej Fijalkowski
*******************************************************************/
#include <uwsgi.h>
struct uwsgi_pypy {
void *handler;
char *lib;
char *setup;
char *home;
char *wsgi;
char *wsgi_file;
struct uwsgi_string_list *eval;
struct uwsgi_string_list *eval_post_fork;
struct uwsgi_string_list *exec;
struct uwsgi_string_list *exec_post_fork;
struct uwsgi_string_list *pp;
} upypy;
// the functions exposed by libpypy-c
char *(*rpython_startup_code)(void);
int (*pypy_setup_home)(char *, int);
int (*pypy_execute_source)(char *);
void (*pypy_thread_attach)(void);
void (*pypy_init_threads)(void);
// the hooks you can override with pypy
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_file_loader)(char *);
void (*uwsgi_pypy_hook_pythonpath)(char *);
void (*uwsgi_pypy_hook_request)(void *, int);
void (*uwsgi_pypy_post_fork_hook)(void);
extern struct uwsgi_server uwsgi;
struct uwsgi_plugin pypy_plugin;
int uwsgi_pypy_helper_masterpid() {
if (uwsgi.master_process) {
return uwsgi.workers[0].pid;
}
return 0;
}
int uwsgi_pypy_helper_worker_id() {
return uwsgi.mywid;
}
int uwsgi_pypy_helper_mule_id() {
return uwsgi.muleid;
}
void uwsgi_pypy_helper_signal(int signum) {
uwsgi_signal_send(uwsgi.signal_socket, signum);
}
struct uwsgi_opt **uwsgi_pypy_helper_opts(int *n) {
*n = uwsgi.exported_opts_cnt;
return uwsgi.exported_opts;
}
char *uwsgi_pypy_helper_version() {
return UWSGI_VERSION;
}
int uwsgi_pypy_helper_register_signal(int signum, char *kind, void *handler) {
return uwsgi_register_signal(signum, kind, handler, pypy_plugin.modifier1);
}
int uwsgi_pypy_helper_register_rpc(char *name, int argc, void *func) {
return uwsgi_register_rpc(name, &pypy_plugin, argc, func);
}
struct iovec *uwsgi_pypy_helper_environ(struct wsgi_request *wsgi_req, uint16_t *len) {
*len = wsgi_req->var_cnt;
return wsgi_req->hvec;
}
static int uwsgi_pypy_init() {
size_t rlen = 0;
char *buffer = NULL;
void *is_cpython_loaded = dlsym(RTLD_DEFAULT, "Py_Initialize");
if (is_cpython_loaded) {
uwsgi_log("!!! Loading both PyPy and CPython in the same process IS PURE EVIL AND IT IS NOT SUPPORTED !!!\n");
exit(1);
}
if (upypy.lib) {
upypy.handler = dlopen(upypy.lib, RTLD_NOW | RTLD_GLOBAL);
}
else {
if (upypy.home) {
#ifdef __APPLE__
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
#else
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
#endif
if (uwsgi_file_exists(libpath)) {
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
}
free(libpath);
}
// fallback to standard library search path
if (!upypy.handler) {
#ifdef __APPLE__
upypy.handler = dlopen("libpypy-c.dylib", RTLD_NOW | RTLD_GLOBAL);
#else
upypy.handler = dlopen("libpypy-c.so", RTLD_NOW | RTLD_GLOBAL);
#endif
}
}
if (!upypy.handler) {
uwsgi_log("unable to load pypy library: %s\n", dlerror());
exit(1);
}
rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!rpython_startup_code) {
uwsgi_log("unable to find rpython_startup_code() symbol\n");
exit(1);
}
pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!pypy_setup_home) {
uwsgi_log("unable to find pypy_setup_home() symbol\n");
exit(1);
}
pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!pypy_init_threads) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_init_threads, multithreading will not work !!!\n");
}
rpython_startup_code();
if (!upypy.home) {
upypy.home = getenv("PYPY_HOME");
if (!upypy.home) {
uwsgi_log("you have to specify a pypy home with --pypy-home\n");
exit(1);
}
}
if (pypy_setup_home(upypy.home, 0)) {
char *retry = uwsgi_concat2(upypy.home, "/lib_pypy");
if (uwsgi_is_dir(retry)) {
// this time we use debug
if (!pypy_setup_home(retry, 1)) {
free(retry);
goto ready;
}
}
uwsgi_log("unable to set pypy home to \"%s\"\n", upypy.home);
exit(1);
}
ready:
if (upypy.setup) {
buffer = uwsgi_open_and_read(upypy.setup, &rlen, 1, NULL);
}
else {
char *start = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_start");
char *end = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_end");
if (start && end) {
buffer = uwsgi_concat2n(start, end-start, "", 0);
}
}
if (!buffer) {
uwsgi_log("you have to load a pypy setup file with --pypy-setup\n");
exit(1);
}
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
// add items to the pythonpath
struct uwsgi_string_list *usl = upypy.pp;
while(usl) {
if (uwsgi_pypy_hook_pythonpath) {
uwsgi_pypy_hook_pythonpath(usl->value);
}
usl = usl->next;
}
return 0;
}
static void uwsgi_pypy_preinit_apps() {
struct uwsgi_string_list *usl = upypy.eval;
while(usl) {
if (pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
}
usl = upypy.exec;
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
usl = usl->next;
}
}
static int uwsgi_pypy_request(struct wsgi_request *wsgi_req) {
/* Standard WSGI request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Empty pypy request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (uwsgi_pypy_hook_request) {
uwsgi_pypy_hook_request(wsgi_req, wsgi_req->async_id);
}
return UWSGI_OK;
}
static void uwsgi_pypy_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static void uwsgi_pypy_init_apps() {
if (uwsgi_pypy_hook_loader && upypy.wsgi) {
uwsgi_pypy_hook_loader(upypy.wsgi);
}
if (uwsgi_pypy_hook_file_loader && upypy.wsgi_file) {
uwsgi_pypy_hook_file_loader(upypy.wsgi_file);
}
}
/*
static void uwsgi_pypy_atexit() {
if (pypy_debug_file)
fflush(pypy_debug_file);
}
*/
static struct uwsgi_option uwsgi_pypy_options[] = {
{"pypy-lib", required_argument, 0, "set the path/name of the pypy library", uwsgi_opt_set_str, &upypy.lib, 0},
{"pypy-setup", required_argument, 0, "set the path of the python setup script", uwsgi_opt_set_str, &upypy.setup, 0},
{"pypy-home", required_argument, 0, "set the home of pypy library", uwsgi_opt_set_str, &upypy.home, 0},
{"pypy-wsgi", required_argument, 0, "load a WSGI module", uwsgi_opt_set_str, &upypy.wsgi, 0},
{"pypy-wsgi-file", required_argument, 0, "load a WSGI/mod_wsgi file", uwsgi_opt_set_str, &upypy.wsgi_file, 0},
{"pypy-eval", required_argument, 0, "evaluate pypy code before fork()", uwsgi_opt_add_string_list, &upypy.eval, 0},
{"pypy-eval-post-fork", required_argument, 0, "evaluate pypy code soon after fork()", uwsgi_opt_add_string_list, &upypy.eval_post_fork, 0},
{"pypy-exec", required_argument, 0, "execute pypy code from file before fork()", uwsgi_opt_add_string_list, &upypy.exec, 0},
{"pypy-exec-post-fork", required_argument, 0, "execute pypy code from file soon after fork()", uwsgi_opt_add_string_list, &upypy.exec_post_fork, 0},
{"pypy-pp", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{"pypy-python-path", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{"pypy-pythonpath", required_argument, 0, "add an item to the pythonpath", uwsgi_opt_add_string_list, &upypy.pp, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static void uwsgi_pypy_enable_threads() {
if (pypy_init_threads) {
pypy_init_threads();
}
}
static void uwsgi_pypy_init_thread() {
if (pypy_thread_attach) {
pypy_thread_attach();
}
}
static int uwsgi_pypy_signal_handler(uint8_t sig, void *handler) {
void (*pypy_func)(int) = (void(*)(int)) handler;
pypy_func(sig);
return 0;
}
static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
int iargvs[UMAX8];
int i;
int (*pypy_func)(int, char **, int*, char *) = (int (*)(int, char **, int*, char *)) func;
// we convert 16bit to int
for(i=0;i<argc;i++) {
iargvs[i] = (int) argvs[i];
}
return pypy_func(argc, argv, iargvs, buffer);
}
static void uwsgi_pypy_post_fork() {
struct uwsgi_string_list *usl = upypy.eval_post_fork;
while(usl) {
if (pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
}
usl = upypy.exec_post_fork;
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
usl = usl->next;
}
if (uwsgi_pypy_post_fork_hook) {
uwsgi_pypy_post_fork_hook();
}
}
static void uwsgi_pypy_onload() {
#ifdef UWSGI_PYPY_HOME
upypy.home = UWSGI_PYPY_HOME;
#endif
}
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
.modifier1 = 0,
.on_load = uwsgi_pypy_onload,
.init = uwsgi_pypy_init,
.request = uwsgi_pypy_request,
.after_request = uwsgi_pypy_after_request,
.options = uwsgi_pypy_options,
.preinit_apps = uwsgi_pypy_preinit_apps,
.init_apps = uwsgi_pypy_init_apps,
.init_thread = uwsgi_pypy_init_thread,
.signal_handler = uwsgi_pypy_signal_handler,
.enable_threads = uwsgi_pypy_enable_threads,
.rpc = uwsgi_pypy_rpc,
.post_fork = uwsgi_pypy_post_fork,
};
+463
View File
@@ -0,0 +1,463 @@
import sys
import os
sys.path.insert(0, '.')
sys.path.extend(os.environ.get('PYTHONPATH','').split(os.pathsep))
import imp
import traceback
__name__ = '__main__'
mainmodule = type(sys)('__main__')
sys.modules['__main__'] = mainmodule
import cffi
# this is a list holding object we do not want to be freed (like callback and handlers)
uwsgi_gc = []
defines = '''
void free(void *);
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_file_loader)(char *);
void (*uwsgi_pypy_hook_pythonpath)(char *);
void (*uwsgi_pypy_hook_request)(void *, int);
void (*uwsgi_pypy_post_fork_hook)(void);
struct iovec {
char *iov_base;
uint64_t iov_len;
};
struct uwsgi_opt {
char *key;
char *value;
int configured;
};
char *uwsgi_binary_path();
void uwsgi_set_processname(char *);
void uwsgi_alarm_trigger(char *, char *, uint64_t);
int uwsgi_signal_registered(uint8_t);
int uwsgi_response_write_body_do(void *, char *, uint64_t);
int uwsgi_response_sendfile_do_can_close(void *, int, uint64_t, uint64_t, int);
int uwsgi_response_prepare_headers(void *, char *, uint16_t);
int uwsgi_response_add_header(void *, char *, uint16_t, char *, uint16_t);
char *uwsgi_request_body_read(void *, uint64_t, int64_t *);
char *uwsgi_request_body_readline(void *, uint64_t, int64_t *);
struct iovec *uwsgi_pypy_helper_environ(void *, uint16_t *);
char *uwsgi_pypy_helper_version();
int uwsgi_pypy_helper_register_signal(int, char *, void *);
int uwsgi_pypy_helper_register_rpc(char *, int, void *);
void uwsgi_pypy_helper_signal(int);
struct uwsgi_opt** uwsgi_pypy_helper_opts(int *);
int uwsgi_pypy_helper_masterpid();
int uwsgi_pypy_helper_worker_id();
int uwsgi_pypy_helper_mule_id();
char *uwsgi_cache_magic_get(char *, uint64_t, uint64_t *, uint64_t *, char *);
int uwsgi_cache_magic_set(char *, uint64_t, char *, uint64_t, uint64_t, uint64_t, char *);
int uwsgi_cache_magic_del(char *, uint64_t, char *);
int uwsgi_add_timer(uint8_t, int);
int uwsgi_add_rb_timer(uint8_t, int, int);
int uwsgi_add_file_monitor(uint8_t, char *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
int uwsgi_user_lock(int);
int uwsgi_user_unlock(int);
'''
ffi = cffi.FFI()
ffi.cdef(defines)
lib = ffi.verify(defines)
libc = ffi.dlopen(None)
"""
this is a global object point the the WSGI callable
it sucks, i will fix it in the near future...
"""
wsgi_application = None
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
"""
load a wsgi module
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_loader(module):
global wsgi_application
m = ffi.string(module)
c = 'application'
if ':' in m:
m, c = m.split(':')
if '.' in m:
mod = __import__(m, None, None, '*')
else:
mod = __import__(m)
wsgi_application = getattr(mod, c)
"""
load a mod_wsgi compliant .wsgi file
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_file_loader(filename):
global wsgi_application
w = ffi.string(filename)
c = 'application'
mod = imp.load_source('uwsgi_file_wsgi', w)
wsgi_application = getattr(mod, c)
"""
.post_fork_hokk
"""
@ffi.callback("void()")
def uwsgi_pypy_post_fork_hook():
import uwsgi
if hasattr(uwsgi, 'post_fork_hook'):
uwsgi.post_fork_hook()
"""
add an item to the pythonpath
"""
@ffi.callback("void(char *)")
def uwsgi_pypy_pythonpath(item):
path = ffi.string(item)
sys.path.append(path)
print "added %s to pythonpath" % path
"""
class implementing wsgi.file_wrapper
"""
class WSGIfilewrapper(object):
def __init__(self, wsgi_req, f, chunksize=0):
self.wsgi_req = wsgi_req
self.f = f
self.chunksize = chunksize
if hasattr(f, 'close'):
self.close = f.close
def __iter__(self):
return self
def sendfile(self):
if hasattr(self.f, 'fileno'):
lib.uwsgi_response_sendfile_do_can_close(self.wsgi_req, self.f.fileno(), 0, 0, 0)
elif hasattr(self.f, 'read'):
if self.chunksize == 0:
chunk = self.f.read()
if len(chunk) > 0:
lib.uwsgi_response_write_body_do(self.wsgi_req, ffi.new("char[]", chunk), len(chunk))
return
while True:
chunk = self.f.read(self.chunksize)
if chunk is None or len(chunk) == 0:
break
lib.uwsgi_response_write_body_do(self.wsgi_req, ffi.new("char[]", chunk), len(chunk))
"""
class implementing wsgi.input
"""
class WSGIinput(object):
def __init__(self, wsgi_req):
self.wsgi_req = wsgi_req
def read(self, size=0):
rlen = ffi.new('int64_t*')
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
if rlen[0] < 0:
raise IOError("error reading wsgi.input")
raise IOError("error waiting for wsgi.input")
def getline(self, hint=0):
rlen = ffi.new('int64_t*')
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
if rlen[0] < 0:
raise IOError("error reading line from wsgi.input")
raise IOError("error waiting for line on wsgi.input")
def readline(self, hint=0):
return self.getline(hint)
def readlines(self, hint=0):
lines = []
while True:
chunk = self.getline(hint)
if len(chunk) == 0:
break
lines.append(chunk)
return lines
def __iter__(self):
return self
def __next__(self):
chunk = self.getline()
if len(chunk) == 0:
raise StopIteration
return chunk
"""
the WSGI request handler
"""
@ffi.callback("void(void *, int)")
def uwsgi_pypy_wsgi_handler(wsgi_req, core):
global wsgi_application
def writer(data):
lib.uwsgi_response_write_body_do(wsgi_req, ffi.new("char[]", data), len(data))
def start_response(status, headers, exc_info=None):
if exc_info:
traceback.print_exception(*exc_info)
lib.uwsgi_response_prepare_headers(wsgi_req, ffi.new("char[]", status), len(status))
for hh in headers:
lib.uwsgi_response_add_header(wsgi_req, ffi.new("char[]", hh[0]), len(hh[0]), ffi.new("char[]", hh[1]), len(hh[1]))
return writer
environ = {}
nv = ffi.new("uint16_t*")
iov = lib.uwsgi_pypy_helper_environ(wsgi_req, nv)
for i in range(0, nv[0], 2):
environ[ffi.string(iov[i].iov_base, iov[i].iov_len)] = ffi.string(iov[i+1].iov_base, iov[i+1].iov_len)
environ['wsgi.version'] = (1, 0)
scheme = 'http'
if 'HTTPS' in environ:
if environ['HTTPS'] in ('on', 'ON', 'On', '1', 'true', 'TRUE', 'True'):
scheme = 'https'
environ['wsgi.url_scheme'] = environ.get('UWSGI_SCHEME', scheme)
environ['wsgi.input'] = WSGIinput(wsgi_req)
environ['wsgi.errors'] = sys.stderr
environ['wsgi.run_once'] = False
environ['wsgi.file_wrapper'] = lambda f, chunksize=0: WSGIfilewrapper(wsgi_req, f, chunksize)
environ['wsgi.multithread'] = True
environ['wsgi.multiprocess'] = True
environ['uwsgi.core'] = core
response = wsgi_application(environ, start_response)
if type(response) is str:
writer(response)
else:
try:
if isinstance(response, WSGIfilewrapper):
response.sendfile()
else:
for chunk in response:
if isinstance(chunk, WSGIfilewrapper):
try:
chunk.sendfile()
finally:
chunk.close()
else:
writer(chunk)
finally:
if hasattr(response, 'close'):
response.close()
lib.uwsgi_pypy_hook_loader = uwsgi_pypy_loader
lib.uwsgi_pypy_hook_file_loader = uwsgi_pypy_file_loader
lib.uwsgi_pypy_hook_pythonpath = uwsgi_pypy_pythonpath
lib.uwsgi_pypy_hook_request = uwsgi_pypy_wsgi_handler
lib.uwsgi_pypy_post_fork_hook = uwsgi_pypy_post_fork_hook
"""
Here we define the "uwsgi" virtual module
"""
uwsgi = imp.new_module('uwsgi')
sys.modules['uwsgi'] = uwsgi
uwsgi.version = ffi.string(lib.uwsgi_pypy_helper_version())
def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
cb = ffi.callback('void(int)', handler)
uwsgi_gc.append(cb)
if lib.uwsgi_pypy_helper_register_signal(signum, ffi.new("char[]", kind), cb) < 0:
raise Exception("unable to register signal %d" % signum)
uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal
class uwsgi_pypy_RPC(object):
def __init__(self, func):
self.func = func
def __call__(self, argc, argv, argvs, buf):
pargs = []
for i in range(0, argc):
pargs.append(ffi.string(argv[i], argvs[i]))
response = self.func(*pargs)
if len(response) > 0 and len(response) <= 65535:
dst = ffi.buffer(buf, 65536)
dst[:len(response)] = response
return len(response)
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_pypy_helper_register_rpc(ffi.new("char[]", name), argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
def uwsgi_pypy_rpc(node, func, *args):
argc = 0
argv = ffi.new('char*[256]')
argvs = ffi.new('uint16_t[256]')
rsize = ffi.new('uint16_t*')
for arg in args:
if argc >= 255:
raise Exception('invalid number of rpc arguments')
if len(arg) >= 65535:
raise Exception('invalid rpc argument size (must be < 65535)')
argv[argc] = ffi.new('char[]', arg)
argvs[argc] = len(arg)
argc += 1
if node:
c_node = ffi.new("char[]", node)
else:
c_node = ffi.NULL
response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize)
if response:
ret = ffi.string(response, rsize[0])
lib.free(response)
return ret
return None
uwsgi.rpc = uwsgi_pypy_rpc
def uwsgi_pypy_call(func, *args):
node = None
if '@' in func:
(func, node) = func.split('@')
return uwsgi_pypy_rpc(node, func, *args)
uwsgi.call = uwsgi_pypy_call
def uwsgi_pypy_uwsgi_signal(signum):
lib.uwsgi_pypy_helper_signal(signum)
uwsgi.signal = uwsgi_pypy_uwsgi_signal
def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
vallen = ffi.new('uint64_t*')
value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache)
if value == ffi.NULL:
return None
ret = ffi.string(value, vallen[0])
libc.free(value)
return ret
uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get
def uwsgi_pypy_uwsgi_cache_set(key, value, expires=0, cache=ffi.NULL):
if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 0, cache) < 0:
raise Exception('unable to store item in the cache')
uwsgi.cache_set = uwsgi_pypy_uwsgi_cache_set
def uwsgi_pypy_uwsgi_cache_update(key, value, expires=0, cache=ffi.NULL):
if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 1 << 1, cache) < 0:
raise Exception('unable to store item in the cache')
uwsgi.cache_update = uwsgi_pypy_uwsgi_cache_update
def uwsgi_pypy_uwsgi_cache_del(key, cache=ffi.NULL):
if lib.uwsgi_cache_magic_del(key, len(key), cache) < 0:
raise Exception('unable to delete item from the cache')
uwsgi.cache_del = uwsgi_pypy_uwsgi_cache_del
def uwsgi_pypy_uwsgi_add_timer(signum, secs):
if lib.uwsgi_add_timer(signum, secs) < 0:
raise Exception("unable to register timer")
uwsgi.add_timer = uwsgi_pypy_uwsgi_add_timer
def uwsgi_pypy_uwsgi_add_rb_timer(signum, secs):
if lib.uwsgi_add_rb_timer(signum, secs, 0) < 0:
raise Exception("unable to register redblack timer")
uwsgi.add_rb_timer = uwsgi_pypy_uwsgi_add_rb_timer
def uwsgi_pypy_uwsgi_add_file_monitor(signum, filename):
if lib.uwsgi_add_file_monitor(signum, ffi.new("char[]", filename)) < 0:
raise Exception("unable to register file monitor")
uwsgi.add_file_monitor = uwsgi_pypy_uwsgi_add_file_monitor
def uwsgi_pypy_lock(num):
if lib.uwsgi_user_lock(num) < 0:
raise Exception("invalid lock")
uwsgi.lock = uwsgi_pypy_lock
def uwsgi_pypy_unlock(num):
if lib.uwsgi_user_unlock(num) < 0:
raise Exception("invalid lock")
uwsgi.unlock = uwsgi_pypy_unlock
def uwsgi_pypy_masterpid():
return lib.uwsgi_pypy_helper_masterpid()
uwsgi.masterpid = uwsgi_pypy_masterpid
def uwsgi_pypy_worker_id():
return lib.uwsgi_pypy_helper_worker_id()
uwsgi.worker_id = uwsgi_pypy_worker_id
def uwsgi_pypy_mule_id():
return lib.uwsgi_pypy_helper_mule_id()
uwsgi.mule_id = uwsgi_pypy_mule_id
def uwsgi_pypy_signal_registered(signum):
if lib.uwsgi_signal_registered(signum) > 0:
return True
return False
uwsgi.signal_registered = uwsgi_pypy_signal_registered
def uwsgi_pypy_alarm(alarm, msg):
lib.uwsgi_alarm_trigger(ffi.new('char[]', alarm), ffi.new('char[]', msg), len(msg))
uwsgi.alarm = uwsgi_pypy_alarm
def uwsgi_pypy_setprocname(name):
lib.uwsgi_set_processname(ffi.new('char[]',name))
uwsgi.setprocname = uwsgi_pypy_setprocname
def uwsgi_pypy_add_cron(signum, minute, hour, day, month, week):
if lib.uwsgi_signal_add_cron(signum, minute, hour, day, month, week) < 0:
raise Exception("unable to register cron")
return True
uwsgi.add_cron = uwsgi_pypy_add_cron
"""
populate uwsgi.opt
"""
uwsgi.opt = {}
n_opts = ffi.new('int*')
u_opts = lib.uwsgi_pypy_helper_opts(n_opts)
for i in range(0, n_opts[0]):
k = ffi.string(u_opts[i].key)
if u_opts[i].value == ffi.NULL:
v = True
else:
v = ffi.string(u_opts[i].value)
if k in uwsgi.opt:
if type(uwsgi.opt[k]) is list:
uwsgi.opt[k].append(v)
else:
uwsgi.opt[k] = [uwsgi.opt[k], v]
else:
uwsgi.opt[k] = v
print "Initialized PyPy with Python", sys.version
print "PyPy Home:", sys.prefix
+10 -11
View File
@@ -1,13 +1,12 @@
import os,sys
from distutils import sysconfig
NAME='pypy'
GCC_LIST = ['../python/python_plugin', '../python/pyutils', '../python/pyloader', '../python/wsgi_handlers', '../python/wsgi_headers', '../python/wsgi_subhandler',
'../python/web3_subhandler', '../python/pump_subhandler','../python/gil', '../python/uwsgi_pymodule', '../python/profiler', '../python/symimporter']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
CFLAGS.append('-DUWSGI_PYPY')
LIBS = ['-lpypy-c']
LDFLAGS = []
LIBS = []
GCC_LIST = ['pypy_plugin']
BINARY_LIST = [ ('uwsgi_pypy_setup','pypy_setup.py')]
CFLAGS = []
try:
import __pypy__
import sys
CFLAGS.append('-DUWSGI_PYPY_HOME="\\"%s\\""' % sys.prefix)
except:
pass
+2 -2
View File
@@ -5,7 +5,7 @@ extern struct uwsgi_python up;
void gil_real_get() {
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
PyEval_AcquireLock();
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
#else
@@ -17,7 +17,7 @@ void gil_real_get() {
void gil_real_release() {
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
PyEval_ReleaseLock();
#else
-4
View File
@@ -15,7 +15,6 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
@@ -42,14 +41,12 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
break;
}
#endif
return 0;
}
int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
#ifndef UWSGI_PYPY
static uint64_t last_ts = 0;
uint64_t now = uwsgi_micros();
uint64_t delta = 0;
@@ -64,7 +61,6 @@ int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject
last_ts = now;
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
}
#endif
return 0;
}
-5
View File
@@ -672,10 +672,6 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *uwsgi_eval_loader(void *arg1) {
#ifdef UWSGI_PYPY
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
return NULL;
#else
char *code = (char *) arg1;
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
@@ -731,7 +727,6 @@ PyObject *uwsgi_eval_loader(void *arg1) {
}
return wsgi_eval_callable;
#endif
}
+6 -44
View File
@@ -52,11 +52,7 @@ void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
}
void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
#ifndef UWSGI_PYPY
const char *version = Py_GetVersion();
#else
const char *version = PYPY_VERSION;
#endif
const char *space = strchr(version, ' ');
if (space) {
fprintf(stdout, "%.*s\n", (int) (space-version), version);
@@ -136,9 +132,7 @@ struct uwsgi_option uwsgi_python_options[] = {
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
#ifndef __CYGWIN__
#ifndef UWSGI_PYPY
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
#endif
#endif
{"pyshell", optional_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
{"pyshell-oneshot", optional_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
@@ -147,9 +141,8 @@ struct uwsgi_option uwsgi_python_options[] = {
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
#ifndef UWSGI_PYPY
{"py-tracebacker", required_argument, 0, "enable the uWSGI python tracebacker", uwsgi_opt_set_str, &up.tracebacker, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
#endif
{"py-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
{"py-autoreload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
{"python-auto-reload", required_argument, 0, "monitor python modules mtime to trigger reload (use only in development)", uwsgi_opt_set_int, &up.auto_reload, UWSGI_OPT_THREADS|UWSGI_OPT_MASTER},
@@ -183,7 +176,6 @@ PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARG
int uwsgi_python_init() {
#ifndef UWSGI_PYPY
char *pyversion = strchr(Py_GetVersion(), '\n');
if (!pyversion) {
uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
@@ -191,9 +183,6 @@ int uwsgi_python_init() {
else {
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
}
#else
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif
if (up.home != NULL) {
#ifdef PYTHREE
@@ -245,9 +234,7 @@ pep405:
#endif
#ifndef UWSGI_PYPY
Py_OptimizeFlag = up.optimize;
#endif
Py_Initialize();
@@ -286,9 +273,6 @@ void uwsgi_python_reset_random_seed() {
random_seed = PyDict_GetItemString(random_dict, "seed");
if (random_seed) {
PyObject *random_args = PyTuple_New(1);
#ifdef UWSGI_PYPY
Py_INCREF(Py_None);
#endif
// pass no args
PyTuple_SetItem(random_args, 0, Py_None);
PyEval_CallObject(random_seed, random_args);
@@ -375,13 +359,11 @@ void uwsgi_python_post_fork() {
pthread_t par_tid;
pthread_create(&par_tid, NULL, uwsgi_python_autoreloader_thread, NULL);
}
#ifndef UWSGI_PYPY
if (up.tracebacker) {
// spawn the tracebacker thread
pthread_t ptb_tid;
pthread_create(&ptb_tid, NULL, uwsgi_python_tracebacker_thread, NULL);
}
#endif
}
UWSGI_RELEASE_GIL
@@ -390,10 +372,6 @@ UWSGI_RELEASE_GIL
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
#ifdef UWSGI_PYPY
uwsgi_log("import by filename is currently not supported on PyPy !!!\n");
return NULL;
#else
FILE *pyfile;
struct _node *py_file_node = NULL;
PyObject *py_compiled_node, *py_file_module;
@@ -479,7 +457,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
Py_DECREF(py_compiled_node);
return py_file_module;
#endif
}
@@ -500,7 +477,11 @@ void init_uwsgi_vars() {
#ifdef PYTHREE
// fix stdout and stderr
PyObject *new_stdprint = PyFile_NewStdPrinter(2);
#ifdef HAS_NO_ERRORS_IN_PyFile_FromFd
PyObject *new_stdprint = PyFile_FromFd(2, NULL, "w", _IOLBF, NULL, NULL, 0);
#else
PyObject *new_stdprint = PyFile_FromFd(2, NULL, "w", _IOLBF, NULL, NULL, NULL, 0);
#endif
PyDict_SetItemString(pysys_dict, "stdout", new_stdprint);
PyDict_SetItemString(pysys_dict, "__stdout__", new_stdprint);
PyDict_SetItemString(pysys_dict, "stderr", new_stdprint);
@@ -1067,13 +1048,11 @@ void uwsgi_python_init_apps() {
UWSGI_GET_GIL;
}
#ifndef UWSGI_PYPY
// prepare for stack suspend/resume
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
}
#endif
// setup app loaders
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
@@ -1160,7 +1139,6 @@ next:
init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE);
}
#ifndef UWSGI_PYPY
if (uwsgi.profiler) {
if (!strcmp(uwsgi.profiler, "pycall")) {
PyEval_SetProfile(uwsgi_python_profiler_call, NULL);
@@ -1169,7 +1147,6 @@ next:
PyEval_SetTrace(uwsgi_python_tracer, NULL);
}
}
#endif
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
@@ -1425,7 +1402,6 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
return NULL;
}
#ifndef UWSGI_PYPY
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
PyGILState_STATE pgst = PyGILState_Ensure();
@@ -1442,7 +1418,6 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
}
}
#endif
char *uwsgi_python_code_string(char *id, char *code, char *function, char *key, uint16_t keylen) {
@@ -1637,7 +1612,6 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
return -1;
}
#ifndef UWSGI_PYPY
void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
PyGILState_STATE pgst = PyGILState_Ensure();
@@ -1654,7 +1628,6 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
}
}
#endif
void uwsgi_python_fixup() {
// set hacky modifier 30
@@ -1668,7 +1641,6 @@ void uwsgi_python_hijack(void) {
// the pyshell will be execute only in the first worker
#ifndef UWSGI_PYPY
FILE *pyfile;
if (up.pyrun) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
@@ -1682,7 +1654,6 @@ void uwsgi_python_hijack(void) {
// could be never executed
exit(0);
}
#endif
if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
uwsgi.workers[uwsgi.mywid].hijacked = 0;
@@ -1708,9 +1679,7 @@ void uwsgi_python_hijack(void) {
else {
PyImport_ImportModule("readline");
#ifndef UWSGI_PYPY
ret = PyRun_InteractiveLoop(stdin, "uwsgi");
#endif
}
if (up.pyshell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
@@ -1830,13 +1799,8 @@ void uwsgi_python_on_load() {
uwsgi_register_logger("python", uwsgi_python_logger);
}
#ifndef UWSGI_PYPY
struct uwsgi_plugin python_plugin = {
.name = "python",
#else
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
#endif
.alias = "python",
.modifier1 = 0,
.init = uwsgi_python_init,
@@ -1858,10 +1822,8 @@ struct uwsgi_plugin pypy_plugin = {
.magic = uwsgi_python_magic,
#ifndef UWSGI_PYPY
.suspend = uwsgi_python_suspend,
.resume = uwsgi_python_resume,
#endif
.harakiri = uwsgi_python_harakiri,
+5 -4
View File
@@ -10,14 +10,14 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
char *uwsgi_python_get_exception_type(PyObject *exc) {
char *class_name = NULL;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
if (PyClass_Check(exc)) {
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
}
else {
#endif
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
#if !defined(PYTHREE)
}
#endif
@@ -301,8 +301,9 @@ void init_pyargv() {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
up.py_argv[up.argc] = wcargv + strlen(ap);
mbstowcs( wcargv, ap, strlen(ap));
up.py_argv[up.argc] = wcargv;
wcargv += strlen(ap) + 1;
#else
up.py_argv[up.argc] = ap;
#endif
-4
View File
@@ -1,7 +1,5 @@
#include "uwsgi_python.h"
#ifndef UWSGI_PYPY
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
@@ -806,5 +804,3 @@ int uwsgi_init_symbol_import() {
return 0;
}
#endif
+4
View File
@@ -22,6 +22,10 @@
#define HAS_NOT_PyFrame_GetLineNumber
#endif
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0
#define HAS_NO_ERRORS_IN_PyFile_FromFd
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#endif
-4
View File
@@ -14,10 +14,6 @@ NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
if 'pypy_version_info' in sys.__dict__:
CFLAGS.append('-DUWSGI_PYPY')
LDFLAGS = []
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
+9 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
PyObject *uwsgi_Input_iter(PyObject *self) {
@@ -339,7 +340,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
}
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, python_plugin.modifier1)) == -1) {
if (wsgi_req->dynamic) {
UWSGI_GET_GIL
if (uwsgi.single_interpreter) {
@@ -350,6 +351,12 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
UWSGI_RELEASE_GIL
}
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == python_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
}
if (wsgi_req->dynamic) {
@@ -358,6 +365,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
}
if (wsgi_req->app_id == -1) {
uwsgi_500(wsgi_req);
uwsgi_log("--- no python application found, check your startup logs for errors ---\n");
+2 -1
View File
@@ -80,7 +80,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
goto end;
}
#ifdef PYTHREE
@@ -193,6 +193,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
UWSGI_GET_GIL
}
end:
Py_INCREF(up.wsgi_writeout);
return up.wsgi_writeout;
}
+59 -8
View File
@@ -4,6 +4,44 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern PyTypeObject uwsgi_InputType;
/*
this is a hack for supporting non-file object passed to wsgi.file_wrapper
*/
static void uwsgi_python_consume_file_wrapper_read(struct wsgi_request *wsgi_req, PyObject *pychunk) {
PyObject *read_method_args = NULL;
PyObject *read_method = PyObject_GetAttrString(pychunk, "read");
if (wsgi_req->sendfile_fd_chunk > 0) {
read_method_args = PyTuple_New(1);
PyTuple_SetItem(read_method_args, 0, PyInt_FromLong(wsgi_req->sendfile_fd_chunk));
}
else {
read_method_args = PyTuple_New(0);
}
for(;;) {
PyObject *read_method_output = PyEval_CallObject(read_method, read_method_args);
if (PyErr_Occurred()) {
uwsgi_manage_exception(wsgi_req, 0);
break;
}
if (!read_method_output) break;
if (PyString_Check(read_method_output)) {
char *content = PyString_AsString(read_method_output);
size_t content_len = PyString_Size(read_method_output);
if (content_len == 0) {
Py_DECREF(read_method_output);
break;
}
UWSGI_RELEASE_GIL
uwsgi_response_write_body_do(wsgi_req, content, content_len);
UWSGI_GET_GIL
}
Py_DECREF(read_method_output);
if (wsgi_req->sendfile_fd_chunk == 0) break;
}
Py_DECREF(read_method_args);
Py_DECREF(read_method);
}
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
@@ -143,10 +181,16 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
}
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
if (wsgi_req->sendfile_obj == wsgi_req->async_result) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
}
// we do not have an iterable, check for read() method
else if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "read")) {
uwsgi_python_consume_file_wrapper_read(wsgi_req, (PyObject *)wsgi_req->async_result);
}
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
}
@@ -190,10 +234,17 @@ exception:
}
}
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
else if (wsgi_req->sendfile_obj == pychunk) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
UWSGI_GET_GIL
}
// we do not have an iterable, check for read() method
else if (PyObject_HasAttrString(pychunk, "read")) {
uwsgi_python_consume_file_wrapper_read(wsgi_req, pychunk);
}
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
Py_DECREF(pychunk);
+3 -1
View File
@@ -888,7 +888,9 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
status = rb_obj_as_string(RARRAY_PTR(ret)[0]);
// get the status code
uwsgi_response_prepare_headers(wsgi_req, RSTRING_PTR(status), RSTRING_LEN(status));
if (uwsgi_response_prepare_headers(wsgi_req, RSTRING_PTR(status), RSTRING_LEN(status))) {
goto clear;
}
headers = RARRAY_PTR(ret)[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
+3
View File
@@ -163,6 +163,8 @@ static ssize_t rr_instance_connected(struct corerouter_peer *peer) {
struct rawrouter_session *rr = (struct rawrouter_session *) cs;
cr_peer_connected(peer, "rr_instance_connected()");
peer->can_retry = 0;
if (rr->xclient) {
cr_reset_hooks_and_read(peer, rr_xclient_read);
return 1;
@@ -251,6 +253,7 @@ static int rawrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_ga
return -1;
}
peer->can_retry = 1;
cr_connect(peer, rr_instance_connected);
return 0;
}
+10
View File
@@ -56,6 +56,7 @@ struct uwsgi_router_cache_conf {
char *status_str;
int status;
char *no_offload;
};
// this is allocated for each transformation
@@ -189,6 +190,14 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
if (uwsgi_response_add_expires(wsgi_req, expires)) goto error;
}
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) {
if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
return UWSGI_ROUTE_BREAK;
}
}
uwsgi_response_write_body_do(wsgi_req, value, valsize);
free(value);
if (ur->custom)
@@ -369,6 +378,7 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
"content_encoding", &urcc->content_encoding,
"mime", &urcc->mime,
"name", &urcc->name,
"no_offload", &urcc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
+121 -2
View File
@@ -1,9 +1,23 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
struct uwsgi_router_file_conf {
char *filename;
size_t filename_len;
char *status;
size_t status_len;
char *content_type;
size_t content_type_len;
char *mime;
};
int uwsgi_routing_func_static(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -17,8 +31,71 @@ int uwsgi_routing_func_static(struct wsgi_request *wsgi_req, struct uwsgi_route
return UWSGI_ROUTE_BREAK;
}
int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
char buf[32768];
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;
}
size_t remains = st.st_size;
while(remains) {
ssize_t rlen = read(fd, buf, UMIN(32768, remains));
if (rlen <= 0) goto end2;
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end2;
remains -= rlen;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
static int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_static;
ur->data = args;
@@ -26,10 +103,52 @@ int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_file(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_file;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_file_conf *urfc = uwsgi_calloc(sizeof(struct uwsgi_router_file_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"filename", &urfc->filename,
"status", &urfc->status,
"content_type", &urfc->content_type,
"mime", &urfc->mime,
NULL)) {
uwsgi_log("invalid file route syntax: %s\n", args);
return -1;
}
if (!urfc->filename) {
uwsgi_log("you have to specifify a filename for the \"file\" router\n");
return -1;
}
urfc->filename_len = strlen(urfc->filename);
if (!urfc->content_type) {
urfc->content_type = "text/html";
}
urfc->content_type_len = strlen(urfc->content_type);
if (!urfc->status) {
urfc->status = "200 OK";
}
urfc->status_len = strlen(urfc->status);
ur->data2 = urfc;
return 0;
}
static int uwsgi_router_file_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
return uwsgi_router_file(ur, args);
}
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);
}
struct uwsgi_plugin router_static_plugin = {
+197
View File
@@ -1,7 +1,125 @@
#include <uwsgi.h>
#ifdef UWSGI_XML_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
#endif
extern struct uwsgi_server uwsgi;
/*
rpc-HTTP interface.
modifier2 changes the parsser behaviours:
0 -> return uwsgi header + rpc response
1 -> return raw rpc response
2 -> split PATH_INFO to get func name and args and return as HTTP response with content_type as application/binary or Accept request header (if different from *)
3 -> set xmlrpc wrapper (requires libxml2)
4 -> set jsonrpc wrapper (requires libjansson)
*/
#ifdef UWSGI_XML_LIBXML2
// raise error on non-string args
static int uwsgi_rpc_xmlrpc_string(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (strcmp((char *) node->name, "string")) {
return -1;
}
if (!node->children) return -1;
if (!node->children->content) return -1;
*argc+=1;
argv[*argc] = (char *) node->children->content;
argvs[*argc] = strlen(argv[*argc]);
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc_value(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "value")) {
if (uwsgi_rpc_xmlrpc_string(node, argv, argvs, argc)) {
return -1;
}
}
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc_args(xmlNode *element, char **argv, uint16_t *argvs, uint8_t *argc) {
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "param")) {
if (uwsgi_rpc_xmlrpc_value(node, argv, argvs, argc)) {
return -1;
}
}
}
}
return 0;
}
static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **argv, uint16_t *argvs, uint8_t *argc, char *response_buf) {
char *method = NULL;
xmlNode *element = xmlDocGetRootElement(doc);
if (!element) return -1;
if (strcmp((char *) element->name, "methodCall")) return -1;
*argc = 0;
xmlNode *node;
for (node = element->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, "methodName") && node->children) {
method = (char *) node->children->content;
}
else if (!strcmp((char *) node->name, "params")) {
if (uwsgi_rpc_xmlrpc_args(node, argv, argvs, argc)) return -1;
}
}
}
if (!method) return -1;
wsgi_req->uh->pktsize = uwsgi_rpc(method, *argc, argv+1, argvs+1, response_buf);
if (!wsgi_req->uh->pktsize) return -1;
if (wsgi_req->uh->pktsize == UMAX16-1) return -1;
// add final NULL byte
response_buf[wsgi_req->uh->pktsize] = 0;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *m_response = xmlNewNode(NULL, BAD_CAST "methodResponse");
xmlDocSetRootElement(rdoc, m_response);
xmlNode *x_params = xmlNewChild(m_response, NULL, BAD_CAST "params", NULL);
xmlNode *x_param = xmlNewChild(x_params, NULL, BAD_CAST "param", NULL);
xmlNode *x_value = xmlNewChild(x_param, NULL, BAD_CAST "value", NULL);
xmlNewTextChild(x_value, NULL, BAD_CAST "string", BAD_CAST response_buf);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_add_content_length(wsgi_req, xlen);
uwsgi_response_add_content_type(wsgi_req, "application/xml", 15);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
return 0;
}
#endif
static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
@@ -20,6 +138,82 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return -1;
}
if (wsgi_req->uh->modifier2 == 2) {
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
}
if (wsgi_req->path_info_len == 0) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *args = NULL;
if (wsgi_req->path_info[0] == '/') {
args = uwsgi_concat2n(wsgi_req->path_info+1, wsgi_req->path_info_len-1, "", 0);
}
else {
args = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
}
argc = 0;
argv[0] = strtok(args, "/");
if (!argv[0]) {
free(args);
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *p = strtok(NULL, "/");
while(p) {
argc++;
argv[argc] = p;
argvs[argc] = strlen(p);
p = strtok(NULL, "/");
}
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, response_buf);
free(args);
if (!wsgi_req->uh->pktsize) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return 1;
if (uwsgi_response_add_content_length(wsgi_req, wsgi_req->uh->pktsize)) return -1;
uint16_t ctype_len = 0;
char *ctype = uwsgi_get_var(wsgi_req, "HTTP_ACCEPT", 11, &ctype_len);
if (ctype && strcmp(ctype, "*/*") && strcmp(ctype, "*")) {
if (uwsgi_response_add_content_type(wsgi_req, ctype, ctype_len)) return -1;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, "application/binary", 18)) return -1;
}
goto sendbody;
}
#ifdef UWSGI_XML_LIBXML2
if (wsgi_req->uh->modifier2 == 3) {
if (wsgi_req->post_cl == 0) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
ssize_t body_len = 0;
char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
if (!doc) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
int ret = uwsgi_rpc_xmlrpc(wsgi_req, doc, argv, argvs, &argc, response_buf);
xmlFreeDoc(doc);
if (ret) {
uwsgi_500(wsgi_req);
}
return UWSGI_OK;
}
#endif
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
@@ -34,6 +228,9 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return -1;
}
}
sendbody:
// write the response
uwsgi_response_write_body_do(wsgi_req, response_buf, wsgi_req->uh->pktsize);
+2
View File
@@ -193,6 +193,7 @@ static ssize_t sr_instance_read(struct corerouter_peer *peer) {
// the instance is connected now we cannot retry connections
static ssize_t sr_instance_connected(struct corerouter_peer *peer) {
cr_peer_connected(peer, "sr_instance_connected()");
peer->can_retry = 0;
// set the output buffer as the main_peer output one
peer->out = peer->session->main_peer->in;
peer->out_pos = 0;
@@ -307,6 +308,7 @@ static ssize_t sr_read(struct corerouter_peer *main_peer) {
return -1;
}
peer->can_retry = 1;
cr_connect(peer, sr_instance_connected);
return 1;
}
+11 -1
View File
@@ -12,13 +12,23 @@ from setuptools.command.build_ext import build_ext
"""
This is a hack allowing you installing
uWSGI and uwsgidecorators via pip and easy_install
since 1.9.11 it automatically detects pypy
"""
uwsgi_compiled = False
def get_profile():
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
is_pypy = False
try:
import __pypy__
is_pypy = True
except ImportError:
pass
if is_pypy:
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/pypy.ini')
else:
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
if not profile.endswith('.ini'):
profile = "%s.ini" % profile
if not '/' in profile:
+80
View File
@@ -0,0 +1,80 @@
#!./uwsgi --http-socket :9090 --gevent 100 --module tests.websocket_chat --gevent-monkey-patch
import uwsgi
import time
import gevent.select
import redis
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
<html>
<head>
<script language="Javascript">
var s = new WebSocket("%s://%s/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/favicon.ico':
return ""
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
r = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = r.pubsub()
channel.subscribe('foobar')
websocket_fd = uwsgi.connection_fd()
redis_fd = channel.connection._sock.fileno()
while True:
# wait max 4 seconds to allow ping to be sent
ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0)
# send ping on timeout
if not ready[0]:
uwsgi.websocket_recv_nb()
for fd in ready[0]:
if fd == websocket_fd:
msg = uwsgi.websocket_recv_nb()
if msg:
r.publish('foobar', msg)
elif fd == redis_fd:
msg = channel.parse_response()
# only interested in user messages
if msg[0] == 'message':
uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
+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-05-11'
s.date = '2013-05-26'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+44 -4
View File
@@ -292,6 +292,7 @@ extern int pivot_root(const char *new_root, const char *put_old);
#include <sys/devpoll.h>
#elif defined(__HAIKU__)
#elif defined(__CYGWIN__)
#elif defined(__HURD__)
#else
#include <sys/event.h>
#endif
@@ -783,6 +784,9 @@ struct uwsgi_opt {
#elif defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#elif defined(__HAIKU__)
#elif defined(__HURD__)
#define PATH_MAX 8192
#define RTLD_DEFAULT ((void *) 0)
#else
#include <machine/endian.h>
#endif
@@ -1082,6 +1086,7 @@ struct uwsgi_route {
int (*if_func)(struct wsgi_request *, struct uwsgi_route *);
int if_negate;
int if_status;
int (*func) (struct wsgi_request *, struct uwsgi_route *);
@@ -1426,11 +1431,18 @@ struct wsgi_request {
// avoid routing loops
int is_routing;
int is_final_routing;
int is_error_routing;
int routes_applied;
// internal routing vm program counter
uint32_t route_pc;
uint32_t error_route_pc;
uint32_t final_route_pc;
// internal routing goto instruction
uint32_t route_goto;
uint32_t error_route_goto;
uint32_t final_route_goto;
int ignore_body;
struct uwsgi_transformation *transformations;
char *transformed_chunk;
@@ -1932,6 +1944,7 @@ struct uwsgi_server {
struct uwsgi_offload_engine *offload_engines;
struct uwsgi_offload_engine *offload_engine_sendfile;
struct uwsgi_offload_engine *offload_engine_transfer;
struct uwsgi_offload_engine *offload_engine_memory;
int offload_threads;
int offload_threads_events;
struct uwsgi_thread **offload_thread;
@@ -2085,6 +2098,7 @@ struct uwsgi_server {
struct uwsgi_mule *mules;
struct uwsgi_string_list *farms_list;
struct uwsgi_farm *farms;
int mule_msg_size;
pid_t mypid;
int mywid;
@@ -2115,6 +2129,7 @@ struct uwsgi_server {
struct uwsgi_router *routers;
struct uwsgi_route *routes;
struct uwsgi_route *final_routes;
struct uwsgi_route *error_routes;
struct uwsgi_route_condition *route_conditions;
struct uwsgi_route_var *route_vars;
#endif
@@ -2148,6 +2163,7 @@ struct uwsgi_server {
#ifdef __linux__
struct uwsgi_string_list *cgroup;
struct uwsgi_string_list *cgroup_opt;
char *cgroup_dir_mode;
char *ns;
char *ns_net;
struct uwsgi_string_list *ns_keep_mount;
@@ -2170,6 +2186,7 @@ struct uwsgi_server {
struct uwsgi_string_list *map_socket;
struct uwsgi_cron *crons;
time_t cron_harakiri;
time_t respawn_delta;
@@ -2371,6 +2388,16 @@ struct uwsgi_cron {
#endif
void (*func)(struct uwsgi_cron *, time_t);
time_t started_at;
// next harakiri timestamp
time_t harakiri;
// number of seconds to wait before calling harakiri on cron
int mercy;
uint8_t unique;
pid_t pid;
struct uwsgi_cron *next;
};
@@ -2905,7 +2932,8 @@ struct uwsgi_async_request {
int event_queue_read(void);
int event_queue_write(void);
void uwsgi_help(char *opt, char *val, void *);
void uwsgi_help(char *, char *, void *);
void uwsgi_print_sym(char *, char *, void *);
int uwsgi_str2_num(char *);
int uwsgi_str3_num(char *);
@@ -2929,7 +2957,7 @@ char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int);
int uwsgi_starts_with(char *, int, char *, int);
int uwsgi_static_want_gzip(struct wsgi_request *, char *, size_t, struct stat *);
int uwsgi_static_want_gzip(struct wsgi_request *, char *, size_t *, struct stat *);
#ifdef __sun__
time_t timegm(struct tm *);
@@ -3148,6 +3176,7 @@ void mule_send_msg(int, char *, size_t);
uint32_t djb33x_hash(char *, uint64_t);
void create_signal_pipe(int *);
void create_msg_pipe(int *, int);
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t);
@@ -3240,12 +3269,15 @@ void uwsgi_opt_add_shared_socket(char *, char *, void *);
void uwsgi_opt_add_socket(char *, char *, void *);
void uwsgi_opt_add_lazy_socket(char *, char *, void *);
void uwsgi_opt_add_cron(char *, char *, void *);
void uwsgi_opt_add_cron2(char *, char *, void *);
void uwsgi_opt_add_unique_cron(char *, char *, void *);
void uwsgi_opt_load_plugin(char *, char *, void *);
void uwsgi_opt_load_dl(char *, char *, void *);
void uwsgi_opt_load(char *, char *, void *);
void uwsgi_opt_safe_fd(char *, char *, void *);
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *, char *, void *);
void uwsgi_opt_add_unique_legion_cron(char *, char *, void *);
void uwsgi_opt_sni(char *, char *, void *);
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *, char *, char *, char *, char *);
#endif
@@ -3330,6 +3362,7 @@ struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *,
void uwsgi_opt_add_route(char *, char *, void *);
int uwsgi_apply_routes(struct wsgi_request *);
void uwsgi_apply_final_routes(struct wsgi_request *);
int uwsgi_apply_error_routes(struct wsgi_request *);
int uwsgi_apply_routes_do(struct uwsgi_route *, struct wsgi_request *, char *, uint16_t);
void uwsgi_register_embedded_routers(void);
void uwsgi_routing_dump();
@@ -3736,6 +3769,7 @@ void uwsgi_offload_engines_register_all(void);
struct uwsgi_thread *uwsgi_offload_thread_start(void);
int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t);
int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *);
int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t);
void uwsgi_subscription_set_algo(char *);
@@ -3764,8 +3798,8 @@ int uwsgi_plugin_modifier1(char *);
void *cache_udp_server_loop(void *);
void uwsgi_user_lock(int);
void uwsgi_user_unlock(int);
int uwsgi_user_lock(int);
int uwsgi_user_unlock(int);
void simple_loop_run_int(int);
@@ -3830,6 +3864,7 @@ int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, u
int uwsgi_response_add_header_force(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_response_commit_headers(struct wsgi_request *);
int uwsgi_response_sendfile_do(struct wsgi_request *, int, size_t, size_t);
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int);
struct uwsgi_buffer *uwsgi_proto_base_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
@@ -3874,6 +3909,7 @@ void uwsgi_master_check_workers_deadline(void);
void uwsgi_master_check_gateways_deadline(void);
void uwsgi_master_check_mules_deadline(void);
void uwsgi_master_check_spoolers_deadline(void);
void uwsgi_master_check_crons_deadline(void);
int uwsgi_master_check_spoolers_death(int);
int uwsgi_master_check_emperor_death(int);
int uwsgi_master_check_mules_death(int);
@@ -4002,11 +4038,15 @@ void uwsgi_mule_run(void);
void uwsgi_spooler_run(void);
void uwsgi_takeover(void);
char *uwsgi_binary_path(void);
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
#endif
int uwsgi_master_check_cron_death(int);
#ifdef __cplusplus
}
#endif
+35 -2
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.10'
uwsgi_version = '1.9.11'
import os
import re
@@ -356,6 +356,20 @@ def build_uwsgi(uc, print_only=False):
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile)
gcc_list.append('%s/%s' % (path, cfile))
for bfile in up.get('BINARY_LIST', []):
try:
binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" % (path, bfile[1], path, bfile[1])
print(binary_link_cmd)
if os.system(binary_link_cmd) != 0:
raise Exception('unable to link binary file')
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_%s %s/%s.o" % (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path, bfile[1])
print(objcopy_cmd)
if os.system(objcopy_cmd) != 0:
raise Exception('unable to link binary file')
gcc_list.append('%s/%s.o' % (path, bfile[1]))
except:
pass
libs += up['LIBS']
@@ -487,6 +501,9 @@ class uConf(object):
except:
pass
if uwsgi_os == 'GNU':
self.cflags.append('-D__HURD__')
try:
gcc_version = str(spcall("%s -dumpversion" % GCC))
except:
@@ -660,6 +677,8 @@ class uConf(object):
locking_mode = 'posix_sem'
except:
pass
elif uwsgi_os == 'GNU':
locking_mode = 'posix_sem'
elif uwsgi_os == 'Darwin':
locking_mode = 'osx_spinlock'
elif uwsgi_os.startswith('CYGWIN'):
@@ -696,7 +715,7 @@ class uConf(object):
event_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
event_mode = 'kqueue'
elif uwsgi_os.startswith('CYGWIN'):
elif uwsgi_os.startswith('CYGWIN') or uwsgi_os == 'GNU':
event_mode = 'poll'
if event_mode == 'epoll':
@@ -1128,6 +1147,20 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
gcc_list.append(path + '/' + cfile + '.c')
else:
gcc_list.append(path + '/' + cfile)
for bfile in up.get('BINARY_LIST', []):
try:
binary_link_cmd = "ld -r -b binary -o %s/%s.o %s/%s" % (path, bfile[1], path, bfile[1])
print(binary_link_cmd)
if os.system(binary_link_cmd) != 0:
raise Exception('unable to link binary file')
for kind in ('start','end'):
objcopy_cmd = "objcopy --redefine-sym _binary_%s_%s=%s_%s %s/%s.o" % (binarize('%s/%s' % (path, bfile[1])), kind, bfile[0], kind, path, bfile[1])
print(objcopy_cmd)
if os.system(objcopy_cmd) != 0:
raise Exception('unable to link binary file')
gcc_list.append('%s/%s.o' % (path, bfile[1]))
except:
pass
try:
p_ldflags.remove('-Wl,--no-undefined')