mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c9ebdaa69 | ||
|
|
fbd9e5b4d7 | ||
|
|
b9a3425b6d | ||
|
|
d4742c611b | ||
|
|
c645a590aa | ||
|
|
275a7fe63f | ||
|
|
0ff16d8312 | ||
|
|
1cb31d6c7e | ||
|
|
8a6eb553df | ||
|
|
946af8b9ee | ||
|
|
098a1f647e | ||
|
|
c9681dc430 | ||
|
|
ff0b8b2d53 | ||
|
|
75f520d43a | ||
|
|
65209748ba | ||
|
|
cd604ef07b | ||
|
|
51da8bc531 | ||
|
|
2374ba12bd | ||
|
|
0a75aaec25 | ||
|
|
a8c286ae83 |
+2
-2
@@ -181,6 +181,7 @@ void uwsgi_daemons_spawn_all() {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ud->registered = 1;
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -194,7 +195,6 @@ void uwsgi_daemons_spawn_all() {
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -366,7 +366,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
freq = atoi(comma + 1);
|
||||
}
|
||||
command = space + 1;
|
||||
if (!strcmp(opt, "smart-attach-daemon2")) {
|
||||
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
daemonize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -348,7 +348,8 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes();
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -853,6 +853,7 @@ next:
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
|
||||
@@ -388,6 +388,12 @@ void uwsgi_reload(char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.alarm_thread) {
|
||||
if (i == uwsgi.alarm_thread->queue) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[0]) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[1]) continue;
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
|
||||
+18
-12
@@ -77,19 +77,8 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_run();
|
||||
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
@@ -98,6 +87,23 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_run() {
|
||||
int id = uwsgi.muleid;
|
||||
int i;
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
|
||||
+53
-7
@@ -166,9 +166,8 @@ static void uwsgi_routing_reset_memory(struct wsgi_request *wsgi_req, struct uws
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
int n = -1;
|
||||
|
||||
char *orig_subject = subject;
|
||||
@@ -268,9 +267,22 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
return uwsgi_apply_routes_do(wsgi_req, NULL, 0);
|
||||
return uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
void uwsgi_apply_final_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.final_routes) return;
|
||||
|
||||
// avoid loops
|
||||
if (wsgi_req->is_routing) return;
|
||||
|
||||
wsgi_req->is_final_routing = 1;
|
||||
|
||||
uwsgi_apply_routes_do(uwsgi.final_routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
while(urc) {
|
||||
@@ -286,7 +298,10 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *space = NULL;
|
||||
char *command = NULL;
|
||||
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
|
||||
struct uwsgi_route *old_ur = NULL, *ur = uwsgi.routes;
|
||||
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
|
||||
ur = uwsgi.final_routes;
|
||||
}
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
old_ur = ur;
|
||||
@@ -298,7 +313,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
old_ur->next = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
|
||||
uwsgi.final_routes = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
}
|
||||
}
|
||||
|
||||
ur->pos = pos;
|
||||
@@ -409,8 +429,7 @@ done:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_fixup_routes() {
|
||||
struct uwsgi_route *ur = uwsgi.routes;
|
||||
void uwsgi_fixup_routes(struct uwsgi_route *ur) {
|
||||
while(ur) {
|
||||
// prepare the main pointers
|
||||
ur->ovn = uwsgi_calloc(sizeof(int) * uwsgi.cores);
|
||||
@@ -612,6 +631,9 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
|
||||
|
||||
// find the label
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (wsgi_req->is_final_routing) {
|
||||
routes = uwsgi.final_routes;
|
||||
}
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
|
||||
@@ -1291,6 +1313,14 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
uwsgi_uuid(ret);
|
||||
*vallen = 36;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "status", 6)) {
|
||||
ret = uwsgi_num2str(wsgi_req->status);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "rtime", 5)) {
|
||||
ret = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1537,5 +1567,21 @@ void uwsgi_routing_dump() {
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal routing table ***\n");
|
||||
routes = uwsgi.final_routes;
|
||||
if (!routes) return;
|
||||
uwsgi_log("*** dumping internal final routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal final routing table ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
+21
-15
@@ -122,21 +122,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
|
||||
@@ -145,6 +131,26 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
void uwsgi_spooler_run() {
|
||||
int i;
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
}
|
||||
|
||||
void destroy_spool(char *dir, char *file) {
|
||||
|
||||
if (chdir(dir)) {
|
||||
|
||||
+1
-1
@@ -644,7 +644,7 @@ safe:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
|
||||
+26
-9
@@ -607,6 +607,20 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = rss;
|
||||
}
|
||||
|
||||
if (!wsgi_req->do_not_account) {
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
|
||||
// this is used for MAX_REQUESTS
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests++;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply final routes after accounting
|
||||
uwsgi_apply_final_routes(wsgi_req);
|
||||
#endif
|
||||
|
||||
// close the connection with the client
|
||||
if (!wsgi_req->fd_closed) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
@@ -629,15 +643,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
}
|
||||
|
||||
if (!wsgi_req->do_not_account) {
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
|
||||
// this is used for MAX_REQUESTS
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests++;
|
||||
}
|
||||
|
||||
// after_request hook
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->after_request)
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req);
|
||||
@@ -2225,6 +2230,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
|
||||
uwsgi_string->next = NULL;
|
||||
uwsgi_string->custom = 0;
|
||||
uwsgi_string->custom2 = 0;
|
||||
uwsgi_string->custom_ptr = NULL;
|
||||
|
||||
return uwsgi_string;
|
||||
}
|
||||
@@ -3939,3 +3945,14 @@ void http_url_encode(char *buf, uint16_t *len, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_takeover() {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (uwsgi.muleid) {
|
||||
uwsgi_mule_run();
|
||||
}
|
||||
else {
|
||||
uwsgi_worker_run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,6 +531,22 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
|
||||
|
||||
{"final-route", required_argument, 0, "add a final route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"final-route-host", required_argument, 0, "add a final route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"final-route-uri", required_argument, 0, "add a final route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"final-route-qs", required_argument, 0, "add a final route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"final-route-remote-addr", required_argument, 0, "add a final route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"final-route-user-agent", required_argument, 0, "add a final route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"final-route-remote-user", required_argument, 0, "add a final route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"final-route-referer", required_argument, 0, "add a final route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"final-route-label", required_argument, 0, "add a final routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"final-route-if", required_argument, 0, "add a final route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"final-route-if-not", required_argument, 0, "add a final route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"final-route-run", required_argument, 0, "always run the specified final route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -2790,6 +2806,16 @@ next2:
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_worker_run();
|
||||
// never here
|
||||
_exit(0);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_worker_run() {
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.lazy || uwsgi.lazy_apps) {
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ struct uwsgi_airbrake_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *apikey;
|
||||
char *env;
|
||||
};
|
||||
|
||||
struct uwsgi_airbrake_opt {
|
||||
@@ -28,9 +29,14 @@ static void uwsgi_airbrake_set_apikey(CURL *curl, CURLoption option, char *arg,
|
||||
uacc->apikey = arg;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_set_env(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
uacc->env = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_airbrake_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
{"apikey", 0, uwsgi_airbrake_set_apikey},
|
||||
{"env", 0, uwsgi_airbrake_set_env},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_airbrake_ssl},
|
||||
{"timeout", CURLOPT_TIMEOUT, uwsgi_airbrake_int},
|
||||
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_airbrake_int},
|
||||
@@ -65,78 +71,89 @@ end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_airbrake_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) {
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
}
|
||||
|
||||
static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apikey) {
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
|
||||
xmlChar *xmlbuff;
|
||||
int buffersize;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr notice_node = NULL, node = NULL, line_node = NULL, errnode = NULL;
|
||||
char *msg = uwsgi_str("uWSGI segfault");
|
||||
char *msg = NULL;
|
||||
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
notice_node = xmlNewNode(NULL, BAD_CAST "notice");
|
||||
xmlNewProp(notice_node, BAD_CAST "version", BAD_CAST "2.3");
|
||||
xmlDocSetRootElement(doc, notice_node);
|
||||
|
||||
xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST apikey);
|
||||
xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST uacc->apikey);
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "notifier", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST "uWSGI");
|
||||
xmlNewChild(node, NULL, BAD_CAST "version", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewChild(node, NULL, BAD_CAST "url", BAD_CAST "https://github.com/unbit/uwsgi");
|
||||
|
||||
// request env
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "request", NULL);
|
||||
node = xmlNewChild(node, NULL, BAD_CAST "cgi-data", NULL);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "uwsgi_version");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST __VERSION__);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "compiled_with_version");
|
||||
|
||||
struct utsname uuts;
|
||||
#ifdef __sun__
|
||||
if (uname(&uuts) < 0) {
|
||||
#else
|
||||
if (uname(&uuts)) {
|
||||
#endif
|
||||
uwsgi_error("uname()");
|
||||
}
|
||||
else {
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.sysname);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_sysname");
|
||||
|
||||
char *os_version = uwsgi_concat3(uuts.release, "-", uuts.version);
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST os_version);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_version");
|
||||
free(os_version);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.machine);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "machine");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.nodename);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "nodename");
|
||||
|
||||
}
|
||||
// end request env
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
|
||||
if (uacc->env) {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST uacc->env);
|
||||
}
|
||||
else {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
|
||||
}
|
||||
|
||||
errnode = xmlNewChild(notice_node, NULL, BAD_CAST "error", NULL);
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "class", BAD_CAST "RuntimeError");
|
||||
node = xmlNewChild(errnode, NULL, BAD_CAST "backtrace", NULL);
|
||||
|
||||
char *p = strtok(ut->buf, "\n");
|
||||
int i = 0;
|
||||
char *ctx = NULL;
|
||||
char *text = uwsgi_str(ut->buf);
|
||||
char *p = strtok_r(text, "\n", &ctx);
|
||||
while (p) {
|
||||
// skip log messages
|
||||
if (!uwsgi_startswith(p, "***", 3))
|
||||
goto next;
|
||||
i++;
|
||||
// skip last 2 backtrace lines, real bt starts after them
|
||||
if (i <= 2) {
|
||||
goto next;
|
||||
}
|
||||
// backtrace line looks like this: uwsgi(simple_loop_run+0xc5) [0x451555]
|
||||
// we take binary/lib as filename
|
||||
// and extract method name from remaining string
|
||||
char *n = strchr(p, '(');
|
||||
if (n) {
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
|
||||
*n = 0;
|
||||
|
||||
char *pls = strchr(n+1, '+');
|
||||
@@ -144,8 +161,15 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
*pls = 0;
|
||||
}
|
||||
|
||||
if (i == 3) {
|
||||
free(msg);
|
||||
if (!strcmp("uwsgi_backtrace", n+1) || !strcmp("what_i_am_doing", n+1)) {
|
||||
goto next;
|
||||
}
|
||||
else if (!strcmp("uwsgi_fpe", n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI FPE at ", n+1, " in ", p);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!msg) {
|
||||
if (strlen(n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI segfault at ", n+1, " in ", p);
|
||||
}
|
||||
@@ -155,6 +179,12 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
}
|
||||
}
|
||||
|
||||
// skip empty lines
|
||||
if (!p)
|
||||
goto next;
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
|
||||
|
||||
if ((n+1)[0] == ')') {
|
||||
xmlNewProp(line_node, BAD_CAST "method", BAD_CAST "()");
|
||||
}
|
||||
@@ -164,28 +194,23 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
|
||||
xmlNewProp(line_node, BAD_CAST "file", BAD_CAST p);
|
||||
|
||||
xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
|
||||
//xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
|
||||
}
|
||||
next:
|
||||
p = strtok(NULL, "\n");
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
}
|
||||
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "message", BAD_CAST msg);
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
|
||||
|
||||
xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
|
||||
free(ut->buf);
|
||||
free(msg);
|
||||
ut->buf = (char *) xmlbuff;
|
||||
ut->len = strlen(ut->buf);
|
||||
free(text);
|
||||
|
||||
return (char *) xmlbuff;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +224,7 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_airbrake_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
@@ -218,7 +243,8 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
@@ -226,19 +252,20 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
|
||||
uwsgi_format_airbrake_backtrace(ut, uacc->apikey);
|
||||
char *notice = uwsgi_format_airbrake_backtrace(ut);
|
||||
|
||||
curl_slist_append(expect, "Accept: */*");
|
||||
curl_slist_append(expect, "Content-Type: text/xml; charset=utf-8");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ut->buf);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, ut->len);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notice);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(notice));
|
||||
|
||||
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));
|
||||
}
|
||||
free(notice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -168,7 +168,8 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
|
||||
environment was not blessed by the Go community.
|
||||
|
||||
Instead of completely dropping support for Go, we studied how the gccgo project works and we
|
||||
decided it was a better approach for uWSGI.
|
||||
|
||||
This new plugin works by initializing a new "go runtime" after each fork().
|
||||
|
||||
The runtime calls the Go main function (developed by the user), and pass the whole
|
||||
uWSGI control to it.
|
||||
|
||||
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
|
||||
manages mules, spoolers and workers)
|
||||
|
||||
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
|
||||
from your apps are native goroutines)
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin gccgo_plugin;
|
||||
|
||||
struct uwsgi_gccgo{
|
||||
struct uwsgi_string_list *libs;
|
||||
char *args;
|
||||
} ugccgo;
|
||||
|
||||
/*
|
||||
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
*/
|
||||
|
||||
struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
// no_split_stack is the key to avoid crashing !!!
|
||||
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
|
||||
|
||||
void runtime_check(void);
|
||||
void runtime_args(int, char **);
|
||||
void runtime_osinit(void);
|
||||
void runtime_schedinit(void);
|
||||
void *__go_go(void *, void *);
|
||||
void runtime_main(void);
|
||||
void runtime_mstart(void *);
|
||||
|
||||
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
|
||||
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
|
||||
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
|
||||
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
|
||||
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
|
||||
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
|
||||
|
||||
static void mainstart(void *arg __attribute__((unused))) {
|
||||
runtime_main();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) __asm__ ("main.main");
|
||||
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
|
||||
|
||||
void (*uwsgigo_hook_init)(void);
|
||||
void (*uwsgigo_hook_main)(void);
|
||||
|
||||
void uwsgigo_main_init(void) {
|
||||
uwsgigo_hook_init();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) {
|
||||
uwsgigo_hook_main();
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_request_body_read(struct wsgi_request *wsgi_req, char *p, uint64_t len) {
|
||||
ssize_t rlen = 0;
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, len, &rlen);
|
||||
if (buf == uwsgi.empty) {
|
||||
return 0;
|
||||
}
|
||||
else if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, buf, rlen);
|
||||
return (int) rlen;
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *handler) {
|
||||
return uwsgi_register_signal(signum, receiver, handler, gccgo_plugin.modifier1);
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_initialize() {
|
||||
struct uwsgi_string_list *usl = ugccgo.libs;
|
||||
while(usl) {
|
||||
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!handle) {
|
||||
uwsgi_log("unable to open go shared library: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(handle, "main.main");
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (!uwsgigo_hook_init || !uwsgigo_hook_main) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go runtime initialization
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
argc++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
free(argv_list);
|
||||
}
|
||||
runtime_check();
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
int n = 0;
|
||||
while(p) {
|
||||
argv[n] = p;
|
||||
n++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
runtime_args(argc, argv);
|
||||
}
|
||||
else {
|
||||
char *argv[2] = {0,0};
|
||||
runtime_args(0, argv);
|
||||
}
|
||||
runtime_osinit();
|
||||
runtime_schedinit();
|
||||
__go_go(mainstart, NULL);
|
||||
runtime_mstart(runtime_m());
|
||||
// never here
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->async_environ = uwsgigo_env(wsgi_req);
|
||||
int i;
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
uwsgigo_env_add(wsgi_req->async_environ, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
|
||||
i++;
|
||||
}
|
||||
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
|
||||
uwsgigo_signal_handler(handler, signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin gccgo_plugin = {
|
||||
.name = "gccgo",
|
||||
.modifier1 = 11,
|
||||
.options = uwsgi_gccgo_options,
|
||||
//.on_load = uwsgi_gccgo_on_load,
|
||||
.request = uwsgi_gccgo_request,
|
||||
.after_request = uwsgi_gccgo_after_request,
|
||||
.post_fork = uwsgi_gccgo_initialize,
|
||||
.signal_handler = uwsgi_gccgo_signal_handler,
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
package uwsgi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
//extern uwsgi_takeover
|
||||
func uwsgi_takeover()
|
||||
//extern uwsgi_response_write_body_do
|
||||
func uwsgi_response_write_body_do(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_response_prepare_headers_int
|
||||
func uwsgi_response_prepare_headers_int(*interface{}, int) int
|
||||
//extern uwsgi_response_add_header
|
||||
func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
|
||||
//extern uwsgi_gccgo_helper_request_body_read
|
||||
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_gccgo_helper_register_signal
|
||||
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
|
||||
|
||||
var uwsgi_signals_gc [256]func(uint8)
|
||||
|
||||
func Env(wsgi_req *interface{}) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
return &env
|
||||
}
|
||||
|
||||
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
|
||||
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
r *http.Request
|
||||
wsgi_req *interface{}
|
||||
headers http.Header
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
uwsgi_response_write_body_do(w.wsgi_req, &p[0], uint64(len(p)))
|
||||
return len(p), err
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) WriteHeader(status int) {
|
||||
uwsgi_response_prepare_headers_int(w.wsgi_req, status )
|
||||
if w.headers.Get("Content-Type") == "" {
|
||||
w.headers.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
for k := range w.headers {
|
||||
for _, v := range w.headers[k] {
|
||||
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
|
||||
v = strings.TrimSpace(v)
|
||||
kb := []byte(k)
|
||||
vb := []byte(v)
|
||||
uwsgi_response_add_header(w.wsgi_req, &kb[0], uint16(len(k)), &vb[0], uint16(len(v)))
|
||||
}
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Header() http.Header {
|
||||
return w.headers
|
||||
}
|
||||
|
||||
|
||||
type BodyReader struct {
|
||||
wsgi_req *interface{}
|
||||
}
|
||||
|
||||
// there is no close in request body
|
||||
func (br *BodyReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *BodyReader) Read(p []byte) (n int, err error) {
|
||||
var rlen int = uwsgi_request_body_read(br.wsgi_req, &p[0], uint64(len(p)))
|
||||
if (rlen == 0) {
|
||||
err = io.EOF;
|
||||
return 0, err
|
||||
} else if (rlen == -1) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
return 0, err
|
||||
}
|
||||
return rlen, err
|
||||
}
|
||||
|
||||
func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
|
||||
httpReq, err := cgi.RequestFromMap(*env)
|
||||
if err == nil {
|
||||
httpReq.Body = &BodyReader{wsgi_req}
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
}
|
||||
|
||||
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
var b []byte = []byte(receiver)
|
||||
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
|
||||
return false
|
||||
}
|
||||
uwsgi_signals_gc[signum] = handler
|
||||
return true
|
||||
}
|
||||
|
||||
func SignalHandler(handler func(uint8), signum uint8) {
|
||||
handler(signum)
|
||||
}
|
||||
|
||||
func Run() {
|
||||
uwsgi_takeover()
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import "uwsgi"
|
||||
import "net/http"
|
||||
import "fmt"
|
||||
import "io/ioutil"
|
||||
import "os"
|
||||
|
||||
|
||||
func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -24,6 +25,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(os.Args)
|
||||
http.HandleFunc("/view/", viewHandler)
|
||||
http.HandleFunc("/post/", postHandler)
|
||||
uwsgi.Run()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
[uwsgi]
|
||||
plugins = geoip, router_cache
|
||||
http-socket = :9090
|
||||
|
||||
; 8 bytes blocksize is the right thing to do
|
||||
cache2 = name=limiter,items=1000,blocksize=8
|
||||
; allows expiring items
|
||||
master = true
|
||||
|
||||
; get the cache value for the current ip (if any)
|
||||
route-run = cachevar:key=${REMOTE_ADDR},as_num=1,var=LIMIT
|
||||
; block the peer if it did more than 10 404 requests in the last 30 seconds
|
||||
route-if = >:${LIMIT};10 goto:blockit
|
||||
; end of routing
|
||||
route-run = last:
|
||||
|
||||
|
||||
module = werkzeug.testapp:test_app
|
||||
threads = 10
|
||||
|
||||
; track the user if a 404 is returned
|
||||
final-route-if = equal:${uwsgi[status]};404 goto:trackit
|
||||
; end of final routing
|
||||
final-route-run = last:
|
||||
|
||||
final-route-label = trackit
|
||||
; increase the value in the 'limiter' cache
|
||||
final-route-run = cacheinc:key=${REMOTE_ADDR},expires=30
|
||||
; increase the value if the connection is from italy !!!
|
||||
final-route-if = equal:${geoip[country_name]};Italy cacheinc:key=${REMOTE_ADDR},expires=30
|
||||
|
||||
; block the client
|
||||
route-label = blockit
|
||||
route-run = log:STOP YOU BASTARD !!!
|
||||
route-run = break:503
|
||||
+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 = '2013-05-08'
|
||||
s.date = '2013-05-11'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -1425,6 +1425,7 @@ struct wsgi_request {
|
||||
|
||||
// avoid routing loops
|
||||
int is_routing;
|
||||
int is_final_routing;
|
||||
int routes_applied;
|
||||
// internal routing vm program counter
|
||||
uint32_t route_pc;
|
||||
@@ -2113,6 +2114,7 @@ struct uwsgi_server {
|
||||
#ifdef UWSGI_ROUTING
|
||||
struct uwsgi_router *routers;
|
||||
struct uwsgi_route *routes;
|
||||
struct uwsgi_route *final_routes;
|
||||
struct uwsgi_route_condition *route_conditions;
|
||||
struct uwsgi_route_var *route_vars;
|
||||
#endif
|
||||
@@ -3327,13 +3329,14 @@ char *uwsgi_tmpname(char *, char *);
|
||||
struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, char *));
|
||||
void uwsgi_opt_add_route(char *, char *, void *);
|
||||
int uwsgi_apply_routes(struct wsgi_request *);
|
||||
int uwsgi_apply_routes_do(struct wsgi_request *, char *, uint16_t);
|
||||
void uwsgi_apply_final_routes(struct wsgi_request *);
|
||||
int uwsgi_apply_routes_do(struct uwsgi_route *, struct wsgi_request *, char *, uint16_t);
|
||||
void uwsgi_register_embedded_routers(void);
|
||||
void uwsgi_routing_dump();
|
||||
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *, struct uwsgi_route *, char *, uint16_t, char *, size_t);
|
||||
int uwsgi_route_api_func(struct wsgi_request *, char *, char *);
|
||||
struct uwsgi_route_condition *uwsgi_register_route_condition(char *, int (*) (struct wsgi_request *, struct uwsgi_route *));
|
||||
void uwsgi_fixup_routes(void);
|
||||
void uwsgi_fixup_routes(struct uwsgi_route *);
|
||||
#endif
|
||||
|
||||
void uwsgi_reload(char **);
|
||||
@@ -3993,6 +3996,12 @@ void uwsgi_add_safe_fd(int);
|
||||
void uwsgi_ipcsem_clear(void);
|
||||
char *uwsgi_str_to_hex(char *, size_t);
|
||||
|
||||
// this 3 functions have been added 1.9.10 to allow plugins take the control over processes
|
||||
void uwsgi_worker_run(void);
|
||||
void uwsgi_mule_run(void);
|
||||
void uwsgi_spooler_run(void);
|
||||
void uwsgi_takeover(void);
|
||||
|
||||
void uwsgi_check_emperor(void);
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
+8
-6
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.9'
|
||||
uwsgi_version = '1.9.10'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -153,7 +153,7 @@ def spcall3(cmd):
|
||||
def add_o(x):
|
||||
if x == 'uwsgi':
|
||||
x = 'main'
|
||||
elif x.endswith('.a'):
|
||||
elif x.endswith('.a') or x.endswith('.o'):
|
||||
return x
|
||||
x = x + '.o'
|
||||
return x
|
||||
@@ -277,7 +277,7 @@ def build_uwsgi(uc, print_only=False):
|
||||
objfile = file
|
||||
if objfile == 'uwsgi':
|
||||
objfile = 'main'
|
||||
if not objfile.endswith('.a'):
|
||||
if not objfile.endswith('.a') and not objfile.endswith('.o'):
|
||||
compile(' '.join(cflags), last_cflags_ts, objfile + '.o', file + '.c')
|
||||
|
||||
if uc.get('embedded_plugins'):
|
||||
@@ -346,6 +346,8 @@ def build_uwsgi(uc, print_only=False):
|
||||
for cfile in up['GCC_LIST']:
|
||||
if cfile.endswith('.a'):
|
||||
gcc_list.append(cfile)
|
||||
elif cfile.endswith('.o'):
|
||||
gcc_list.append('%s/%s' % (path, cfile))
|
||||
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
|
||||
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
|
||||
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
|
||||
@@ -471,7 +473,7 @@ class uConf(object):
|
||||
self.gcc_list.append('proto/scgi')
|
||||
self.include_path = []
|
||||
|
||||
self.cflags = ['-O2', '-I.', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
|
||||
self.cflags = ['-O2', '-I.', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split() + self.get('cflags','').split()
|
||||
|
||||
report['kernel'] = uwsgi_os
|
||||
|
||||
@@ -568,7 +570,7 @@ class uConf(object):
|
||||
return None
|
||||
return value
|
||||
except:
|
||||
if default:
|
||||
if default is not None:
|
||||
return default
|
||||
return None
|
||||
|
||||
@@ -1122,7 +1124,7 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
for cfile in up['GCC_LIST']:
|
||||
if cfile.endswith('.a'):
|
||||
gcc_list.append(cfile)
|
||||
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
|
||||
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m') and not cfile.endswith('.o'):
|
||||
gcc_list.append(path + '/' + cfile + '.c')
|
||||
else:
|
||||
gcc_list.append(path + '/' + cfile)
|
||||
|
||||
Reference in New Issue
Block a user