mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a32f5d49d | ||
|
|
bf67984049 | ||
|
|
41b6005d30 | ||
|
|
497f7efa55 | ||
|
|
ad7ca0b098 | ||
|
|
1d591c95f2 | ||
|
|
d3daca0b16 | ||
|
|
bae1ade00a | ||
|
|
fd663aedbd | ||
|
|
6b9ce2d755 | ||
|
|
bd2728b391 | ||
|
|
dc250fd7b5 | ||
|
|
0a9345b8d4 | ||
|
|
db509f2d38 | ||
|
|
b12c39607d | ||
|
|
224260ce3e | ||
|
|
5f86d9522f | ||
|
|
a0fafe7847 | ||
|
|
daeaf1b231 | ||
|
|
fbc0a2775f | ||
|
|
d3c89a3f63 | ||
|
|
cd43a0d12d | ||
|
|
f06df71bfc | ||
|
|
eab2472dd0 | ||
|
|
87a2f3585c | ||
|
|
c257a9aa98 | ||
|
|
43aebe2d66 | ||
|
|
309115d611 | ||
|
|
5881d41b2b | ||
|
|
9fe4b7b14a | ||
|
|
930c19210a | ||
|
|
5beb170cfd | ||
|
|
a13103d851 | ||
|
|
bc5a86694f | ||
|
|
812685096b | ||
|
|
f70c070a0f | ||
|
|
accf622ffc | ||
|
|
04173869ee | ||
|
|
509a3c5cd4 | ||
|
|
81ad3a916d | ||
|
|
3f93a0b8e4 | ||
|
|
4408b655a4 | ||
|
|
71a6b8a304 | ||
|
|
7e9069eabf | ||
|
|
6c77dd0e38 | ||
|
|
27e506c72a | ||
|
|
bea68191e3 | ||
|
|
9b207d8a62 | ||
|
|
68d5b2de3b | ||
|
|
3a62573005 | ||
|
|
1c6dd42318 | ||
|
|
73ad0677bd | ||
|
|
15b2cf0712 | ||
|
|
0da0fa211a | ||
|
|
a8ecd71ffd | ||
|
|
ea0a95a441 | ||
|
|
6ac6e58bf7 | ||
|
|
f2c7addb73 | ||
|
|
fff5fa536b | ||
|
|
95825c9b99 | ||
|
|
1e84fcf880 | ||
|
|
0f742a72bf | ||
|
|
fd96a02576 | ||
|
|
77ca76428d | ||
|
|
9ea8f4f07c | ||
|
|
9ffc311177 | ||
|
|
4f89a350aa | ||
|
|
8f18c77587 | ||
|
|
371cafef94 | ||
|
|
89c31e9280 | ||
|
|
418d784148 | ||
|
|
c146275e9b | ||
|
|
eff23382c2 | ||
|
|
d566469c63 | ||
|
|
e008ce5d56 | ||
|
|
9d21c99183 | ||
|
|
7e80927317 | ||
|
|
6664e7120b | ||
|
|
687aabd30b | ||
|
|
fab656c635 | ||
|
|
72c31dab7a | ||
|
|
f19a301b73 | ||
|
|
19a19a8a67 | ||
|
|
d9c9f41624 | ||
|
|
dc97853f9f | ||
|
|
b089774c36 | ||
|
|
f8a271a027 | ||
|
|
ef12aaf13c | ||
|
|
a559361a30 | ||
|
|
6aad281441 |
+22
-23
@@ -363,6 +363,19 @@ void uwsgi_alarm_thread_start() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_alarm_trigger_uai(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// check if a log should raise an alarm
|
||||
void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
@@ -372,7 +385,14 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
while (ual) {
|
||||
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
|
||||
if (!ual->negate) {
|
||||
uwsgi_alarm_log_run(ual, msg, len);
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_trigger_uai(uall->alarm, msg, len);
|
||||
else
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
@@ -397,18 +417,6 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uai->last_msg_size = len;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// call the alarms mapped to a log line
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// this is the api function workers,mules and whatever you want can call from code
|
||||
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
if (!uwsgi.alarm_thread) return;
|
||||
@@ -416,16 +424,7 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
|
||||
if (!uai) return;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
uwsgi_alarm_trigger_uai(uai, msg, len);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
|
||||
+12
-11
@@ -476,17 +476,17 @@ static void lru_remove_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
{
|
||||
struct uwsgi_cache_item *prev, *next, *curr = cache_item(index);
|
||||
|
||||
if (curr->next) {
|
||||
next = cache_item(curr->next);
|
||||
next->prev = curr->prev;
|
||||
if (curr->lru_next) {
|
||||
next = cache_item(curr->lru_next);
|
||||
next->lru_prev = curr->lru_prev;
|
||||
} else
|
||||
uc->lru_tail = curr->prev;
|
||||
uc->lru_tail = curr->lru_prev;
|
||||
|
||||
if (curr->prev) {
|
||||
prev = cache_item(curr->prev);
|
||||
prev->next = curr->next;
|
||||
if (curr->lru_prev) {
|
||||
prev = cache_item(curr->lru_prev);
|
||||
prev->lru_next = curr->lru_next;
|
||||
} else
|
||||
uc->lru_head = curr->next;
|
||||
uc->lru_head = curr->lru_next;
|
||||
}
|
||||
|
||||
static void lru_add_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
@@ -495,12 +495,12 @@ static void lru_add_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
|
||||
if (uc->lru_tail) {
|
||||
prev = cache_item(uc->lru_tail);
|
||||
prev->next = index;
|
||||
prev->lru_next = index;
|
||||
} else
|
||||
uc->lru_head = index;
|
||||
|
||||
curr->next = 0;
|
||||
curr->prev = uc->lru_tail;
|
||||
curr->lru_next = 0;
|
||||
curr->lru_prev = uc->lru_tail;
|
||||
uc->lru_tail = index;
|
||||
}
|
||||
|
||||
@@ -1249,6 +1249,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"math_initial", &c_math_initial,
|
||||
"ignore_full", &c_ignore_full,
|
||||
"purge_lru", &c_purge_lru,
|
||||
"lru", &c_purge_lru,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
|
||||
@@ -816,3 +816,19 @@ char *uwsgi_manage_placeholder(char *key) {
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_resolve(char *opt, char *value, void *foo) {
|
||||
char *equal = strchr(value, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid resolve syntax, must be placeholder=domain\n");
|
||||
exit(1);
|
||||
}
|
||||
char *ip = uwsgi_resolve_ip(equal+1);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve name %s\n", equal+1);
|
||||
uwsgi_error("uwsgi_resolve_ip()");
|
||||
exit(1);
|
||||
}
|
||||
char *new_opt = uwsgi_concat2n(value, (equal-value)+1, ip, strlen(ip));
|
||||
uwsgi_opt_set_placeholder(opt, new_opt, (void *) 1);
|
||||
}
|
||||
|
||||
+656
-588
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -3,9 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct http_status_codes {
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
};
|
||||
|
||||
/* statistically ordered */
|
||||
@@ -73,7 +73,7 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.stats_pusher_default_freq = 3;
|
||||
|
||||
uwsgi.original_log_fd = -1;
|
||||
uwsgi.original_log_fd = 2;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
@@ -113,6 +113,7 @@ void uwsgi_init_default() {
|
||||
uwsgi.log_master_bufsize = 8192;
|
||||
|
||||
uwsgi.worker_reload_mercy = 60;
|
||||
uwsgi.mule_reload_mercy = 60;
|
||||
|
||||
uwsgi.max_vars = MAX_VARS;
|
||||
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
|
||||
|
||||
+20
-12
@@ -301,19 +301,27 @@ void logto(char *logfile) {
|
||||
}
|
||||
|
||||
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
// if the log-master is already active, just re-set the original_log_fd
|
||||
if (uwsgi.shared->worker_log_pipe[0] == -1) {
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
uwsgi.original_log_fd = 2;
|
||||
}
|
||||
else {
|
||||
uwsgi.original_log_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1845,7 +1853,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
size_t msg_len = len;
|
||||
if (msg[len-1] == '\n') msg_len--;
|
||||
char *e_json = uwsgi_malloc(msg_len * 2);
|
||||
char *e_json = uwsgi_malloc((msg_len * 2)+1);
|
||||
escape_json(msg, msg_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1854,7 +1862,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
char *e_json = uwsgi_malloc(len * 2);
|
||||
char *e_json = uwsgi_malloc((len * 2)+1);
|
||||
escape_json(msg, len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1875,7 +1883,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
char *e_json = uwsgi_malloc(strftime_len * 2);
|
||||
char *e_json = uwsgi_malloc((strftime_len * 2)+1);
|
||||
escape_json(sftime, strftime_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
|
||||
@@ -135,6 +135,15 @@ void uwsgi_master_check_mercy() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0 && uwsgi.mules[i].cursed_at) {
|
||||
if (uwsgi_now() > uwsgi.mules[i].no_mercy_at) {
|
||||
uwsgi_log_verbose("mule %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i + 1, uwsgi.mules[i].pid);
|
||||
uwsgi_curse_mule(i, SIGKILL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -907,6 +916,7 @@ int master_loop(char **argv, char **environ) {
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("mule %d (pid: %d) annihilated\n", i + 1, (int) diedpid);
|
||||
uwsgi.mules[i].pid = 0;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
@@ -954,6 +964,11 @@ next:
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
if (uwsgi.lazy_apps && uwsgi.need_app) {
|
||||
uwsgi_log_verbose("need-app requested, destroying the instance...\n");
|
||||
kill_them_all(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
@@ -969,6 +984,10 @@ next:
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_GO_CHEAP_CODE) {
|
||||
uwsgi_log("worker %d asked for cheap mode (pid: %d)...\n", thewid, (int) diedpid);
|
||||
uwsgi.workers[thewid].cheaped = 1;
|
||||
}
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
|
||||
@@ -25,6 +25,11 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
|
||||
+17
-12
@@ -24,6 +24,15 @@ void uwsgi_curse(int wid, int sig) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_curse_mule(int mid, int sig) {
|
||||
uwsgi.mules[mid].cursed_at = uwsgi_now();
|
||||
uwsgi.mules[mid].no_mercy_at = uwsgi.mules[mid].cursed_at + uwsgi.mule_reload_mercy;
|
||||
|
||||
if (sig) {
|
||||
(void) kill(uwsgi.mules[mid].pid, sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_signal_spoolers(int signum) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
@@ -53,15 +62,6 @@ void uwsgi_destroy_processes() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO mules can be programmed to be gracefully reloaded
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
waitpid(uwsgi.mules[i].pid, &waitpid_status, 0);
|
||||
uwsgi_log("mule %d has been buried (pid: %d)\n", i, (int) uwsgi.mules[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_pid > 0) {
|
||||
kill(uwsgi.emperor_pid, SIGINT);
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
@@ -796,7 +796,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ud->command)*2)+1);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
@@ -913,7 +913,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi.has_metrics && !uwsgi.stats_no_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
@@ -1145,6 +1145,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.stats_no_cores) goto nocores;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
@@ -1206,9 +1208,12 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
nocores:
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
|
||||
if (i < uwsgi.numproc - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
@@ -1284,7 +1289,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ucron->command)*2)+1);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
|
||||
+27
-2
@@ -321,6 +321,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
char *m_initial_value = NULL;
|
||||
char *m_children = NULL;
|
||||
char *m_alias = NULL;
|
||||
char *m_reset_after_push = NULL;
|
||||
|
||||
if (!strchr(arg, '=')) {
|
||||
m_name = uwsgi_str(arg);
|
||||
@@ -340,6 +341,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
"arg3n", &m_arg3n,
|
||||
"children", &m_children,
|
||||
"alias", &m_alias,
|
||||
"reset_after_push", &m_reset_after_push,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid metric keyval syntax: %s\n", arg);
|
||||
exit(1);
|
||||
@@ -381,6 +383,10 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
struct uwsgi_metric* um = uwsgi_register_metric(m_name, m_oid, type, collector, NULL, freq, NULL);
|
||||
um->initial_value = initial_value;
|
||||
|
||||
if (m_reset_after_push){
|
||||
um->reset_after_push = 1;
|
||||
}
|
||||
|
||||
if (m_children) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(m_children, ";", p, ctx) {
|
||||
@@ -427,6 +433,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
if (m_initial_value) free(m_initial_value);
|
||||
if (m_children) free(m_children);
|
||||
if (m_alias) free(m_alias);
|
||||
if (m_reset_after_push) free(m_reset_after_push);
|
||||
return um;
|
||||
}
|
||||
|
||||
@@ -613,7 +620,7 @@ struct uwsgi_metric *uwsgi_metric_find_by_asn(char *asn, size_t len) {
|
||||
}\
|
||||
if (!um) return -1;\
|
||||
if (um->collector || um->type == UWSGI_METRIC_ALIAS) return -1;\
|
||||
uwsgi_rlock(uwsgi.metrics_lock)
|
||||
uwsgi_wlock(uwsgi.metrics_lock)
|
||||
|
||||
int uwsgi_metric_set(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
@@ -694,6 +701,22 @@ int64_t uwsgi_metric_getn(char *name, size_t nlen, char *oid, size_t olen) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_metric_set_max(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if (value > *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_metric_set_min(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if ((value > um->initial_value || 0) && value < *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define uwsgi_metric_name(f, n) ret = snprintf(buf, 4096, f, n); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_name2(f, n, n2) ret = snprintf(buf, 4096, f, n, n2); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
|
||||
@@ -768,9 +791,11 @@ void uwsgi_setup_metrics() {
|
||||
struct uwsgi_metric *vsz = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].vsz_size, 0, NULL);
|
||||
if (i > 0) uwsgi_metric_add_child(total_vsz, vsz);
|
||||
|
||||
// skip core metrics for core 0
|
||||
// skip core metrics for worker 0
|
||||
if (i == 0) continue;
|
||||
|
||||
if (uwsgi.metrics_no_cores) continue;
|
||||
|
||||
int j;
|
||||
for(j=0;j<uwsgi.cores;j++) {
|
||||
uwsgi_metric_name2("worker.%d.core.%d.requests", i, j) ; uwsgi_metric_oid2("3.%d.2.%d.1", i, j);
|
||||
|
||||
+7
-4
@@ -43,7 +43,7 @@ void uwsgi_mule(int id) {
|
||||
#endif
|
||||
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGHUP, end_me);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
@@ -329,9 +329,11 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count + farms_count, timeout);
|
||||
int ret = -1;
|
||||
retry:
|
||||
ret = poll(mulepoll, count + farms_count, timeout);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("poll");
|
||||
uwsgi_error("uwsgi_mule_get_msg()/poll()");
|
||||
}
|
||||
else if (ret > 0 ) {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
@@ -353,7 +355,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -380,6 +382,7 @@ next:
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -583,6 +583,39 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route)
|
||||
{
|
||||
|
||||
if (route->data_len < 3)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
uint16_t status_msg_len = 0;
|
||||
const char *status_msg = uwsgi_http_status_msg(route->data, &status_msg_len);
|
||||
|
||||
if (!status_msg)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
char *buf = uwsgi_concat3n(route->data, route->data_len, " ", 1, (char *) status_msg, status_msg_len);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, buf, route->data_len + 1 + status_msg_len))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, status_msg_len))
|
||||
goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) status_msg, status_msg_len);
|
||||
|
||||
end:
|
||||
free(buf);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return(struct uwsgi_route *ur, char *arg)
|
||||
{
|
||||
ur->func = uwsgi_router_return_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// simple math router
|
||||
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -1086,6 +1119,32 @@ static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setremoteaddr route
|
||||
static int uwsgi_router_setremoteaddr_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "REMOTE_ADDR", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->remote_addr = ptr;
|
||||
wsgi_req->remote_addr_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setremoteaddr(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setremoteaddr_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setdocroot route
|
||||
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -1761,6 +1820,8 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
uwsgi_register_router("last", uwsgi_router_continue);
|
||||
uwsgi_register_router("break", uwsgi_router_break);
|
||||
uwsgi_register_router("return", uwsgi_router_return);
|
||||
uwsgi_register_router("break-with-status", uwsgi_router_return);
|
||||
uwsgi_register_router("log", uwsgi_router_log);
|
||||
uwsgi_register_router("donotlog", uwsgi_router_donotlog);
|
||||
uwsgi_register_router("logvar", uwsgi_router_logvar);
|
||||
@@ -1783,6 +1844,7 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
|
||||
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
|
||||
uwsgi_register_router("seturi", uwsgi_router_seturi);
|
||||
uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr);
|
||||
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
|
||||
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
|
||||
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
|
||||
|
||||
+63
-6
@@ -229,8 +229,11 @@ int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
|
||||
uwsgi.wait_milliseconds_hook(freq);
|
||||
while(timeout == 0 || waiting == 0 || (timeout > 0 && waiting > 0 && (waiting/1000) < timeout)) {
|
||||
if (uwsgi.wait_milliseconds_hook(freq)) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return -1;
|
||||
}
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
@@ -266,6 +269,27 @@ static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t offset) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (uwsgi.sharedareas[id]->area == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_sharedarea_init_fd()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = fd;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
@@ -301,24 +325,41 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
char *s_offset = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
"offset", &s_offset,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid sharedarea keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t len = 0;
|
||||
off_t offset = 0;
|
||||
int pages = 0;
|
||||
if (s_size) {
|
||||
len = uwsgi_n64(s_size);
|
||||
if (strlen(s_size) > 2 && s_size[0] == '0' && s_size[1] == 'x') {
|
||||
len = strtoul(s_size+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
len = uwsgi_n64(s_size);
|
||||
}
|
||||
pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) pages++;
|
||||
}
|
||||
|
||||
if (s_offset) {
|
||||
if (strlen(s_offset) > 2 && s_offset[0] == '0' && s_offset[1] == 'x') {
|
||||
offset = strtoul(s_offset+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
offset = uwsgi_n64(s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pages) {
|
||||
pages = atoi(s_pages);
|
||||
@@ -326,27 +367,43 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
|
||||
char *area = NULL;
|
||||
struct uwsgi_sharedarea *sa = NULL;
|
||||
|
||||
int fd = -1;
|
||||
if (s_file) {
|
||||
fd = open(s_file, O_RDWR|O_SYNC);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(s_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (s_fd) {
|
||||
fd = atoi(s_fd);
|
||||
}
|
||||
else if (s_ptr) {
|
||||
}
|
||||
|
||||
if (pages) {
|
||||
if (!area) {
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
if (fd > -1) {
|
||||
sa = uwsgi_sharedarea_init_fd(fd, len, offset);
|
||||
}
|
||||
else if (area) {
|
||||
sa = uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_ptr(area, len);
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you need to set a size for a sharedarea !!! [%s]\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (s_pages) free(s_pages);
|
||||
if (s_file) free(s_file);
|
||||
if (s_fd) free(s_fd);
|
||||
if (s_ptr) free(s_ptr);
|
||||
if (s_size) free(s_size);
|
||||
if (s_offset) free(s_offset);
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
+25
-7
@@ -1733,13 +1733,6 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
int zero_used = 0;
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1760,6 +1753,24 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
if (!uwsgi.is_a_reload) {
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
if (uwsgi.chmod_socket) {
|
||||
if (uwsgi.chmod_socket_value) {
|
||||
if (chmod(uwsgi_sock->name, uwsgi.chmod_socket_value) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("chmod() fd0 socket to 666 for lazy and brave users\n");
|
||||
if (chmod(uwsgi_sock->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
|
||||
@@ -1794,6 +1805,13 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
stdin_done:
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
|
||||
@@ -459,6 +459,8 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
|
||||
+6
-15
@@ -551,25 +551,16 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
uint16_t i;
|
||||
// replace " with '
|
||||
for(i=0;i<kl;i++) {
|
||||
if (k[i] == '"') {
|
||||
k[i] = '\'';
|
||||
}
|
||||
}
|
||||
for(i=0;i<vl;i++) {
|
||||
if (v[i] == '"') {
|
||||
v[i] = '\'';
|
||||
}
|
||||
}
|
||||
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
|
||||
if (uwsgi_stats_str(us, var)) {
|
||||
char *escaped_var = uwsgi_malloc(((kl+vl+1)*2)+1);
|
||||
escape_json(var, strlen(var), escaped_var);
|
||||
free(var);
|
||||
if (uwsgi_stats_str(us, escaped_var)) {
|
||||
us->dirty = 1;
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
return;
|
||||
}
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
us->dirty = 1;
|
||||
}
|
||||
|
||||
+15
-5
@@ -1051,10 +1051,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uint64_t end_of_request = uwsgi_micros();
|
||||
wsgi_req->end_of_request = end_of_request;
|
||||
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
if (!wsgi_req->do_not_account_avg_rt) {
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
}
|
||||
|
||||
// get memory usage
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
@@ -3155,6 +3156,10 @@ void escape_json(char *src, size_t len, char *dst) {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '"';
|
||||
}
|
||||
else if (src[i] == '\\') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '\\';
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
@@ -3752,7 +3757,7 @@ static void *uwsgi_thread_run(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
struct uwsgi_thread *uwsgi_thread_new_with_data(void (*func) (struct uwsgi_thread *), void *data) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_calloc(sizeof(struct uwsgi_thread));
|
||||
|
||||
@@ -3769,6 +3774,7 @@ struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
uwsgi_socket_nb(ut->pipe[1]);
|
||||
|
||||
ut->func = func;
|
||||
ut->data = data;
|
||||
|
||||
pthread_attr_init(&ut->tattr);
|
||||
pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED);
|
||||
@@ -3788,6 +3794,10 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
return uwsgi_thread_new_with_data(func, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
|
||||
size_t i;
|
||||
va_list ap;
|
||||
|
||||
+39
-8
@@ -101,6 +101,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"declare-option2", required_argument, 0, "declare a new uWSGI custom option (non-immediate)", uwsgi_opt_add_custom_option, NULL, 0},
|
||||
|
||||
{"resolve", required_argument, 0, "place the result of a dns query in the specified placeholder, sytax: placeholder=name (immediate option)", uwsgi_opt_resolve, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -219,6 +221,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-no-blacklist", no_argument, 0, "disable Emperor blacklisting subsystem", uwsgi_opt_true, &uwsgi.emperor_no_blacklist, 0},
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
@@ -243,6 +246,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"mule-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a mule can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.mule_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
@@ -560,6 +564,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-no-cores", no_argument, 0, "disable generation of cores-related metrics", uwsgi_opt_true, &uwsgi.metrics_no_cores, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
|
||||
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
|
||||
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
@@ -570,6 +575,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER|UWSGI_OPT_METRICS},
|
||||
{"stats-pusher-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-pushers-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-no-cores", no_argument, 0, "disable generation of cores-related stats", uwsgi_opt_true, &uwsgi.stats_no_cores, UWSGI_OPT_MASTER},
|
||||
{"stats-no-metrics", no_argument, 0, "do not include metrics in stats output", uwsgi_opt_true, &uwsgi.stats_no_metrics, UWSGI_OPT_MASTER},
|
||||
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
|
||||
@@ -672,6 +679,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-cheap", required_argument, 0, "use main alarm thread rather than create dedicated threads for curl-based alarms", uwsgi_opt_true, &uwsgi.alarm_cheap, 0},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
@@ -691,13 +699,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarm-msg-size", required_argument, 0, "set the max size of an alarm message (default 8192)", uwsgi_opt_set_64bit, &uwsgi.alarm_msg_size, 0},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
|
||||
|
||||
{"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
|
||||
@@ -1247,6 +1255,11 @@ void kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1268,6 +1281,11 @@ void gracefully_kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1309,6 +1327,12 @@ void grace_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
@@ -1355,6 +1379,11 @@ void reap_them_all(int signum) {
|
||||
if (uwsgi.workers[i].pid > 0)
|
||||
uwsgi_curse(i, SIGTERM);
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void harakiri() {
|
||||
@@ -1555,21 +1584,25 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
void signal_pidfile(int sig, char *filename) {
|
||||
int signal_pidfile(int sig, char *filename) {
|
||||
|
||||
int ret = 0;
|
||||
size_t size = 0;
|
||||
|
||||
char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
|
||||
if (size > 0) {
|
||||
if (kill((pid_t) atoi(buffer), sig)) {
|
||||
uwsgi_error("kill()");
|
||||
uwsgi_error("signal_pidfile()/kill()");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("error: invalid pidfile\n");
|
||||
ret = -1;
|
||||
}
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/ void uwsgi_command_signal(char *opt) {
|
||||
@@ -2198,7 +2231,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
|
||||
|
||||
// setup master logging
|
||||
if (uwsgi.log_master && !uwsgi.daemonize2 && !uwsgi.logto2)
|
||||
if (uwsgi.log_master)
|
||||
uwsgi_setup_log_master();
|
||||
|
||||
// setup offload engines
|
||||
@@ -2481,7 +2514,6 @@ int uwsgi_start(void *v_argv) {
|
||||
if (uwsgi.logto2) {
|
||||
if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
|
||||
logto(uwsgi.logto2);
|
||||
uwsgi_setup_log_master();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4201,8 +4233,7 @@ void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
|
||||
long *signum_fake_ptr = (long *) sig;
|
||||
int signum = (long) signum_fake_ptr;
|
||||
signal_pidfile(signum, pidfile);
|
||||
exit(0);
|
||||
exit(signal_pidfile(signum, pidfile));
|
||||
}
|
||||
|
||||
void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
|
||||
@@ -271,12 +271,11 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_airbrake_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_airbrake_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_airbrake_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_airbrake_loop, uacc);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
|
||||
@@ -3,9 +3,18 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_alarm_curl {
|
||||
CURL *curl;
|
||||
struct uwsgi_thread *ut;
|
||||
int pos;
|
||||
int blen;
|
||||
char *body;
|
||||
int hlen;
|
||||
char hdr[];
|
||||
};
|
||||
|
||||
struct uwsgi_alarm_curl_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *url;
|
||||
char *subject;
|
||||
char *to;
|
||||
};
|
||||
@@ -17,7 +26,7 @@ struct uwsgi_alarm_curl_opt {
|
||||
};
|
||||
|
||||
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
#ifdef CURLPROTO_SMTP
|
||||
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->to = arg;
|
||||
struct curl_slist *list = NULL;
|
||||
@@ -29,6 +38,7 @@ static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
curl_easy_setopt(curl, option, list);
|
||||
free(items);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -44,16 +54,33 @@ static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *ar
|
||||
uacc->subject = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
|
||||
static void uwsgi_alarm_curl_url(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
#ifndef CURLPROTO_SMTP
|
||||
if (!uwsgi_strnicmp(arg, 4, "smtp", 4)) {
|
||||
uwsgi_error("Please update libcurl to use SMTP protocol.\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef CURLOPT_MAIL_FROM
|
||||
uacc->url = arg;
|
||||
curl_easy_setopt(curl, option, arg);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_ssl_insecure(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, uwsgi_alarm_curl_url},
|
||||
#ifdef CURLPROTO_SMTP
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to},
|
||||
{"mail_from", CURLOPT_MAIL_FROM, NULL},
|
||||
#endif
|
||||
{"subject", 0, uwsgi_alarm_curl_set_subject},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
|
||||
{"ssl_insecure", 0, uwsgi_alarm_curl_ssl_insecure},
|
||||
{"auth_user", CURLOPT_USERNAME, NULL},
|
||||
{"auth_pass", CURLOPT_PASSWORD, NULL},
|
||||
{"method", CURLOPT_CUSTOMREQUEST, NULL},
|
||||
@@ -65,14 +92,10 @@ static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
|
||||
struct uwsgi_alarm_curl_opt *o = uaco;
|
||||
char *equal = strchr(opt,'=');
|
||||
if (!equal) {
|
||||
if (!uacc->first) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, opt);
|
||||
uacc->first = 1;
|
||||
}
|
||||
if (!equal && !uacc->url) {
|
||||
uwsgi_alarm_curl_url(curl, CURLOPT_URL, opt, uacc);
|
||||
return;
|
||||
}
|
||||
uacc->first = 1;
|
||||
*equal = 0;
|
||||
while(o->name) {
|
||||
if (!strcmp(o->name, opt)) {
|
||||
@@ -82,91 +105,137 @@ static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_cu
|
||||
else {
|
||||
curl_easy_setopt(curl, o->option, equal+1);
|
||||
}
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
struct uwsgi_alarm_curl *uac = userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
struct uwsgi_alarm_curl_config *uacc = ut->data;
|
||||
int remains = full_size;
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr+=4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
if (uac->pos < uac->hlen) {
|
||||
if (remains > uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->hdr + uac->pos, uac->hlen - uac->pos);
|
||||
ptr += uac->hlen - uac->pos;
|
||||
remains -= uac->hlen - uac->pos;
|
||||
uac->pos = uac->hlen;
|
||||
} else {
|
||||
memcpy(ptr, uac->hdr + uac->pos, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr+=9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
}
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
if (remains > uac->blen + uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, uac->blen + uac->hlen - uac->pos);
|
||||
remains -= uac->blen + uac->hlen - uac->pos;
|
||||
uac->pos = uac->blen + uac->hlen;
|
||||
return full_size - remains;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_alloc(struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
char *addr;
|
||||
struct uwsgi_alarm_curl *uac;
|
||||
size_t required = 0;
|
||||
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 2;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 2;
|
||||
if (required)
|
||||
required += 2; /* newline between MIME header and body */
|
||||
|
||||
uac = uwsgi_malloc(sizeof(*uac) + required);
|
||||
uac->hlen = required;
|
||||
addr = uac->hdr;
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr += 4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr += 9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (required) {
|
||||
*addr++ = '\r';
|
||||
*addr = '\n';
|
||||
}
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_init_curl(struct uwsgi_alarm_instance *uai) {
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
if (!curl) {
|
||||
uwsgi_error("Failed to initialize libcurl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
struct uwsgi_alarm_curl_config uacc;
|
||||
memset(&uacc, 0, sizeof(uacc));
|
||||
char *opts = uwsgi_str(uai->arg);
|
||||
|
||||
// fill curl options
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
|
||||
uwsgi_alarm_curl_setopt(curl, p, &uacc);
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
if (!uacc.url) {
|
||||
uwsgi_error("An URL is required to trigger curl-based alarm.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_alloc(&uacc);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, uac);
|
||||
free(opts);
|
||||
uac->curl = curl;
|
||||
uai->data_ptr = uac;
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_call_curl(struct uwsgi_alarm_curl *uac, char *msg, int len)
|
||||
{
|
||||
uac->pos = 0;
|
||||
uac->body = msg;
|
||||
uac->blen = len;
|
||||
curl_easy_setopt(uac->curl, CURLOPT_INFILESIZE, uac->hlen + uac->blen);
|
||||
CURLcode res = curl_easy_perform(uac->curl);
|
||||
if (res != CURLE_OK)
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_init_curl(ut->data);
|
||||
uac->ut = ut;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret < 0) return;
|
||||
@@ -174,31 +243,26 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
ut->pos = 0;
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
uwsgi_alarm_curl_call_curl(uac, ut->buf, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_init_curl(uai);
|
||||
else
|
||||
uwsgi_thread_new_with_data(uwsgi_alarm_curl_loop, uai);
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
struct uwsgi_alarm_curl *uac = uai->data_ptr;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_call_curl(uac, msg, len);
|
||||
else {
|
||||
struct uwsgi_thread *ut = uac->ut;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_load(void) {
|
||||
|
||||
@@ -4,10 +4,9 @@ void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
|
||||
|
||||
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_alarm_xmpp_loop, uai->arg);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
ut->data = uai->arg;
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
|
||||
@@ -353,7 +353,7 @@ static void asyncio_loop() {
|
||||
// call add_handler on each socket
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOi", uwsgi_sock->fd, asyncio_accept, (long) uwsgi_sock) == NULL) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", uwsgi_sock->fd, asyncio_accept, (long) uwsgi_sock) == NULL) {
|
||||
uwsgi_pyexit;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
|
||||
@@ -380,6 +380,11 @@ metrics_loop:
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
if (!wok) goto clear;
|
||||
um = um->next;
|
||||
}
|
||||
|
||||
+6
-24
@@ -66,32 +66,14 @@ SV * coroae_coro_new(CV *block) {
|
||||
}
|
||||
|
||||
static int coroae_wait_milliseconds(int timeout) {
|
||||
int ret = -1;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(newSVnv(((double)timeout)/1000.0));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
char buf[256];
|
||||
double d = ((double)timeout)/1000.0;
|
||||
int ret = snprintf(buf, 256, "Coro::AnyEvent::sleep %f", d);
|
||||
if (ret <= 0 || ret > 256) return -1;
|
||||
perl_eval_pv(buf, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
int ret = 0;
|
||||
dSP;
|
||||
|
||||
@@ -36,7 +36,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
if (uems->database && uems->username && uems->password) {
|
||||
std::string err;
|
||||
if (c.auth(uems->database, uems->username, uems->password, err, uems->predigest ? false : true) == false) {
|
||||
uwsgi_log_verbose("[emperor-mongodb] unabel to authenticate to db %s: %s\n", uems->database, err.c_str());
|
||||
uwsgi_log_verbose("[emperor-mongodb] unable to authenticate to db %s: %s\n", uems->database, err.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,6 +345,9 @@ static void gil_gevent_release() {
|
||||
|
||||
static void gevent_loop() {
|
||||
|
||||
// ensure SIGPIPE is ignored
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ struct uwsgi_http {
|
||||
|
||||
int headers_timeout;
|
||||
int connect_timeout;
|
||||
int manage_source;
|
||||
int enable_proxy_protocol;
|
||||
};
|
||||
|
||||
struct http_session {
|
||||
@@ -156,7 +158,7 @@ void hr_session_ssl_close(struct corerouter_session *);
|
||||
ssize_t hr_ssl_read(struct corerouter_peer *);
|
||||
ssize_t hr_ssl_write(struct corerouter_peer *);
|
||||
|
||||
int hr_https_add_vars(struct http_session *, struct uwsgi_buffer *);
|
||||
int hr_https_add_vars(struct http_session *, struct corerouter_peer *, struct uwsgi_buffer *);
|
||||
void hr_setup_ssl(struct http_session *, struct uwsgi_gateway_socket *);
|
||||
|
||||
#endif
|
||||
|
||||
+45
-7
@@ -62,6 +62,9 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-server-name-as-http-host", required_argument, 0, "force SERVER_NAME to HTTP_HOST", uwsgi_opt_true, &uhttp.server_name_as_http_host, 0},
|
||||
{"http-headers-timeout", required_argument, 0, "set internal http socket timeout for headers", uwsgi_opt_set_int, &uhttp.headers_timeout, 0},
|
||||
{"http-connect-timeout", required_argument, 0, "set internal http socket timeout for backend connections", uwsgi_opt_set_int, &uhttp.connect_timeout, 0},
|
||||
|
||||
{"http-manage-source", no_argument, 0, "manage the SOURCE HTTP method placing the session in raw mode", uwsgi_opt_true, &uhttp.manage_source, 0},
|
||||
{"http-enable-proxy-protocol", optional_argument, 0, "manage PROXY protocol requests", uwsgi_opt_true, &uhttp.enable_proxy_protocol, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -150,10 +153,14 @@ static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "close", 5)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "close", 5) || !uwsgi_strnicmp(val, vallen, "upgrade", 7)) {
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
}
|
||||
else if (peer->key == uwsgi.hostname && hr->raw_body && !uwsgi_strncmp("ICE_URL", 7, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
else if (uhttp.auto_gzip && !uwsgi_strncmp("ACCEPT_ENCODING", 15, hh, keylen)) {
|
||||
@@ -189,6 +196,14 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
char *watermark = ptr + hr->headers_size;
|
||||
char *base = ptr;
|
||||
char *query_string = NULL;
|
||||
char *proxy_src = NULL;
|
||||
char *proxy_dst = NULL;
|
||||
char *proxy_src_port = NULL;
|
||||
char *proxy_dst_port = NULL;
|
||||
uint16_t proxy_src_len = 0;
|
||||
uint16_t proxy_dst_len = 0;
|
||||
uint16_t proxy_src_port_len = 0;
|
||||
uint16_t proxy_dst_port_len = 0;
|
||||
|
||||
peer->out = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// force this buffer to be destroyed as soon as possibile
|
||||
@@ -201,10 +216,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
struct uwsgi_buffer *out = peer->out;
|
||||
int found = 0;
|
||||
|
||||
if (uwsgi.enable_proxy_protocol || uhttp.enable_proxy_protocol) {
|
||||
ptr = proxy1_parse(ptr, watermark, &proxy_src, &proxy_src_len, &proxy_dst, &proxy_dst_len, &proxy_src_port, &proxy_src_port_len, &proxy_dst_port, &proxy_dst_port_len);
|
||||
base = ptr;
|
||||
}
|
||||
|
||||
// REQUEST_METHOD
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == ' ') {
|
||||
if (uwsgi_buffer_append_keyval(out, "REQUEST_METHOD", 14, base, ptr - base)) return -1;
|
||||
// on SOURCE METHOD, force raw body
|
||||
if (uhttp.manage_source && !uwsgi_strncmp(base, ptr - base, "SOURCE", 6)) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
ptr++;
|
||||
found = 1;
|
||||
break;
|
||||
@@ -324,12 +348,21 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (hr_https_add_vars(hr, out)) return -1;
|
||||
if (hr_https_add_vars(hr, peer, out)) return -1;
|
||||
#endif
|
||||
|
||||
// REMOTE_ADDR
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, peer->session->client_address, strlen(peer->session->client_address))) return -1;
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, peer->session->client_port, strlen(peer->session->client_port))) return -1;
|
||||
if (proxy_src) {
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, proxy_src, proxy_src_len)) return -1;
|
||||
if (proxy_src_port) {
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, proxy_src_port, proxy_src_port_len)) return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, peer->session->client_address, strlen(peer->session->client_address))) return -1;
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, peer->session->client_port, strlen(peer->session->client_port))) return -1;
|
||||
}
|
||||
|
||||
//HEADERS
|
||||
base = ptr;
|
||||
@@ -796,6 +829,13 @@ 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->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
// on raw body, ensure keepalive is disabled
|
||||
if (hr->raw_body) hr->session.can_keepalive = 0;
|
||||
|
||||
if (hr->session.can_keepalive && hr->content_length == 0) {
|
||||
main_peer->disabled = 1;
|
||||
// stop reading from the client
|
||||
@@ -807,9 +847,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
// reset main timeout
|
||||
http_set_timeout(main_peer, uhttp.cr.socket_timeout);
|
||||
|
||||
@@ -166,10 +166,17 @@ void uwsgi_opt_http_to_https(char *opt, char *value, void *cr) {
|
||||
ucr->has_sockets++;
|
||||
}
|
||||
|
||||
int hr_https_add_vars(struct http_session *hr, struct uwsgi_buffer *out) {
|
||||
int hr_https_add_vars(struct http_session *hr, struct corerouter_peer *peer, struct uwsgi_buffer *out) {
|
||||
// HTTPS (adapted from nginx)
|
||||
if (hr->session.ugs->mode == UWSGI_HTTP_SSL) {
|
||||
if (uwsgi_buffer_append_keyval(out, "HTTPS", 5, "on", 2)) return -1;
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
const char *servername = SSL_get_servername(hr->ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername) {
|
||||
peer->key = (char *) servername;
|
||||
peer->key_len = strlen(servername);
|
||||
}
|
||||
#endif
|
||||
hr->ssl_client_cert = SSL_get_peer_certificate(hr->ssl);
|
||||
if (hr->ssl_client_cert) {
|
||||
X509_NAME *name = X509_get_subject_name(hr->ssl_client_cert);
|
||||
|
||||
@@ -59,6 +59,7 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
uint32_t h_len = 0;
|
||||
|
||||
int has_size = 0;
|
||||
int has_connection = 0;
|
||||
|
||||
for(i=next;i<len;i++) {
|
||||
if (key) {
|
||||
@@ -73,6 +74,7 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
if (hr->session.can_keepalive) {
|
||||
#endif
|
||||
if (!uwsgi_strnicmp(key, colon-key, "Connection", 10)) {
|
||||
has_connection = 1;
|
||||
if (!uwsgi_strnicmp(colon+2, h_len-((colon-key)+2), "close", 5)) {
|
||||
goto end;
|
||||
}
|
||||
@@ -169,6 +171,10 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// avoid iOS making mess...
|
||||
if (!has_connection) {
|
||||
if (uwsgi_buffer_insert(ub, len-2, "Connection: close\r\n", 19)) return -1;
|
||||
}
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -811,8 +811,25 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -3) != 0) {
|
||||
http = lua_tolstring(L, -2, &slen);
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
|
||||
if (lua_type(L, -1) == LUA_TTABLE) {
|
||||
for (i = 1; /*empty*/ ; ++i) {
|
||||
lua_rawgeti(L, -1, i);
|
||||
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -768,6 +768,9 @@ XS(XS_sharedarea_wait) {
|
||||
id = SvIV(ST(0));
|
||||
if (items > 1) {
|
||||
freq = SvIV(ST(1));
|
||||
if (items > 2) {
|
||||
timeout = SvIV(ST(2));
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_sharedarea_wait(id, freq, timeout)) {
|
||||
|
||||
@@ -168,6 +168,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"py-sharedarea", required_argument, 0, "create a sharedarea from a python bytearray object of the specified size", uwsgi_opt_add_string_list, &up.sharedarea, 0},
|
||||
#endif
|
||||
|
||||
{"py-call-osafterfork", no_argument, 0, "enable child processes running cpython to trap OS signals", uwsgi_opt_true, &up.call_osafterfork, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -377,6 +379,11 @@ void uwsgi_python_post_fork() {
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
// reset python signal flags so child processes can trap signals
|
||||
if (up.call_osafterfork) {
|
||||
PyOS_AfterFork();
|
||||
}
|
||||
|
||||
uwsgi_python_reset_random_seed();
|
||||
|
||||
// call the post_fork_hook
|
||||
|
||||
@@ -1426,7 +1426,7 @@ PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int64_t value = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_inc64", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iL|l:sharedarea_inc64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1443,12 +1443,56 @@ PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iLI:sharedarea_write32", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write32(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write32()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write16(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int16_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iLI:sharedarea_write16", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write16(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write16()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int64_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ill:sharedarea_write64", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iLL:sharedarea_write64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1470,7 +1514,7 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
char *value;
|
||||
Py_ssize_t value_len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ils#:sharedarea_write", &id, &pos, &value, &value_len)) {
|
||||
if (!PyArg_ParseTuple(args, "iLs#:sharedarea_write", &id, &pos, &value, &value_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1570,7 +1614,7 @@ PyObject *py_uwsgi_sharedarea_write8(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int8_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ilb:sharedarea_write8", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iLb:sharedarea_write8", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1592,7 +1636,7 @@ PyObject *py_uwsgi_sharedarea_read64(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int64_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read64", &id, &pos)) {
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read64", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1604,16 +1648,59 @@ PyObject *py_uwsgi_sharedarea_read64(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read64()");
|
||||
}
|
||||
|
||||
return PyLong_FromLong(value);
|
||||
return PyLong_FromLongLong(value);
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read32", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read32(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read32()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read16(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int16_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read16", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read16(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read16()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read8(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int8_t byte;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read8", &id, &pos)) {
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read8", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1633,7 +1720,7 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
uint64_t len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_read", &id, &pos, &len)) {
|
||||
if (!PyArg_ParseTuple(args, "iL|L:sharedarea_read", &id, &pos, &len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2459,6 +2546,10 @@ static PyMethodDef uwsgi_sa_methods[] = {
|
||||
{"sharedarea_writelong", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_read64", py_uwsgi_sharedarea_read64, METH_VARARGS, ""},
|
||||
{"sharedarea_write64", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_read32", py_uwsgi_sharedarea_read32, METH_VARARGS, ""},
|
||||
{"sharedarea_write32", py_uwsgi_sharedarea_write32, METH_VARARGS, ""},
|
||||
{"sharedarea_read16", py_uwsgi_sharedarea_read16, METH_VARARGS, ""},
|
||||
{"sharedarea_write16", py_uwsgi_sharedarea_write16, METH_VARARGS, ""},
|
||||
{"sharedarea_inclong", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{"sharedarea_inc64", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{"sharedarea_rlock", py_uwsgi_sharedarea_rlock, METH_VARARGS, ""},
|
||||
@@ -3191,6 +3282,40 @@ PyObject *py_uwsgi_metric_get(PyObject * self, PyObject * args) {
|
||||
return PyLong_FromLongLong(value);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_set_max(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_set_max", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_set_max(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_set_min(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_set_min", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_set_min(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_metrics_methods[] = {
|
||||
{"metric_inc", py_uwsgi_metric_inc, METH_VARARGS, ""},
|
||||
@@ -3199,6 +3324,8 @@ static PyMethodDef uwsgi_metrics_methods[] = {
|
||||
{"metric_div", py_uwsgi_metric_div, METH_VARARGS, ""},
|
||||
{"metric_get", py_uwsgi_metric_get, METH_VARARGS, ""},
|
||||
{"metric_set", py_uwsgi_metric_set, METH_VARARGS, ""},
|
||||
{"metric_set_max", py_uwsgi_metric_set_max, METH_VARARGS, ""},
|
||||
{"metric_set_min", py_uwsgi_metric_set_min, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -197,6 +197,8 @@ struct uwsgi_python {
|
||||
PyObject *raw_callable;
|
||||
|
||||
struct uwsgi_string_list *sharedarea;
|
||||
|
||||
int call_osafterfork;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *u
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
@@ -132,6 +135,9 @@ int uwsgi_routing_func_sendfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
@@ -199,6 +205,9 @@ int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
|
||||
@@ -35,7 +35,13 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) ur->data;
|
||||
char *addr = ur->data + sizeof(struct uwsgi_header);
|
||||
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, addr, strlen(addr));
|
||||
if (!ub_addr) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->via = UWSGI_VIA_ROUTE;
|
||||
|
||||
@@ -66,18 +72,20 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
|
||||
if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->status = 202;
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_proxy_nb(wsgi_req, addr, ub, remains, uwsgi.socket_timeout)) {
|
||||
uwsgi_log("error routing request to uwsgi server %s\n", addr);
|
||||
if (uwsgi_proxy_nb(wsgi_req, ub_addr->buf, ub, remains, uwsgi.socket_timeout)) {
|
||||
uwsgi_log("error routing request to uwsgi server %s\n", ub_addr->buf);
|
||||
}
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
}
|
||||
|
||||
@@ -150,6 +150,11 @@ static void rrdtool_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, c
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int ret = snprintf(buf, 1024, "N:%lld", (long long) (*um->value));
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
if (ret < 3 || ret >= 1024) {
|
||||
uwsgi_log("unable to update rrdtool metric for %s\n", um->name);
|
||||
goto next;
|
||||
|
||||
@@ -92,6 +92,11 @@ static void stats_pusher_socket(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
socket_send_metric(ub, uspi, um);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
um = um->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
@@ -95,6 +95,11 @@ static void stats_pusher_statsd(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|m");
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
um = um->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
@@ -94,6 +94,13 @@ static void stats_pusher_zabbix(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
if (uwsgi_buffer_append(zn->ub, "\",\"value\":\"", 11)) { error = 1; goto end;}
|
||||
if (uwsgi_buffer_num64(zn->ub, *um->value)) { error = 1; goto end;}
|
||||
if (uwsgi_buffer_append(zn->ub, "\"}", 2)) { error = 1; goto end;}
|
||||
if (um->reset_after_push){
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
}
|
||||
um = um->next;
|
||||
if (um) {
|
||||
if (uwsgi_buffer_append(zn->ub, ",", 1)) { error = 1; goto end;}
|
||||
|
||||
+178
-149
@@ -8,12 +8,12 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct fcgi_record {
|
||||
uint8_t version;
|
||||
uint8_t type;
|
||||
uint8_t req1;
|
||||
uint8_t req0;
|
||||
uint8_t type;
|
||||
uint8_t req1;
|
||||
uint8_t req0;
|
||||
uint8_t cl1;
|
||||
uint8_t cl0;
|
||||
uint8_t pad;
|
||||
uint8_t pad;
|
||||
uint8_t reserved;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
@@ -24,39 +24,45 @@ int fastcgi_to_uwsgi(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
uint8_t octet;
|
||||
uint32_t keylen, vallen;
|
||||
for (j = 0; j < len; j++) {
|
||||
octet = (uint8_t) buf[j];
|
||||
if (octet > 127) {
|
||||
if (j + 4 >= len) return -1;
|
||||
octet = (uint8_t) buf[j];
|
||||
if (octet > 127) {
|
||||
if (j + 4 >= len)
|
||||
return -1;
|
||||
keylen = uwsgi_be32(&buf[j]) ^ 0x80000000;
|
||||
j += 4;
|
||||
j += 4;
|
||||
}
|
||||
else {
|
||||
if (j+1 >= len) return -1;
|
||||
if (j + 1 >= len)
|
||||
return -1;
|
||||
keylen = octet;
|
||||
j++;
|
||||
}
|
||||
octet = (uint8_t) buf[j];
|
||||
if (octet > 127) {
|
||||
if (j + 4 >= len) return -1;
|
||||
octet = (uint8_t) buf[j];
|
||||
if (octet > 127) {
|
||||
if (j + 4 >= len)
|
||||
return -1;
|
||||
vallen = uwsgi_be32(&buf[j]) ^ 0x80000000;
|
||||
j += 4;
|
||||
j += 4;
|
||||
}
|
||||
else {
|
||||
if (j+1 >= len) return -1;
|
||||
if (j + 1 >= len)
|
||||
return -1;
|
||||
vallen = octet;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (j + (keylen + vallen) > len) {
|
||||
if (j + (keylen + vallen) > len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (keylen > 0xffff || vallen > 0xffff) return -1;
|
||||
if (keylen > 0xffff || vallen > 0xffff)
|
||||
return -1;
|
||||
uint16_t pktsize = proto_base_add_uwsgi_var(wsgi_req, buf + j, keylen, buf + j + keylen, vallen);
|
||||
if (pktsize == 0) return -1;
|
||||
wsgi_req->uh->pktsize += pktsize;
|
||||
if (pktsize == 0)
|
||||
return -1;
|
||||
wsgi_req->uh->pktsize += pktsize;
|
||||
// -1 here as the for() will increment j again
|
||||
j += (keylen + vallen) - 1;
|
||||
j += (keylen + vallen) - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -66,7 +72,7 @@ int fastcgi_to_uwsgi(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
/*
|
||||
|
||||
each fastcgi packet is composed by a header and a body
|
||||
the parser rebuild a whole packet until it find a 0 PARAMS or a STDIN one
|
||||
the parser rebuild a whole packet until it finds a 0 STDIN
|
||||
|
||||
*/
|
||||
|
||||
@@ -78,38 +84,40 @@ int uwsgi_proto_fastcgi_parser(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->proto_parser_buf_size = uwsgi.buffer_size;
|
||||
}
|
||||
|
||||
ssize_t len = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
ssize_t len = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
if (len > 0) {
|
||||
goto parse;
|
||||
}
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
uwsgi_error("uwsgi_proto_fastcgi_parser()");
|
||||
return -1;
|
||||
}
|
||||
// mute on 0 len...
|
||||
if (wsgi_req->proto_parser_pos > 0) {
|
||||
uwsgi_error("uwsgi_proto_fastcgi_parser()");
|
||||
}
|
||||
return -1;
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
uwsgi_error("uwsgi_proto_fastcgi_parser()");
|
||||
return -1;
|
||||
}
|
||||
// mute on 0 len...
|
||||
if (wsgi_req->proto_parser_pos > 0) {
|
||||
uwsgi_error("uwsgi_proto_fastcgi_parser()");
|
||||
}
|
||||
return -1;
|
||||
parse:
|
||||
wsgi_req->proto_parser_pos += len;
|
||||
// ok let's see what we need to do
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
if (wsgi_req->proto_parser_pos >= sizeof(struct fcgi_record)) {
|
||||
struct fcgi_record *fr = (struct fcgi_record *) wsgi_req->proto_parser_buf;
|
||||
uint16_t fcgi_len = uwsgi_be16((char *)&fr->cl1);
|
||||
uint16_t fcgi_len = uwsgi_be16((char *) &fr->cl1);
|
||||
uint32_t fcgi_all_len = sizeof(struct fcgi_record) + fcgi_len + fr->pad;
|
||||
uint8_t fcgi_type = fr->type;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
uint8_t *sid = (uint8_t *) & wsgi_req->stream_id;
|
||||
sid[0] = fr->req0;
|
||||
sid[1] = fr->req1;
|
||||
// if STDIN, end of the loop
|
||||
if (fcgi_type == 5) {
|
||||
wsgi_req->uh->modifier1 = uwsgi.fastcgi_modifier1;
|
||||
wsgi_req->uh->modifier2 = uwsgi.fastcgi_modifier2;
|
||||
// does the request stream ended ?
|
||||
if (fcgi_len == 0) wsgi_req->proto_parser_eof = 1;
|
||||
return UWSGI_OK;
|
||||
}
|
||||
// if we have a full packet, parse it and reset the memory
|
||||
@@ -122,12 +130,6 @@ parse:
|
||||
}
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
// end of PARAMS
|
||||
if (fcgi_type == 4 && fcgi_len == 0) {
|
||||
wsgi_req->uh->modifier1 = uwsgi.fastcgi_modifier1;
|
||||
wsgi_req->uh->modifier2 = uwsgi.fastcgi_modifier2;
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
else if (fcgi_all_len > wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos) {
|
||||
char *tmp_buf = realloc(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf_size + fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos));
|
||||
@@ -152,33 +154,41 @@ parse:
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
int has_read = 0;
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
|
||||
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
|
||||
wsgi_req->proto_parser_remains -= remains;
|
||||
wsgi_req->proto_parser_remains_buf += remains;
|
||||
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
|
||||
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
|
||||
wsgi_req->proto_parser_remains -= remains;
|
||||
wsgi_req->proto_parser_remains_buf += remains;
|
||||
// we consumed all of the body, we can safely move the memory
|
||||
if (wsgi_req->proto_parser_remains == 0 && wsgi_req->proto_parser_move) {
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_move, wsgi_req->proto_parser_pos);
|
||||
if (wsgi_req->proto_parser_remains == 0 && wsgi_req->proto_parser_move) {
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_move, wsgi_req->proto_parser_pos);
|
||||
wsgi_req->proto_parser_move = 0;
|
||||
}
|
||||
return remains;
|
||||
}
|
||||
}
|
||||
return remains;
|
||||
}
|
||||
|
||||
// if we already have seen eof, return 0
|
||||
if (wsgi_req->proto_parser_eof) return 0;
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
for(;;) {
|
||||
if (wsgi_req->proto_parser_pos >= sizeof(struct fcgi_record)) {
|
||||
struct fcgi_record *fr = (struct fcgi_record *) wsgi_req->proto_parser_buf;
|
||||
uint16_t fcgi_len = uwsgi_be16((char *)&fr->cl1);
|
||||
for (;;) {
|
||||
if (wsgi_req->proto_parser_pos >= sizeof(struct fcgi_record)) {
|
||||
struct fcgi_record *fr = (struct fcgi_record *) wsgi_req->proto_parser_buf;
|
||||
uint16_t fcgi_len = uwsgi_be16((char *) &fr->cl1);
|
||||
uint32_t fcgi_all_len = sizeof(struct fcgi_record) + fcgi_len + fr->pad;
|
||||
uint8_t fcgi_type = fr->type;
|
||||
// if we have a full packet, parse it and reset the memory
|
||||
if (wsgi_req->proto_parser_pos >= fcgi_all_len) {
|
||||
// STDIN ? (ignore other types)
|
||||
if (fcgi_type == 5) {
|
||||
uint8_t fcgi_type = fr->type;
|
||||
// if we have a full packet, parse it and reset the memory
|
||||
if (wsgi_req->proto_parser_pos >= fcgi_all_len) {
|
||||
// STDIN ? (ignore other types)
|
||||
if (fcgi_type == 5) {
|
||||
// EOF ?
|
||||
if (fcgi_len == 0) {
|
||||
wsgi_req->proto_parser_eof = 1;
|
||||
return 0;
|
||||
}
|
||||
// copy data to the buf
|
||||
size_t remains = UMIN(fcgi_len, len);
|
||||
memcpy(buf, wsgi_req->proto_parser_buf + sizeof(struct fcgi_record), remains);
|
||||
@@ -187,45 +197,46 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf + sizeof(struct fcgi_record) + remains;
|
||||
// we consumed all of the body, we can safely move the memory
|
||||
if (wsgi_req->proto_parser_remains == 0) {
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
}
|
||||
else {
|
||||
// postpone memory move
|
||||
wsgi_req->proto_parser_move = fcgi_all_len;
|
||||
}
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
return remains;
|
||||
}
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
}
|
||||
else if (fcgi_all_len > wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos) {
|
||||
char *tmp_buf = realloc(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf_size + fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_proto_fastcgi_read_body()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->proto_parser_buf = tmp_buf;
|
||||
wsgi_req->proto_parser_buf_size += fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
}
|
||||
if (!has_read) goto gather;
|
||||
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
|
||||
wsgi_req->proto_parser_pos -= fcgi_all_len;
|
||||
}
|
||||
else if (fcgi_all_len > wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos) {
|
||||
char *tmp_buf = realloc(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf_size + fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_proto_fastcgi_read_body()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->proto_parser_buf = tmp_buf;
|
||||
wsgi_req->proto_parser_buf_size += fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
}
|
||||
if (!has_read)
|
||||
goto gather;
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
gather:
|
||||
rlen = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
rlen = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
|
||||
if (rlen > 0) {
|
||||
has_read = 1;
|
||||
wsgi_req->proto_parser_pos += rlen;
|
||||
continue;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// write a STDOUT packet
|
||||
@@ -233,12 +244,12 @@ int uwsgi_proto_fastcgi_write(struct wsgi_request *wsgi_req, char *buf, size_t l
|
||||
|
||||
// fastcgi packets are limited to 64k
|
||||
if (wsgi_req->proto_parser_status == 0) {
|
||||
uint16_t fcgi_len = UMIN(len-wsgi_req->write_pos, 0xffff);
|
||||
uint16_t fcgi_len = UMIN(len - wsgi_req->write_pos, 0xffff);
|
||||
wsgi_req->proto_parser_status = fcgi_len;
|
||||
struct fcgi_record fr;
|
||||
fr.version = 1;
|
||||
fr.type = 6;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
uint8_t *sid = (uint8_t *) & wsgi_req->stream_id;
|
||||
fr.req1 = sid[1];
|
||||
fr.req0 = sid[0];
|
||||
fr.pad = 0;
|
||||
@@ -250,25 +261,42 @@ int uwsgi_proto_fastcgi_write(struct wsgi_request *wsgi_req, char *buf, size_t l
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t wlen = write(wsgi_req->fd, buf+wsgi_req->write_pos, wsgi_req->proto_parser_status);
|
||||
if (wlen > 0) {
|
||||
wsgi_req->write_pos += wlen;
|
||||
ssize_t wlen = write(wsgi_req->fd, buf + wsgi_req->write_pos, wsgi_req->proto_parser_status);
|
||||
if (wlen > 0) {
|
||||
wsgi_req->write_pos += wlen;
|
||||
wsgi_req->proto_parser_status -= wlen;
|
||||
if (wsgi_req->write_pos == len) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (wlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (wsgi_req->write_pos == len) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (wlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_proto_fastcgi_close(struct wsgi_request *wsgi_req) {
|
||||
// before sending the END_REQUEST and closing the connection we need to check for EOF
|
||||
if (!wsgi_req->proto_parser_eof) {
|
||||
// we use a custom tiny buffer, all the data will be discarded...
|
||||
char buf[4096];
|
||||
for(;;) {
|
||||
ssize_t rlen = uwsgi_proto_fastcgi_read_body(wsgi_req, buf, 4096);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) {
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) goto end;
|
||||
continue;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (rlen == 0) break;
|
||||
}
|
||||
}
|
||||
// special case here, we run in void context, so we need to wait directly here
|
||||
char end_request[24];
|
||||
memcpy(end_request, FCGI_END_REQUEST, 24);
|
||||
@@ -279,69 +307,70 @@ void uwsgi_proto_fastcgi_close(struct wsgi_request *wsgi_req) {
|
||||
end_request[10] = sid[1];
|
||||
end_request[11] = sid[0];
|
||||
(void) uwsgi_write_true_nb(wsgi_req->fd, end_request, 24, uwsgi.socket_timeout);
|
||||
end:
|
||||
uwsgi_proto_base_close(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_proto_fastcgi_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
// fastcgi packets are limited to 64k
|
||||
if (wsgi_req->proto_parser_status == 0) {
|
||||
uint16_t fcgi_len = (uint16_t) UMIN(len-wsgi_req->write_pos, 0xffff);
|
||||
wsgi_req->proto_parser_status = fcgi_len;
|
||||
struct fcgi_record fr;
|
||||
fr.version = 1;
|
||||
fr.type = 6;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
fr.req1 = sid[1];
|
||||
fr.req0 = sid[0];
|
||||
fr.pad = 0;
|
||||
fr.reserved = 0;
|
||||
fr.cl0 = (uint8_t) (fcgi_len & 0xff);
|
||||
fr.cl1 = (uint8_t) ((fcgi_len >> 8) & 0xff);
|
||||
if (uwsgi_write_true_nb(wsgi_req->fd, (char *) &fr, sizeof(struct fcgi_record), uwsgi.socket_timeout)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (wsgi_req->proto_parser_status == 0) {
|
||||
uint16_t fcgi_len = (uint16_t) UMIN(len - wsgi_req->write_pos, 0xffff);
|
||||
wsgi_req->proto_parser_status = fcgi_len;
|
||||
struct fcgi_record fr;
|
||||
fr.version = 1;
|
||||
fr.type = 6;
|
||||
uint8_t *sid = (uint8_t *) & wsgi_req->stream_id;
|
||||
fr.req1 = sid[1];
|
||||
fr.req0 = sid[0];
|
||||
fr.pad = 0;
|
||||
fr.reserved = 0;
|
||||
fr.cl0 = (uint8_t) (fcgi_len & 0xff);
|
||||
fr.cl1 = (uint8_t) ((fcgi_len >> 8) & 0xff);
|
||||
if (uwsgi_write_true_nb(wsgi_req->fd, (char *) &fr, sizeof(struct fcgi_record), uwsgi.socket_timeout)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t wlen = uwsgi_sendfile_do(wsgi_req->fd, fd, pos+wsgi_req->write_pos, wsgi_req->proto_parser_status);
|
||||
if (wlen > 0) {
|
||||
wsgi_req->write_pos += wlen;
|
||||
ssize_t wlen = uwsgi_sendfile_do(wsgi_req->fd, fd, pos + wsgi_req->write_pos, wsgi_req->proto_parser_status);
|
||||
if (wlen > 0) {
|
||||
wsgi_req->write_pos += wlen;
|
||||
wsgi_req->proto_parser_status -= wlen;
|
||||
if (wsgi_req->write_pos == len) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (wlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (wsgi_req->write_pos == len) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (wlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_proto_fastcgi_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
void uwsgi_proto_fastcgi_nph_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, s
|
||||
return 2 + keylen + 2 + hvlen;
|
||||
}
|
||||
|
||||
static char *proxy1_parse(char *ptr, char *watermark, char **src, uint16_t *src_len, char **dst, uint16_t *dst_len, char **src_port, uint16_t *src_port_len, char **dst_port, uint16_t *dst_port_len) {
|
||||
char *proxy1_parse(char *ptr, char *watermark, char **src, uint16_t *src_len, char **dst, uint16_t *dst_len, char **src_port, uint16_t *src_port_len, char **dst_port, uint16_t *dst_port_len) {
|
||||
// check for PROXY header
|
||||
if (watermark - ptr > 6) {
|
||||
if (memcmp(ptr, "PROXY ", 6)) return ptr;
|
||||
|
||||
@@ -9,4 +9,5 @@ cache2 = name=items_17,blocks=17,items=17,bitmap=1,blocksize=1
|
||||
cache2 = name=items_4_10,blocks=5,items=5,bitmap=1,blocksize=10
|
||||
cache2 = name=items_1_100000,blocks=1000,items=2,bitmap=1,blocksize=100
|
||||
cache2 = name=items_non_bitmap,items=2,blocksize=20
|
||||
cache2 = name=items_lru,items=3,blocksize=20,purge_lru=1
|
||||
pyrun = t/cachebitmap.py
|
||||
|
||||
+11
-1
@@ -5,7 +5,7 @@ import string
|
||||
|
||||
class BitmapTest(unittest.TestCase):
|
||||
|
||||
__caches__ = ['items_1', 'items_2', 'items_3', 'items_4', 'items_17', 'items_4_10', 'items_1_100000', 'items_non_bitmap']
|
||||
__caches__ = ['items_1', 'items_2', 'items_3', 'items_4', 'items_17', 'items_4_10', 'items_1_100000', 'items_non_bitmap', 'items_lru']
|
||||
|
||||
def setUp(self):
|
||||
for cache in self.__caches__:
|
||||
@@ -103,4 +103,14 @@ class BitmapTest(unittest.TestCase):
|
||||
self.assertIsNone(uwsgi.cache_set('KEY', 'X' * 21, 0, 'items_non_bitmap'))
|
||||
self.assertTrue(uwsgi.cache_set('KEY', 'X' * 20, 0, 'items_non_bitmap'))
|
||||
|
||||
def test_lru(self):
|
||||
self.assertTrue(uwsgi.cache_set('KEY1', 'X' * 20, 0, 'items_lru'))
|
||||
self.assertTrue(uwsgi.cache_set('KEY2', 'X' * 20, 0, 'items_lru'))
|
||||
self.assertTrue(uwsgi.cache_set('KEY3', 'Y' * 20, 0, 'items_lru'))
|
||||
self.assertIsNone(uwsgi.cache_get('KEY1', 'items_lru'))
|
||||
second_item = uwsgi.cache_get('KEY3', 'items_lru')
|
||||
for i in range(4,100):
|
||||
self.assertTrue(uwsgi.cache_set('KEY%d' % i, 'Y' * 20, 0, 'items_lru'))
|
||||
self.assertIsNone(uwsgi.cache_get('KEY%d' % (i-2), 'items_lru'))
|
||||
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
function hello(wsapi_env)
|
||||
local headers = { ["Content-type"] = "text/html", ["set-cookie"] = {"foo=bar", "bar=baz"} }
|
||||
local function hello_text()
|
||||
coroutine.yield("<html><body>")
|
||||
coroutine.yield("<p>Hello Wsapi!</p>")
|
||||
coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>")
|
||||
coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>")
|
||||
coroutine.yield("<p>QUERY_STRING: " .. wsapi_env.QUERY_STRING .. "</p>")
|
||||
coroutine.yield("</body></html>")
|
||||
end
|
||||
return 200, headers, coroutine.wrap(hello_text)
|
||||
end
|
||||
|
||||
return hello
|
||||
@@ -0,0 +1,58 @@
|
||||
use v5.10.0;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Time::HiRes qw(sleep);
|
||||
use autodie qw(:all);
|
||||
|
||||
my $psgi = $ARGV[0] || 't/perl/test_hello.psgi';
|
||||
|
||||
for my $use_thunder_lock (0,1) {
|
||||
for my $cpu_multiplier (1,2,4,8,16,32,64) {
|
||||
my $procs = 16 * $cpu_multiplier;
|
||||
my $desc = sprintf "%3d procs %2s/TL", $procs, ($use_thunder_lock ? "w" : "wo");
|
||||
my $tl_cl = $use_thunder_lock ? "--thunder-lock --lock-engine ipcsem --ftok $psgi" : "";
|
||||
|
||||
#say STDERR "Now testing $desc";
|
||||
system q[for p in $(ps auxf|grep uwsgi.*--disable-logging|grep -v grep|awk '{print $2}'); do kill $p; done];
|
||||
system qq[./uwsgi --http 127.0.0.1:8080 --processes $procs --psgi $psgi --disable-logging $tl_cl >/dev/null 2>&1 &];
|
||||
sleep 0.5;
|
||||
chomp(my $ab = qx[http_proxy= ab -n 10000 -c 32 http://localhost:8080/ 2>&1]);
|
||||
my ($seconds) = $ab =~ m[Time taken for tests:\s+([0-9.]+) seconds];
|
||||
say STDERR "$seconds\t$desc";
|
||||
system q[for p in $(ps auxf|grep uwsgi.*--disable-logging|grep -v grep|awk '{print $2}'); do kill $p; done];
|
||||
sleep 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
||||
$ perl t/perl/test_benchmark.pl t/perl/test_sleepy.psgi
|
||||
7.128 16 procs wo/TL
|
||||
3.547 32 procs wo/TL
|
||||
2.038 64 procs wo/TL
|
||||
2.880 128 procs wo/TL
|
||||
4.578 256 procs wo/TL
|
||||
8.199 512 procs wo/TL
|
||||
13.379 1024 procs wo/TL
|
||||
7.123 16 procs w/TL
|
||||
3.559 32 procs w/TL
|
||||
2.036 64 procs w/TL
|
||||
1.972 128 procs w/TL
|
||||
2.026 256 procs w/TL
|
||||
2.172 512 procs w/TL
|
||||
2.412 1024 procs w/TL
|
||||
|
||||
$ perl t/perl/test_benchmark.pl t/perl/test_hello.psgi
|
||||
1.392 16 procs wo/TL
|
||||
1.743 32 procs wo/TL
|
||||
2.374 64 procs wo/TL
|
||||
3.530 128 procs wo/TL
|
||||
4.984 256 procs wo/TL
|
||||
8.258 512 procs wo/TL
|
||||
9.343 1024 procs wo/TL
|
||||
1.134 16 procs w/TL
|
||||
1.284 32 procs w/TL
|
||||
1.152 64 procs w/TL
|
||||
1.084 128 procs w/TL
|
||||
1.286 256 procs w/TL
|
||||
1.559 512 procs w/TL
|
||||
1.537 1024 procs w/TL
|
||||
@@ -0,0 +1,8 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub {
|
||||
my $env = shift;
|
||||
|
||||
return [200, [], [ "Hello, world!" ]];
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
use Time::HiRes qw(usleep);
|
||||
|
||||
sub {
|
||||
my $env = shift;
|
||||
|
||||
die "PANIC: We are expecting to support psgix.cleanup" unless $env->{'psgix.cleanup'};
|
||||
my $msleep = 2 * 1000 + int rand 7 * 1000; # 2..10ms
|
||||
my $csleep = 2 * 1000 + int rand 7 * 1000; # 2..10ms
|
||||
|
||||
push @{$env->{'psgix.cleanup.handlers'}} => sub { usleep($csleep) };
|
||||
usleep($msleep);
|
||||
|
||||
return [
|
||||
200,
|
||||
[],
|
||||
[ "Responding. Slept $msleep us in the main phase, sleeping $csleep us in the cleanup phase" ],
|
||||
];
|
||||
}
|
||||
+1
-1
@@ -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 = '2014-04-22'
|
||||
s.date = '2014-06-02'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -897,6 +897,7 @@ struct uwsgi_opt {
|
||||
#define UWSGI_EXCEPTION_CODE 5
|
||||
#define UWSGI_QUIET_CODE 29
|
||||
#define UWSGI_BRUTAL_RELOAD_CODE 31
|
||||
#define UWSGI_GO_CHEAP_CODE 15
|
||||
|
||||
#define MAX_VARS 64
|
||||
|
||||
@@ -1566,6 +1567,11 @@ struct wsgi_request {
|
||||
#ifdef UWSGI_SSL
|
||||
SSL *ssl;
|
||||
#endif
|
||||
|
||||
// do not update avg_rt after request
|
||||
int do_not_account_avg_rt;
|
||||
// used for protocol parsers requiring EOF signaling
|
||||
int proto_parser_eof;
|
||||
};
|
||||
|
||||
|
||||
@@ -2706,6 +2712,17 @@ struct uwsgi_server {
|
||||
char *notify_socket;
|
||||
int notify_socket_fd;
|
||||
char *subscription_notify_socket;
|
||||
|
||||
//uWSGI 2.0.5
|
||||
|
||||
int mule_reload_mercy;
|
||||
int alarm_cheap;
|
||||
|
||||
int emperor_no_blacklist;
|
||||
int metrics_no_cores;
|
||||
int stats_no_cores;
|
||||
int stats_no_metrics;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -2939,6 +2956,9 @@ struct uwsgi_mule {
|
||||
time_t user_harakiri;
|
||||
|
||||
char name[0xff];
|
||||
|
||||
time_t cursed_at;
|
||||
time_t no_mercy_at;
|
||||
};
|
||||
|
||||
struct uwsgi_mule_farm {
|
||||
@@ -3006,6 +3026,7 @@ void spooler(struct uwsgi_spooler *);
|
||||
pid_t spooler_start(struct uwsgi_spooler *);
|
||||
|
||||
void uwsgi_curse(int, int);
|
||||
void uwsgi_curse_mule(int, int);
|
||||
void uwsgi_destroy_processes(void);
|
||||
|
||||
void set_harakiri(int);
|
||||
@@ -3771,6 +3792,8 @@ int uwsgi_logic_opt_if_plugin(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_plugin(char *, char *);
|
||||
|
||||
|
||||
void uwsgi_opt_resolve(char *, char *, void *);
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
void uwsgi_opt_set_cap(char *, char *, void *);
|
||||
void uwsgi_opt_set_emperor_cap(char *, char *, void *);
|
||||
@@ -4143,7 +4166,6 @@ char *uwsgi_elf_section(char *, char *, size_t *);
|
||||
|
||||
void uwsgi_alarm_log_check(char *, size_t);
|
||||
void uwsgi_alarm_run(struct uwsgi_alarm_instance *, char *, size_t);
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *, char *, size_t);
|
||||
void uwsgi_register_alarm(char *, void (*)(struct uwsgi_alarm_instance *), void (*)(struct uwsgi_alarm_instance *, char *, size_t));
|
||||
void uwsgi_register_embedded_alarms();
|
||||
void uwsgi_alarms_init();
|
||||
@@ -4169,6 +4191,7 @@ struct uwsgi_thread {
|
||||
void (*func) (struct uwsgi_thread *);
|
||||
};
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*)(struct uwsgi_thread *));
|
||||
struct uwsgi_thread *uwsgi_thread_new_with_data(void (*)(struct uwsgi_thread *), void *data);
|
||||
|
||||
struct uwsgi_offload_request {
|
||||
// the request socket
|
||||
@@ -4421,6 +4444,7 @@ int uwsgi_exceptions_catch(struct wsgi_request *);
|
||||
uint64_t uwsgi_worker_exceptions(int);
|
||||
struct uwsgi_exception_handler *uwsgi_register_exception_handler(char *, int (*)(struct uwsgi_exception_handler_instance *, char *, size_t));
|
||||
|
||||
char *proxy1_parse(char *ptr, char *watermark, char **src, uint16_t *src_len, char **dst, uint16_t *dst_len, char **src_port, uint16_t *src_port_len, char **dst_port, uint16_t *dst_port_len);
|
||||
void uwsgi_async_queue_is_full(time_t);
|
||||
char *uwsgi_get_header(struct wsgi_request *, char *, uint16_t, uint16_t *);
|
||||
|
||||
@@ -4663,6 +4687,9 @@ struct uwsgi_metric {
|
||||
struct uwsgi_metric_threshold *thresholds;
|
||||
|
||||
struct uwsgi_metric *next;
|
||||
|
||||
// allow to reset metrics after each push
|
||||
uint8_t reset_after_push;
|
||||
};
|
||||
|
||||
struct uwsgi_metric_child {
|
||||
@@ -4680,6 +4707,8 @@ int uwsgi_metric_mul(char *, char *, int64_t);
|
||||
int uwsgi_metric_div(char *, char *, int64_t);
|
||||
int64_t uwsgi_metric_get(char *, char *);
|
||||
int64_t uwsgi_metric_getn(char *, size_t, char *, size_t);
|
||||
int uwsgi_metric_set_max(char *, char *, int64_t);
|
||||
int uwsgi_metric_set_min(char *, char *, int64_t);
|
||||
|
||||
struct uwsgi_metric_collector *uwsgi_register_metric_collector(char *, int64_t (*)(struct uwsgi_metric *));
|
||||
struct uwsgi_metric *uwsgi_register_metric(char *, char *, uint8_t, char *, void *, uint32_t, void *);
|
||||
@@ -4707,6 +4736,7 @@ void uwsgi_sharedareas_init();
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int);
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *, uint64_t);
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int, uint64_t, off_t);
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int, uint64_t, char *, uint64_t);
|
||||
int uwsgi_sharedarea_write(int, uint64_t, char *, uint64_t);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0.4'
|
||||
uwsgi_version = '2.0.5.1'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -1058,7 +1058,7 @@ class uConf(object):
|
||||
|
||||
self.embed_config = None
|
||||
|
||||
if uwsgi_os in ('Linux','FreeBSD'):
|
||||
if uwsgi_os not in ('Darwin',):
|
||||
self.embed_config = os.environ.get('UWSGI_EMBED_CONFIG')
|
||||
if not self.embed_config:
|
||||
self.embed_config = self.get('embed_config')
|
||||
|
||||
Reference in New Issue
Block a user