Compare commits

...
74 Commits
Author SHA1 Message Date
roberto@oneiric64 0c9b6e98f7 added support for yaml lists under libyaml 2011-12-07 10:21:11 +01:00
roberto@colossus ce33d0be5a support for older rails apps 2011-12-07 09:21:28 +01:00
roberto@oneiric64 4f0fb90bff added failcnt in subscription system 2011-12-06 11:17:26 +01:00
roberto@mrspurr 66eff0107a fixed SEQPACKET usage 2011-12-06 10:50:30 +01:00
roberto@oneoric64 82f83e610f fixed a fd leak on static file serving 2011-12-06 09:29:41 +01:00
roberto@oneiric64 cf7df391ad correctly report load in fastrouter stats 2011-12-04 15:58:38 +01:00
roberto@oneiric64 244c9f8204 allows modifier2 to be subscribed 2011-12-04 15:35:29 +01:00
roberto@oneoric64 26dc19df7d reverted subscription string usage 2011-12-04 15:30:08 +01:00
roberto@oneiric64 7b8bff1a08 fixed a bug in load value 2011-12-04 13:50:18 +01:00
roberto@oneiric64 0b010124ef subscription optimizations 2011-12-04 13:45:18 +01:00
roberto@oneiric64 c7bde15f39 ready for next (last?) -rc 2011-12-04 10:38:53 +01:00
roberto@oneiric64 b941e4f2f0 pep8 setup.py 2011-12-04 07:41:49 +01:00
roberto@oneiric64 536c6e7e29 pep8 uwsgidecorators 2011-12-04 07:39:01 +01:00
roberto@oneiric64 dfe4abec35 added health_check in log_pipe 2011-12-04 07:14:19 +01:00
roberto@oneiric64 693b80d7d3 fixed healthcheck skip 2011-12-03 11:06:30 +01:00
roberto@oneiric64 c9e6475ef4 fixed another leak in master 2011-12-03 08:26:41 +01:00
roberto@oneiric64 b745132ebd improved ksm support 2011-12-02 13:31:17 +01:00
roberto@oneiric64 19686cb19f update the copyright to 2011 in apache module 2011-12-01 14:18:54 +01:00
roberto@oneiric64 e0c0593b5b fixed a memory leak in glob() 2011-12-01 13:45:52 +01:00
roberto@oneiric64 415a8af363 fix compilation with async=false 2011-12-01 05:44:23 +01:00
roberto@oneiric64 d44777b1b4 fixed mod_uwsgi when SCRIPT_NAME = / 2011-11-30 18:47:14 +01:00
roberto@oneiric64 e3ff3037b4 use vector-io in fileserve mode 2011-11-30 18:38:42 +01:00
roberto@oneiric64 7add30fd31 added uWSGIemptyRemoteUser in mod_uwsgi 2011-11-30 15:37:48 +01:00
roberto@fiorenzo 501cd0349b another fastrouter fix/optimization 2011-11-29 20:52:08 +01:00
roberto@oneiric64 7b4e3f6601 better error reporting in fastrouter 2011-11-29 19:34:29 +01:00
roberto@oneiric64 8622c2780c fixed cheap reporting 2011-11-29 16:17:17 +01:00
roberto@oneiric64 13de7b6d5b fixed a loop in subscription system 2011-11-29 13:29:23 +01:00
roberto@fiorenzo 53cb864f9c added death mark in fastrouter stats 2011-11-29 11:50:09 +01:00
roberto@fiorenzo 72f693f02a fixed subscription rr and added --fastrouter-stats 2011-11-29 11:46:50 +01:00
roberto@genesi fb80e32682 fix obsolete kernel check 2011-11-29 10:41:57 +01:00
roberto@oneiric64 1db3426ee1 applied riccardo's fix for sendfile 2011-11-29 07:52:26 +01:00
roberto@oneiric64 a44879e384 improved lazy mode to allows signals 2011-11-29 07:47:19 +01:00
roberto@oneiric64 c0075c817d remove unneeded debug entry 2011-11-28 22:06:08 +01:00
roberto@oneiric64 177dc3322b remove unneded rb_gc_unregister_address 2011-11-28 21:57:35 +01:00
roberto@storm 21ef4fc89b multiline headers rack fixes 2011-11-28 21:36:03 +01:00
roberto@oneiric64 f467643f6f better post_buffering 2011-11-28 14:14:24 +01:00
roberto@oneiric64 3db41e7e05 better usage of fwrite() 2011-11-28 14:04:49 +01:00
roberto@oneiric64 73151729c6 mark route() requests 2011-11-28 13:58:15 +01:00
roberto@longshot 5d9c415028 merge 2011-11-28 13:07:05 +01:00
roberto@longshot b92ed4da4e fixed after_request remapper 2011-11-28 13:06:43 +01:00
roberto@oneiric64 2d1a9a03d2 reduce a potetial race conditions in evil reloads 2011-11-28 11:35:35 +01:00
roberto@longshot 5d6edd2321 force removal of -Winline during plugins building 2011-11-28 10:29:46 +01:00
roberto@oneiric64 365f4ba83f fixed a bug in FIFO reading 2011-11-28 07:17:58 +01:00
roberto@oneiric64 66e30ae293 report config in USR1 management 2011-11-27 21:05:06 +01:00
roberto@oneiric64 728425de19 Added tag 1.0-rc7 for changeset a3ca2e8e27c5 2011-11-26 18:50:41 +01:00
roberto@oneiric64 b0af1f800b fixed a bug in #ifdef for pump/web3 spotted by riccardo 2011-11-26 18:39:44 +01:00
roberto@oneiric64 543271e856 fixed a ksm leak 2011-11-26 13:02:47 +01:00
roberto@oneiric64 a1564a44fa added postgresql probe 2011-11-26 12:44:38 +01:00
roberto@oneiric64 571029cfd3 added probe infrastructure 2011-11-26 11:05:49 +01:00
roberto@oneiric64 579eaa630a refactored daemons and removed uwsgi.attach_daemon function 2011-11-26 09:04:19 +01:00
roberto@oneiric64 9530c8ffe0 applied riccardo's patch [2] 2011-11-26 08:10:29 +01:00
roberto@oneiric64 0d8690091b applied riccardo's patch [1] 2011-11-26 08:04:39 +01:00
roberto@goyle 5b5e3a1ec1 added delta_requests 2011-11-25 15:34:41 +01:00
roberto@centos64 869ae5e3ed allows the building of uWSGI on ancient linux kernel (like CentOS4) 2011-11-24 12:57:08 +01:00
roberto@oneiric64 d6dc8d86f8 added subscription report on startup 2011-11-24 07:42:14 +01:00
roberto@oneiric64 758745be68 closed bug #56 2011-11-24 07:35:32 +01:00
roberto@oneiric64 2adfa56d6a added threading name in python threads object 2011-11-23 17:44:41 +01:00
roberto@oneiric64 a4c728f5df added auto-patching for Rack::BodyProxy.each 2011-11-23 11:45:13 +01:00
roberto@oneiric64 5c06341b7f ready for -rc7 2011-11-23 10:08:49 +01:00
roberto@oneiric64 6f57902a9b another cron fix 2011-11-23 05:37:00 +01:00
roberto@longshot a3e118893d do not build sqlite on unbit 2011-11-22 18:52:12 +01:00
roberto@oneiric64 ff2d3c29d6 fixed a bug in cron management 2011-11-22 17:56:03 +01:00
roberto@oneiric64 59a8df85f2 added --st as a --subscribe/--subscribe-to alias 2011-11-22 11:23:10 +01:00
roberto@oneiric64 e303bd182a report subscribed nodes timeout 2011-11-22 11:15:13 +01:00
roberto@oneiric64 dcef9a497c less verbose build system 2011-11-22 09:46:16 +01:00
roberto@oneiric64 8d4fd66aaf fixed a bug in execvp() during reload on 64 bit 2011-11-22 09:16:34 +01:00
roberto@debian32 471bd23acf added --subscribe-freq and --subscription-tolerance 2011-11-21 20:22:00 +01:00
roberto@debian32 ffcef81dd0 greatly improved subscription system 2011-11-21 16:23:24 +01:00
roberto@debian32 317df5d06b added @(filename) magic var 2011-11-21 13:22:05 +01:00
roberto@debian32 ad7b5efd6f added --logfile-chmod 2011-11-21 10:32:48 +01:00
roberto@deban32 891f770724 added Lukas to CONTRIBUTORS 2011-11-21 09:55:43 +01:00
roberto@debian32.local 0b6d715982 refactored ping and nagios 2011-11-21 09:42:48 +01:00
roberto@debian32 76c2415516 moved cluster-related functions to a dedicated file 2011-11-20 11:36:42 +01:00
roberto@gambit 3260faca17 Added tag 1.0-rc6 for changeset a2b8f25fd17e 2011-11-19 08:40:45 +01:00
50 changed files with 2669 additions and 1325 deletions
+2
View File
@@ -37,3 +37,5 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
+3
View File
@@ -14,3 +14,6 @@ Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
+39 -4
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -73,6 +73,7 @@ typedef struct {
char scheme[9];
int cgi_mode ;
int max_vars;
int empty_remote_user;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -162,6 +163,7 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
c->empty_remote_user = 1;
return c;
}
@@ -177,6 +179,7 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->empty_remote_user = 1;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
@@ -344,7 +347,15 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
//
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
}
else if (c->empty_remote_user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
}
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
@@ -354,7 +365,8 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] != 0) {
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
@@ -621,7 +633,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->cgi_mode = 1 ;
}
@@ -722,6 +734,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
return NULL ;
}
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->empty_remote_user = 1;
}
else {
c->empty_remote_user = 0;
}
return NULL ;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
@@ -730,6 +764,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+1 -1
View File
@@ -3,7 +3,7 @@ xml = true
ini = true
yaml = true
json = true
sqlite3 = true
sqlite3 = false
zeromq = false
snmp = false
sctp = false
+355
View File
@@ -0,0 +1,355 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
#endif
+5 -2
View File
@@ -171,7 +171,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
@@ -512,6 +512,7 @@ reconnect:
uwsgi_error("glob()");
exit(1);
}
globfree(&g);
emperor_absolute_dir = realpath(".", NULL);
}
@@ -647,7 +648,7 @@ reconnect:
}
}
else {
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
@@ -746,6 +747,7 @@ reconnect:
}
}
globfree(&g);
}
}
@@ -847,6 +849,7 @@ void emperor_send_stats(int fd) {
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
+12
View File
@@ -567,6 +567,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifdef OBSOLETE_LINUX_KERNEL
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#else
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
@@ -659,6 +669,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
+15
View File
@@ -1,5 +1,20 @@
#include "../uwsgi.h"
#ifdef OBSOLETE_LINUX_KERNEL
#ifndef __u16
#define __u16 u_int16_t
#endif
#ifndef __u32
#define __u32 u_int32_t
#endif
#ifndef __s32
#define __s32 int32_t
#endif
#ifndef __u8
#define __u8 u_int8_t
#endif
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
+21
View File
@@ -4,7 +4,12 @@
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#ifdef OBSOLETE_LINUX_KERNEL
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
@@ -27,15 +32,27 @@ void uwsgi_lock_init(void *lock) {
}
void uwsgi_rlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock(lock);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_wlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock(lock);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_rwunlock(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock(lock);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
#endif
}
void uwsgi_lock(void *lock) {
@@ -51,6 +68,9 @@ void uwsgi_unlock(void *lock) {
void uwsgi_rwlock_init(void *lock) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_init(lock);
#else
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
@@ -64,6 +84,7 @@ void uwsgi_rwlock_init(void *lock) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
#endif
}
+1 -1
View File
@@ -64,7 +64,7 @@ void log_request(struct wsgi_request *wsgi_req) {
#endif
// mark route() requests
if (wsgi_req->status == -1) {
if (wsgi_req->status == -17) {
via = msg3;
}
+74 -113
View File
@@ -67,56 +67,7 @@ void expire_rb_timeouts(struct rb_root *root) {
}
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len) {
char *ssb;
char subscrbuf[4096];
uint16_t ustrlen;
ssb = subscrbuf;
ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb+=ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb+=ustrlen;
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(uwsgi.sockets->name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, uwsgi.sockets->name, ustrlen);
ssb+=ustrlen;
if (modifier1) {
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = modifier1_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, modifier1, ustrlen);
ssb+=ustrlen;
}
send_udp_message(224, udp_address, subscrbuf, ssb-subscrbuf);
}
void uwsgi_subscribe(char *subscription) {
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
int subfile_size;
int i;
@@ -149,7 +100,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd);
modifier1 = NULL;
modifier1_len = 0;
}
@@ -167,7 +118,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd);
modifier1 = NULL;
modifier1_len = 0;
lines[i] = '\n';
@@ -191,7 +142,7 @@ void uwsgi_subscribe(char *subscription) {
modifier1_len = strlen(modifier1);
}
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), modifier1, modifier1_len);
uwsgi_send_subscription(udp_address, subscription_key+1, strlen(subscription_key+1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd);
if (modifier1)
modifier1[-1] = ',';
}
@@ -212,6 +163,8 @@ void get_linux_tcp_info(int fd) {
return;
}
uwsgi.shared->load = uwsgi.shared->ti.tcpi_unacked;
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->ti.tcpi_unacked;
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
if ((int)uwsgi.shared->ti.tcpi_unacked >= uwsgi.vassal_sos_backlog) {
@@ -233,35 +186,6 @@ void get_linux_tcp_info(int fd) {
}
#endif
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
int master_loop(char **argv, char **environ) {
@@ -285,7 +209,7 @@ int master_loop(char **argv, char **environ) {
uint8_t uwsgi_signal;
time_t last_request_timecheck = 0;
time_t last_request_timecheck = 0, now = 0;
uint64_t last_request_count = 0;
#ifdef UWSGI_UDP
@@ -532,10 +456,21 @@ int master_loop(char **argv, char **environ) {
}
}
// spawn daemons
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (!ud->registered) {
spawn_daemon(ud);
ud->registered = 1;
}
ud = ud->next;
}
// first subscription
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_subscribe(subscriptions->value);
uwsgi_subscribe(subscriptions->value, 0);
subscriptions = subscriptions->next;
}
@@ -712,7 +647,7 @@ healthy:
if ((uwsgi.cheap || ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
for(i=0;i<(uwsgi.gateways_cnt+uwsgi.daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -721,7 +656,7 @@ healthy:
}
if ( (uwsgi.cheap || ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt+uwsgi.mules_cnt);i++) {
for(i=0;i<(uwsgi.gateways_cnt+uwsgi.daemons_cnt+uwsgi.mules_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -789,7 +724,7 @@ healthy:
if (!uwsgi.cheap) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || ushared->daemons_cnt > 0) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
master_has_children = 1;
}
#ifdef UWSGI_SPOOLER
@@ -840,16 +775,6 @@ healthy:
}
}
// add unregistered daemons
// locking is not needed as daemons can only increase (for now)
for(i=0;i<ushared->daemons_cnt;i++) {
if (!ushared->daemons[i].registered) {
uwsgi_log("spawning daemon %s\n", ushared->daemons[i].command);
spawn_daemon(&ushared->daemons[i]);
ushared->daemons[i].registered = 1;
}
}
// add unregistered timers
// locking is not needed as timers can only increase
@@ -902,6 +827,22 @@ healthy:
uwsgi_manage_command_cron(time(NULL));
}
// check for probes
if (ushared->probes_cnt > 0) {
uwsgi_lock(uwsgi.probe_table_lock);
for(i=0;i<ushared->probes_cnt;i++) {
if (interesting_fd == -1) {
// increment cycles
ushared->probes[i].cycles++;
}
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
uwsgi_route_signal(ushared->probes[i].sig);
}
}
uwsgi_unlock(uwsgi.probe_table_lock);
}
if (rlen > 0) {
if (uwsgi.log_master) {
@@ -929,12 +870,14 @@ healthy:
}
// TODO allow uwsgi.logger = func
}
goto health_cycle;
}
}
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
uwsgi_send_stats(uwsgi.stats_fd);
goto health_cycle;
}
}
@@ -985,6 +928,7 @@ healthy:
close(zerg_client);
free(zerg_msg_control);
goto health_cycle;
}
}
@@ -1011,6 +955,7 @@ healthy:
sleep(2);
exit(1);
}
goto health_cycle;
}
}
@@ -1030,6 +975,7 @@ healthy:
}
uwsgi_sock = uwsgi_sock->next;
}
// here is better to continue instead going to health_cycle
if (found) continue;
}
#ifdef UWSGI_SNMP
@@ -1043,7 +989,7 @@ healthy:
else if (rlen > 0) {
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
}
continue;
goto health_cycle;
}
#endif
@@ -1090,14 +1036,14 @@ healthy:
}
}
continue;
goto health_cycle;
}
#ifdef UWSGI_MULTICAST
if (interesting_fd == uwsgi.cluster_fd) {
if (uwsgi_get_dgram(uwsgi.cluster_fd, uwsgi.wsgi_requests[0])) {
continue;
goto health_cycle;
}
switch(uwsgi.wsgi_requests[0]->uh.modifier1) {
@@ -1137,7 +1083,7 @@ healthy:
uwsgi_log_verbose("[uWSGI cluster %s] new node available: %.*s\n", uwsgi.cluster, uwsgi.wsgi_requests[0]->uh.pktsize, uwsgi.wsgi_requests[0]->buffer);
break;
}
continue;
goto health_cycle;
}
#endif
@@ -1159,10 +1105,11 @@ healthy:
}
uwsgi_unlock(uwsgi.fmon_table_lock);
if (next_iteration) continue;
if (next_iteration) goto health_cycle;;
next_iteration = 0;
uwsgi_lock(uwsgi.timer_table_lock);
for(i=0;i<ushared->timers_cnt;i++) {
if (ushared->timers[i].registered) {
if (interesting_fd == ushared->timers[i].fd) {
@@ -1173,7 +1120,8 @@ healthy:
}
}
}
if (next_iteration) continue;
uwsgi_unlock(uwsgi.timer_table_lock);
if (next_iteration) goto health_cycle;;
// check for worker signal
@@ -1193,6 +1141,7 @@ healthy:
close(interesting_fd);
//uwsgi.workers[i].pipe[0] = -1;
}
goto health_cycle;
}
#ifdef UWSGI_SPOOLER
@@ -1213,6 +1162,7 @@ healthy:
uwsgi_log_verbose("lost connection with the spooler\n");
close(interesting_fd);
}
goto health_cycle;
}
}
#endif
@@ -1220,7 +1170,12 @@ healthy:
}
uwsgi.current_time = time(NULL);
health_cycle:
now = time(NULL);
if (now - uwsgi.current_time < 1) {
continue;
}
uwsgi.current_time = now;
// checking logsize
if (uwsgi.logfile) {
if (uwsgi.log_master) {
@@ -1266,6 +1221,7 @@ healthy:
}
// this will be incremented at (more or less) regular intervals
uwsgi.master_cycles++;
// recalculate requests counter on race conditions risky configurations
@@ -1303,6 +1259,7 @@ healthy:
continue;
}
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0) continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
@@ -1449,11 +1406,11 @@ healthy:
uwsgi_cluster_add_me();
}
// resubscribe every 10 cycles
if (uwsgi.subscriptions && ((uwsgi.master_cycles % 10) == 0 || uwsgi.master_cycles == 1)) {
// resubscribe every 10 cycles by default
if (uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) {
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while(subscriptions) {
uwsgi_subscribe(subscriptions->value);
uwsgi_subscribe(subscriptions->value, 0);
subscriptions = subscriptions->next;
}
}
@@ -1541,12 +1498,14 @@ healthy:
/* reload the daemons */
// TODO reload_gateway(diedpid);
pid_found = 0;
for(i=0;i<uwsgi.shared->daemons_cnt;i++) {
if (uwsgi.shared->daemons[i].pid == diedpid) {
spawn_daemon(&uwsgi.shared->daemons[i]);
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid == diedpid) {
spawn_daemon(ud);
pid_found = 1;
break;
}
ud = ud->next;
}
if (pid_found) continue;
@@ -1589,11 +1548,13 @@ healthy:
}
}
for(i=0;i<uwsgi.shared->daemons_cnt;i++) {
if (uwsgi.shared->daemons[i].pid == diedpid) {
uwsgi_log("daemon %d (pid: %d) annihilated\n", i+1, (int) diedpid);
struct uwsgi_daemon *ud = uwsgi.daemons;
while(ud) {
if (ud->pid == diedpid) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
goto next;
}
ud = ud->next;
}
if (WIFEXITED(waitpid_status)) {
+38 -40
View File
@@ -102,8 +102,13 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
@@ -179,32 +184,26 @@ void uwsgi_manage_signal_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
int run_task = 0;
// mday and wday are ORed
if (ucron->day == -1 && ucron->week == -1) {
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->day == -1) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
else if (ucron->week == -1) {
ucron->week = uwsgi_cron_delta->tm_wday;
if (ucron->day != -1 && ucron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (ucron->day == uwsgi_cron_delta->tm_mday) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
ucron->day = uwsgi_cron_delta->tm_mday;
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
@@ -252,31 +251,26 @@ void uwsgi_manage_command_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
// mday and wday are ORed
if (current_cron->day == -1 && current_cron->week == -1) {
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->day == -1) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
else if (current_cron->week == -1) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else {
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day != -1 && current_cron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
@@ -326,6 +320,9 @@ void uwsgi_send_stats(int fd) {
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
@@ -341,6 +338,7 @@ void uwsgi_send_stats(int fd) {
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i+1].delta_requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
+3 -2
View File
@@ -34,6 +34,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint16_t argvs[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
@@ -52,9 +53,9 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
}
}
}
+50 -6
View File
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
char *cgi_docroot;
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 100)
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
struct option uwsgi_cgi_options[] = {
@@ -32,6 +32,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int waitpid_status;
char *argv[2];
char full_path[PATH_MAX];
int cgi_pipe[2];
ssize_t len;
/* Standard CGI request */
if (!wsgi_req->uh.pktsize) {
@@ -47,6 +49,26 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
// check for file availability (and 'runnability')
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
if (access(full_path, R_OK)) {
wsgi_req->status = 404;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 404 Not Found\r\n\r\n", 26);
return UWSGI_OK;
}
if (access(full_path, X_OK)) {
wsgi_req->status = 500;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 500 Internal Server Error\r\n\r\n", 26);
return UWSGI_OK;
}
if (pipe(cgi_pipe)) {
uwsgi_error("pipe()");
return UWSGI_OK;
}
cgi_pid = fork();
if (cgi_pid < 0) {
@@ -59,6 +81,29 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
close(wsgi_req->poll.fd);
wsgi_req->fd_closed = 1;
// wait for data
char startbuf[8];
char *ptr = startbuf;
int remains = 8;
while(remains > 0) {
uwsgi_log("waiting for fd\n");
int ret = uwsgi_waitfd(cgi_pipe[0], 10);
uwsgi_log("data available\n");
if (ret > 0) {
len = read(cgi_pipe[0], ptr, remains);
if (len > 0) {
ptr+=len;
remains -= len;
}
}
}
uwsgi_log("STARTBUF %.*s\n", 8, startbuf);
if (!memcmp(startbuf, "Status: ", 8)) {
// wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 "
}
// now wait for fd
if (waitpid(cgi_pid, &waitpid_status ,0) > 0) {
uwsgi_log("CGI FINISHED\n");
@@ -69,18 +114,19 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (i != wsgi_req->poll.fd && i != 2) {
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[0] && i != cgi_pipe[1]) {
close(i);
}
}
// now map wsgi_req->poll.fd to 0 && 1
// now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1
if (wsgi_req->poll.fd != 0) {
dup2(wsgi_req->poll.fd, 0);
close(wsgi_req->poll.fd);
}
dup2(0,1);
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
dup2(cgi_pipe[1],1);
// fill cgi env
@@ -92,8 +138,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
i++;
}
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
argv[0] = full_path;
argv[1] = NULL;
+5 -2
View File
@@ -94,7 +94,8 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
char *call;
char buffer[0xffff];
char *argv[0xff] ;
char *argv[256] ;
uint16_t argvs[256] ;
int argc = 0;
uint16_t ret;
ei_x_buff xr;
@@ -215,14 +216,16 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
else if (etype == ERL_STRING_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
ret = uwsgi_rpc(call, argc, argv, buffer);
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
#ifdef UWSGI_DEBUG
uwsgi_log("buffer: %.*s\n", ret, buffer);
+191 -59
View File
@@ -20,6 +20,8 @@
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define LONG_ARGS_FASTROUTER_TOLERANCE 150009
#define LONG_ARGS_FASTROUTER_STATS 150010
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -32,6 +34,8 @@
#define del_check_timeout(x) rb_erase(&x->rbt, ufr.timeouts);
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
void fastrouter_send_stats(int);
struct uwsgi_fastrouter_socket {
char *name;
int fd;
@@ -55,6 +59,8 @@ struct uwsgi_fastrouter {
char *base;
int base_len;
char *stats_server;
char *subscription_server;
struct uwsgi_subscribe_slot *subscriptions;
int subscription_regexp;
@@ -71,8 +77,21 @@ struct uwsgi_fastrouter {
int cheap;
int i_am_cheap;
int tolerance;
} ufr;
static void fastrouter_go_cheap(void) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
@@ -112,6 +131,9 @@ struct option fastrouter_options[] = {
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
{"fastrouter-subscription-use-regexp", no_argument, &ufr.subscription_regexp, 1},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{"fastrouter-stats", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{"fastrouter-stats-server", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{"fastrouter-ss", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{0, 0, 0, 0},
};
@@ -129,10 +151,15 @@ void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
usr->address = val;
usr->address_len = vallen;
}
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
usr->modifier1 = uwsgi_str_num(val, vallen);
}
else if (!uwsgi_strncmp("cores", 5, key, keylen)) {
usr->cores = uwsgi_str_num(val, vallen);
}
else if (!uwsgi_strncmp("load", 4, key, keylen)) {
usr->load = uwsgi_str_num(val, vallen);
}
}
struct fastrouter_session {
@@ -165,41 +192,29 @@ struct fastrouter_session {
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
// check timeout expired
if (fr_session == NULL) {
if (ufr.subscription_server) {
//time_t current_time = time(NULL);
uwsgi_log("checking for node health\n");
struct uwsgi_subscribe_slot *slot = ufr.subscriptions;
while(slot) {
struct uwsgi_subscribe_node *node = slot->nodes;
while(node) {
uwsgi_log("%.*s (hits: %llu) %.*s\n", slot->keylen, slot->key, slot->hits, node->len, node->name);
node = node->next;
}
slot = slot->next;
}
del_check_timeout(ufr.subscriptions_check);
ufr.subscriptions_check = add_check_timeout(10);
}
return;
}
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
if (ufr.subscriptions && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
if (fr_session->un && fr_session->un->len > 0) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
if (ufr.subscriptions && fr_session->un && fr_session->un->len > 0) {
// decrease reference count
#ifdef UWSGI_DEBUG
uwsgi_log("[1] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
#endif
fr_session->un->reference--;
#ifdef UWSGI_DEBUG
uwsgi_log("[2] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
#endif
if (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING) {
if (fr_session->un->death_mark == 0)
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->failcnt++;
fr_session->un->death_mark = 1;
// check if i can remove the node
if (fr_session->un->reference == 0) {
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
}
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
fastrouter_go_cheap();
}
}
@@ -307,6 +322,7 @@ void fastrouter_loop() {
socklen_t solen = sizeof(int);
int ufr_subserver = -1;
int ufr_stats_server = -1;
for(i=0;i<2048;i++) {
fr_table[i] = NULL;
@@ -363,6 +379,23 @@ void fastrouter_loop() {
//ufr.subscriptions_check = add_check_timeout(10);
}
if (ufr.stats_server) {
char *tcp_port = strchr(ufr.stats_server, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
ufr_stats_server = bind_to_tcp(ufr.stats_server, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
ufr_stats_server = bind_to_unix(ufr.stats_server, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(ufr.queue, ufr_stats_server);
uwsgi_log("*** FastRouter stats server enabled on %s fd: %d ***\n", ufr.stats_server, ufr_stats_server);
}
if (ufr.pattern) {
init_magic_table(magic_table);
}
@@ -429,7 +462,10 @@ void fastrouter_loop() {
continue;
}
if (interesting_fd == ufr_subserver) {
if (interesting_fd == ufr_stats_server) {
fastrouter_send_stats(ufr_stats_server);
}
else if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ufr.queue, ufr_subserver);
@@ -437,15 +473,35 @@ void fastrouter_loop() {
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
if (uwsgi_add_subscribe_node(&ufr.subscriptions, &usr, ufr.subscription_regexp) && ufr.i_am_cheap) {
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 0;
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(&ufr.subscriptions, &usr, ufr.subscription_regexp) && ufr.i_am_cheap) {
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 0;
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(&ufr.subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ufr.subscription_regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->failcnt++;
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(&ufr.subscriptions, node);
}
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
fastrouter_go_cheap();
}
}
}
}
}
else {
@@ -466,7 +522,8 @@ void fastrouter_loop() {
case FASTROUTER_STATUS_RECV_HDR:
len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
if (len < 0)
uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
@@ -524,6 +581,9 @@ void fastrouter_loop() {
fr_session->instance_address_len = fr_session->un->len;
fr_session->modifier1 = fr_session->un->modifier1;
}
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
fastrouter_go_cheap();
}
}
else if (ufr.base) {
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
@@ -558,23 +618,6 @@ void fastrouter_loop() {
if (tmp_socket_name) free(tmp_socket_name);
if (fr_session->instance_fd < 0) {
/*
if (ufr.subscription_server) {
if (fr_session->un && fr_session->un->len > 0) {
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
ufr_sock = ufr_sock->next;
}
ufr.i_am_cheap = 1;
}
}
}
*/
fr_session->instance_failed = 1;
close_session(fr_table, fr_session);
break;
@@ -757,6 +800,9 @@ int fastrouter_opt(int i, char *optarg) {
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
ufr.subscription_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_STATS:
ufr.stats_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_EVENTS:
ufr.nevents = atoi(optarg);
return 1;
@@ -807,3 +853,89 @@ struct uwsgi_plugin fastrouter_plugin = {
.init = fastrouter_init,
};
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void fastrouter_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
fprintf(output, "\"fastrouter\": [");
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->next) {
stats_send("\"%s\",", uwsgi_sock->name);
}
else {
stats_send("\"%s\"", uwsgi_sock->name);
}
uwsgi_sock = uwsgi_sock->next;
}
fprintf(output, "],\n");
if (ufr.subscription_server) {
fprintf(output, "\"subscriptions\": [\n");
struct uwsgi_subscribe_slot *s_slot = ufr.subscriptions;
while(s_slot) {
fprintf(output, "\t{ \"key\": \"%.*s\",\n", s_slot->keylen, s_slot->key);
fprintf(output, "\t\t\"hits\": %llu,\n", (unsigned long long) s_slot->hits);
fprintf(output, "\t\t\"nodes\": [\n");
struct uwsgi_subscribe_node *s_node = s_slot->nodes;
while(s_node) {
fprintf(output, "\t\t\t{\"name\": \"%.*s\", \"modifier1\": %d, \"modifier2\": %d, \"last_check\": %llu, \"requests\": %llu, \"tx\": %llu, \"cores\": %llu, \"load\": %llu, \"ref\": %llu, \"failcnt\": %llu, \"death_mark\": %d}", s_node->len, s_node->name, s_node->modifier1, s_node->modifier2,
(unsigned long long) s_node->last_check, (unsigned long long) s_node->requests, (unsigned long long) s_node->transferred,
(unsigned long long) s_node->cores, (unsigned long long) s_node->load, (unsigned long long) s_node->reference,
(unsigned long long) s_node->failcnt, s_node->death_mark);
if (s_node->next) {
fprintf(output, ",\n");
}
else {
fprintf(output, "\n");
}
s_node = s_node->next;
}
fprintf(output, "\t\t]\n");
if (s_slot->next) {
fprintf(output, "\t},\n");
}
else {
fprintf(output, "\t}\n");
}
s_slot = s_slot->next;
// check for loopy optimization
if (s_slot == ufr.subscriptions) break;
}
fprintf(output, "],\n");
}
fprintf(output,"\"cheap\": %d\n", ufr.i_am_cheap);
fprintf(output,"}\n");
fclose(output);
}
+2 -2
View File
@@ -682,7 +682,7 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
}
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint8_t i;
const char *sv;
@@ -698,7 +698,7 @@ uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
for(i=0;i<argc;i++) {
lua_pushstring(L, argv[i]);
lua_pushlstring(L, argv[i], argvs[i]);
}
if (lua_pcall(L, argc, 1, 0) != 0) {
+18 -19
View File
@@ -15,49 +15,48 @@ struct option nagios_options[] = {
int nagios() {
char *tcp_port;
struct wsgi_request nagios_req;
// connect and send
struct uwsgi_header uh;
char *buf = NULL;
if (!use_nagios) {
return 1;
}
if (!uwsgi.sockets) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port = strchr(uwsgi.sockets->name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
nagios_req.uh.pktsize = 0;
nagios_req.uh.modifier2 = 0;
if (write(fd, &nagios_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_req.poll.fd = fd;
nagios_req.poll.events = POLLIN;
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buf);
if (ret == -2) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else if (ret == -1) {
fprintf(stdout, "UWSGI CRITICAL: error reading response\n");
exit(2);
}
else {
if (nagios_req.uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
if (uh.pktsize > 0 && buf) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uh.pktsize, buf);
exit(1);
}
else {
+12 -14
View File
@@ -15,8 +15,8 @@ struct option uwsgi_ping_options[] = {
static void ping() {
struct wsgi_request ping_req;
char *buf = uwsgi_malloc(uwsgi.buffer_size);
struct uwsgi_header uh;
char *buf = NULL;
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
@@ -28,25 +28,22 @@ static void ping() {
exit(1);
}
memset(&ping_req, 0, sizeof(struct wsgi_request));
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
ping_req.uh.pktsize = 0;
ping_req.uh.modifier2 = 0;
if (write(fd, &ping_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
ping_req.poll.fd = fd;
ping_req.poll.events = POLLIN;
ping_req.buffer = buf;
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
int ret = uwsgi_read_response(fd, &uh, uping.ping_timeout, &buf);
if (ret < 0) {
exit(1);
}
else {
if (ping_req.uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
if (uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, uh.pktsize, buf);
exit(2);
}
else {
@@ -98,6 +95,7 @@ int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_initial_output = 1;
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
+90
View File
@@ -0,0 +1,90 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->fd = uwsgi_connect(up->args, -1, 1);
if (up->fd != -1) {
// status = CONNECTING
up->state = 1;
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// uselsess here (we have only one state), only to show a good practice
// check the state
if (up->state == 1) {
if (uwsgi_is_bad_connection(up->fd)) {
// signal the bad connection (if needed)
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
// this is a good connection
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
}
// default action
return 0;
}
int probeconnect_init() {
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
return 0;
}
struct uwsgi_plugin probeconnect_plugin = {
.init = probeconnect_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='probeconnect'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['connectprobe']
+132
View File
@@ -0,0 +1,132 @@
#include "../../uwsgi.h"
#include <libpq-fe.h>
extern struct uwsgi_server uwsgi;
int pg_prober_callback(int, struct uwsgi_signal_probe *);
int probepg_init(void);
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->last_event = event_queue_write();
up->data = (void *) PQconnectStart(up->args);
if (up->data) {
// status = CONNECTING
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD)
goto bad;
up->fd = PQsocket((PGconn *) up->data);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
bad:
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// check the state
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD) {
// signal the bad connection (if needed)
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
else if (up->state == CONNECTION_OK) {
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
// still wait...
else {
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
// the connection is good
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
if (wait_type == PGRES_POLLING_ACTIVE)
wait_type = PQconnectPoll((PGconn *) up->data);
up->cycles = 0;
up->fd = -1;
// state = NOOP
up->state = 0;
PQfinish((PGconn *) up->data);
if (wait_type == PGRES_POLLING_FAILED) {
if (!up->bad) {
up->bad = 1;
return 1;
}
}
else {
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
else if (wait_type == PGRES_POLLING_READING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
up->last_event = event_queue_read();
}
else if (wait_type == PGRES_POLLING_WRITING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
up->last_event = event_queue_write();
}
}
}
}
// default action
return 0;
}
int probepg_init() {
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
return 0;
}
struct uwsgi_plugin probepg_plugin = {
.init = probepg_init,
};
+9
View File
@@ -0,0 +1,9 @@
import os
NAME='probepg'
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
GCC_LIST = ['pgprobe']
+1
View File
@@ -147,6 +147,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
wsgi_req->sendfile_fd = SvIV(fn);
SvREFCNT_dec(fn);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
// no need to close here as perl GC will do the close()
return UWSGI_OK;
}
+8 -6
View File
@@ -155,26 +155,28 @@ XS(XS_call) {
dXSARGS;
char buffer[0xffff];
char *func;
uint16_t size = 0;
int i;
char *argv[0xff];
char *argv[256];
uint16_t argvs[256];
STRLEN arg_len;
psgi_check_args(1);
func = SvPV_nolen(ST(0));
for(i=0;i<(items-1);i++) {
argv[i] = SvPV_nolen(ST(i+1));
argv[i] = SvPV(ST(i+1), arg_len);
argvs[i] = arg_len;
}
size = uwsgi_rpc(func, items-1, argv, buffer);
char *response = uwsgi_do_rpc(NULL, func, items-1, argv, argvs, &size);
if (size > 0) {
ST(0) = newSVpv(buffer, size);
ST(0) = newSVpv(response, size);
sv_2mortal(ST(0));
free(response);
XSRETURN(1);
}
+1 -1
View File
@@ -342,12 +342,12 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Pump response.\n");
goto clear;
}
#endif
}
+15 -16
View File
@@ -80,9 +80,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
int id = uwsgi_apps_cnt;
int multiapp = 0;
#ifdef UWSGI_ASYNC
int i;
#endif
char *mountpoint;
@@ -320,9 +318,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
// add start_response on WSGI app
Py_INCREF((PyObject *)up.wsgi_spitout);
wi->wsgi_args = PyTuple_New(wi->argc);
wi->args = PyTuple_New(wi->argc);
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
if (PyTuple_SetItem(wi->args, 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
}
@@ -370,24 +368,25 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
PyThreadState_Swap(up.main_thread);
}
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
const char *default_app = "";
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
uwsgi_rawlog(" (default app)");
default_app = " (default app)" ;
uwsgi.default_app = id;
}
uwsgi_apps_cnt++;
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
uwsgi_rawlog("\n");
uwsgi_apps_cnt++;
if (multiapp > 1) {
for(i=1;i<multiapp;i++) {
+77 -23
View File
@@ -29,6 +29,10 @@ struct option uwsgi_python_options[] = {
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"shared-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-pyimport", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-py-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-python-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
@@ -106,9 +110,9 @@ int uwsgi_python_init() {
#ifndef UWSGI_PYPY
char *pyversion = strchr(Py_GetVersion(), '\n');
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
#else
uwsgi_log("PyPy version: %s\n", PYPY_VERSION);
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif
#ifndef UWSGI_PYPY
@@ -160,7 +164,7 @@ int uwsgi_python_init() {
up.reset_ts = simple_reset_ts;
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
uwsgi_log_initial("Python main interpreter initialized at %p\n", up.main_thread);
return 1;
@@ -253,7 +257,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!pyfile) {
uwsgi_error_open(real_filename);
free(real_filename);
fclose(pyfile);
return NULL;
}
}
@@ -740,6 +743,9 @@ int uwsgi_python_manage_options(int i, char *optarg) {
uwsgi.honour_stdin = 1;
up.pyshell = 1;
return 1;
case LONG_ARGS_SHARED_PYIMPORT:
uwsgi_string_new_list(&up.shared_import_list, optarg);
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
return 1;
@@ -893,17 +899,8 @@ void uwsgi_python_spooler_init(void) {
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
#ifndef UWSGI_PYPY
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
}
// this hook will be executed by master (or worker1 when master is not requested, so COW is in place)
void uwsgi_python_preinit_apps() {
init_pyargv();
@@ -913,7 +910,6 @@ void uwsgi_python_init_apps() {
#endif
#endif
#ifdef __linux__
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
@@ -931,6 +927,34 @@ void uwsgi_python_init_apps() {
init_uwsgi_vars();
// load shared imports
struct uwsgi_string_list *upli = up.shared_import_list;
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
}
else {
if (PyImport_ImportModule(upli->value) == NULL) {
PyErr_Print();
}
}
upli = upli->next;
}
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
// prepare for stack suspend/resume
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
#ifndef UWSGI_PYPY
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
}
// setup app loaders
#ifdef UWSGI_MINTERPRETERS
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
@@ -1091,8 +1115,34 @@ void uwsgi_python_init_thread(int core_id) {
pthread_setspecific(up.upt_save_key, (void *) pts);
pthread_setspecific(up.upt_gil_key, (void *) pts);
#ifdef UWSGI_DEBUG
uwsgi_log("pts %d = %p\n", core_id, pts);
uwsgi_log("python ThreadState %d = %p\n", core_id, pts);
#endif
UWSGI_GET_GIL;
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
PyObject *threading_module = PyImport_ImportModule("threading");
if (threading_module) {
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
if (threading_module_dict) {
#ifdef PYTHREE
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
#else
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
#endif
if (threading_current) {
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
if (!current_thread) {
// ignore the error
PyErr_Clear();
}
else {
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
Py_INCREF(current_thread);
}
}
}
}
UWSGI_RELEASE_GIL;
}
@@ -1241,36 +1291,38 @@ clear:
return -1;
}
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
UWSGI_GET_GIL;
uint8_t i;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
char *rv;
size_t rl;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
if (!pyargs)
return 0;
for (i = 0; i < argc; i++) {
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
PyTuple_SetItem(pyargs, i, PyString_FromStringAndSize(argv[i], argvs[i]));
}
ret = python_call((PyObject *) func, pyargs, 0, NULL);
Py_DECREF(pyargs);
if (ret) {
if (PyString_Check(ret)) {
rv = PyString_AsString(ret);
rl = PyString_Size(ret);
if (rl <= 0xffff) {
if (rl <= 65536) {
memcpy(buffer, rv, rl);
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return rl;
}
}
Py_DECREF(ret);
}
if (PyErr_Occurred())
@@ -1454,6 +1506,8 @@ struct uwsgi_plugin python_plugin = {
.short_options = "w:O:H:J:",
.request = uwsgi_request_wsgi,
.after_request = uwsgi_after_request_wsgi,
.preinit_apps = uwsgi_python_preinit_apps,
.init_apps = uwsgi_python_init_apps,
.fixup = uwsgi_python_fixup,
+72 -116
View File
@@ -220,6 +220,25 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
return Py_True;
}
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int timeout = 0;
int freq = 0;
char *probe, *probe_args;
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
return NULL;
}
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
return PyErr_Format(PyExc_ValueError, "unable to add probe");
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
@@ -275,13 +294,13 @@ PyObject *py_uwsgi_add_file_monitor(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
char buffer[0xffff];
char *func;
uint16_t size = 0;
PyObject *py_func;
int argc = PyTuple_Size(args);
int i;
char *argv[0xff];
char *argv[256];
uint16_t argvs[256];
// TODO better error reporting
if (argc < 1)
@@ -295,19 +314,29 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
func = PyString_AsString(py_func);
for (i = 0; i < (argc - 1); i++) {
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 1));
PyObject *py_str = PyTuple_GetItem(args, i + 1);
if (!PyString_Check(py_str)) {
goto clear;
}
argv[i] = PyString_AsString(py_str);
argvs[i] = PyString_Size(py_str);
}
size = uwsgi_rpc(func, argc - 1, argv, buffer);
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
if (size > 0) {
return PyString_FromStringAndSize(buffer, size);
PyObject *ret = PyString_FromStringAndSize(response, size);
free(response);
return ret;
}
clear:
Py_INCREF(Py_None);
return Py_None;
clear:
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
}
PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
@@ -327,19 +356,15 @@ PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
char buffer[0xffff];
char *node, *func;
char *node = NULL, *func;
uint16_t size = 0;
PyObject *py_node, *py_func;
struct wsgi_request rpc_req;
int argc = PyTuple_Size(args);
char *argv[0xff];
int i, fd;
uint16_t pktsize = 0, ulen;
char *bufptr;
int rlen;
int rpc_args = 0;
int argc = PyTuple_Size(args);
char *argv[256];
uint16_t argvs[256];
int i;
// TODO better error reporting
if (argc < 2)
@@ -350,9 +375,6 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
if (PyString_Check(py_node)) {
node = PyString_AsString(py_node);
}
else {
node = "";
}
py_func = PyTuple_GetItem(args, 1);
@@ -362,87 +384,28 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
func = PyString_AsString(py_func);
for (i = 0; i < (argc - 2); i++) {
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 2));
rpc_args++;
PyObject *py_str = PyTuple_GetItem(args, i + 2);
if (!PyString_Check(py_str))
goto clear;
argv[i] = PyString_AsString(py_str);
argvs[i] = PyString_Size(py_str);
}
if (!strcmp(node, "")) {
if (!rpc_args) {
size = uwsgi_rpc(func, 0, NULL, buffer);
}
else {
size = uwsgi_rpc(func, rpc_args, argv, buffer);
}
}
else {
// connect to node
fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0)
goto clear;
// prepare a uwsgi array
pktsize = 2 + strlen(func);
for (i = 0; i < argc - 2; i++) {
pktsize += 2 + strlen(argv[i]);
}
memset(&rpc_req, 0, sizeof(struct wsgi_request));
rpc_req.uh.modifier1 = 173;
rpc_req.uh.pktsize = pktsize;
rpc_req.uh.modifier2 = 0;
bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc - 2; i++) {
ulen = strlen(argv[i]);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &rpc_req.uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
goto clear;
}
if (write(fd, buffer, pktsize) != pktsize) {
uwsgi_error("write()");
close(fd);
goto clear;
}
rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (rlen > 0) {
rpc_req.poll.fd = fd;
rpc_req.poll.events = POLLIN;
rpc_req.buffer = buffer;
if (uwsgi_parse_packet(&rpc_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
size = rpc_req.uh.pktsize;
}
}
}
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
if (size > 0) {
return PyString_FromStringAndSize(buffer, size);
}
PyObject *ret = PyString_FromStringAndSize(response, size);
free(response);
return ret;
}
Py_INCREF(Py_None);
return Py_None;
clear:
Py_INCREF(Py_None);
return Py_None;
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
}
PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
@@ -464,23 +427,6 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
return Py_True;
}
PyObject *py_uwsgi_attach_daemon(PyObject * self, PyObject * args) {
char *command = NULL;
if (!PyArg_ParseTuple(args, "s:attach_daemon", &command)) {
return NULL;
}
if (uwsgi_attach_daemon(command)) {
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
}
PyObject *py_uwsgi_signal_registered(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
@@ -1942,13 +1888,18 @@ PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
char *host, *message;
Py_ssize_t message_len;
ssize_t ret;
char *uwsgi_message;
if (!PyArg_ParseTuple(args, "ss:send_multicast_message", &host, &message)) {
if (!PyArg_ParseTuple(args, "ss#:send_multicast_message", &host, &message, &message_len)) {
return NULL;
}
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, host, message, strlen(message));
uwsgi_message = uwsgi_malloc(message_len+4);
memcpy(uwsgi_message+4, message, message_len);
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, 0, host, uwsgi_message, message_len);
free(uwsgi_message);
if (ret <= 0) {
Py_INCREF(Py_None);
@@ -2338,7 +2289,7 @@ PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
ui->func = NULL;
// mark a route request
wsgi_req->status = -1;
wsgi_req->status = -17;
return (PyObject *) ui;
}
@@ -2485,6 +2436,12 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
}
Py_DECREF(zero);
zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].delta_requests);
if (PyDict_SetItemString(worker_dict, "delta_requests", zero)) {
goto clear;
}
Py_DECREF(zero);
zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].signals);
if (PyDict_SetItemString(worker_dict, "signals", zero)) {
goto clear;
@@ -3010,8 +2967,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"listen_queue", py_uwsgi_listen_queue, METH_VARARGS, ""},
{"attach_daemon", py_uwsgi_attach_daemon, METH_VARARGS, ""},
{"register_signal", py_uwsgi_register_signal, METH_VARARGS, ""},
{"signal", py_uwsgi_signal, METH_VARARGS, ""},
{"signal_wait", py_uwsgi_signal_wait, METH_VARARGS, ""},
@@ -3019,6 +2974,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
+2 -2
View File
@@ -21,6 +21,7 @@
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
#define PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
@@ -133,6 +134,7 @@ struct uwsgi_python {
struct uwsgi_string_list *python_path;
struct uwsgi_string_list *import_list;
struct uwsgi_string_list *shared_import_list;
struct uwsgi_string_list *spooler_import_list;
struct uwsgi_string_list *post_pymodule_alias;
@@ -210,8 +212,6 @@ PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
ssize_t uwsgi_sendfile(struct wsgi_request *);
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *);
+1 -1
View File
@@ -192,12 +192,12 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
#endif
}
+77
View File
@@ -6,6 +6,26 @@ extern struct uwsgi_rack ur;
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
Check_Type(rbmessage, T_STRING);
char *message = RSTRING_PTR(rbmessage);
size_t len = RSTRING_LEN(rbmessage);
if (len > 80) {
uwsgi_log("- warning message must be max 80 chars, it will be truncated -");
memcpy(uwsgi.shared->warning_message, message, 80);
uwsgi.shared->warning_message[80] = 0;
}
else {
memcpy(uwsgi.shared->warning_message, message, len);
uwsgi.shared->warning_message[len] = 0;
}
return Qnil;
}
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
Check_Type(rbname, T_STRING);
@@ -575,6 +595,59 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
return Qfalse;
}
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
char *node = NULL, *func;
uint16_t size = 0;
char *argv[256];
uint16_t argvs[256];
int i;
// TODO better error reporting
if (argc < 2)
goto clear;
VALUE rpc_node = rpc_argv[0];
if (TYPE(rpc_node) == T_STRING) {
node = RSTRING_PTR(rpc_node);
}
VALUE rpc_func = rpc_argv[1];
if (TYPE(rpc_func) != T_STRING)
goto clear;
func = RSTRING_PTR(rpc_func);
for (i = 0; i < (argc - 2); i++) {
VALUE rpc_str = rpc_argv[i + 2];
if (TYPE(rpc_str) != T_STRING)
goto clear;
argv[i] = RSTRING_PTR(rpc_str);
argvs[i] = RSTRING_LEN(rpc_str);
}
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
if (size > 0) {
VALUE ret = rb_str_new(response, size);
free(response);
return ret;
}
clear:
rb_raise(rb_eRuntimeError, "unable to call rpc function");
return Qnil;
}
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
int rb_argc = 0;
@@ -690,6 +763,10 @@ void uwsgi_rack_init_api() {
uwsgi_rack_api("mule_id", rack_uwsgi_mule_id, 0);
uwsgi_rack_api("logsize", rack_uwsgi_logsize, 0);
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
if (uwsgi.cache_max_items > 0) {
+146 -120
View File
@@ -149,6 +149,10 @@ VALUE require_rails(VALUE arg) {
#endif
}
VALUE require_thin(VALUE arg) {
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("thin"));
}
VALUE init_rack_app(VALUE);
VALUE rack_call_rpc_handler(VALUE args) {
@@ -157,7 +161,7 @@ VALUE rack_call_rpc_handler(VALUE args) {
}
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint8_t i;
VALUE rb_args = rb_ary_new2(2);
@@ -170,7 +174,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
rb_ary_store(rb_args, 0, (VALUE) func);
for (i = 0; i < argc; i++) {
rb_ary_store(rb_rpc_args, i, rb_str_new2(argv[i]));
rb_ary_store(rb_rpc_args, i, rb_str_new(argv[i], argvs[i]));
}
rb_ary_store(rb_args, 1, rb_rpc_args);
@@ -211,8 +215,6 @@ int uwsgi_rack_init(){
http_sc->message_size = (int) strlen(http_sc->message);
}
ur.unprotected = 0;
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK
@@ -282,7 +284,27 @@ void uwsgi_rack_init_apps(void) {
uwsgi_log("rails app %s ready\n", ur.rails);
VALUE ac = rb_const_get(rb_cObject, rb_intern("ActionController"));
ur.dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
ur.dispatcher = Qnil;
if (rb_funcall(ac, rb_intern("const_defined?"), 1, ID2SYM(rb_intern("Dispatcher"))) == Qtrue) {
VALUE ac_dispatcher = rb_const_get(ac, rb_intern("Dispatcher"));
if (rb_respond_to(ac_dispatcher, rb_intern("call")) || rb_respond_to(ac_dispatcher, ID2SYM(rb_intern("call")))) {
ur.dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
}
}
if (ur.dispatcher == Qnil) {
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
rb_protect( require_thin, 0, &error ) ;
if (error) {
uwsgi_ruby_exception();
exit(1);
}
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
VALUE thin_rack_adapter = rb_const_get(thin_rack, rb_intern("Adapter"));
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
ur.dispatcher = rb_funcall( thin_rack_adapter_rails, rb_intern("new"), 0);
}
if (ur.dispatcher == Qnil) {
uwsgi_log("unable to load rails dispatcher\n");
@@ -330,7 +352,7 @@ VALUE call_dispatch(VALUE env) {
}
VALUE send_body(VALUE obj) {
static VALUE send_body(VALUE obj) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t len = 0;
@@ -348,6 +370,15 @@ VALUE send_body(VALUE obj) {
return Qnil;
}
VALUE body_to_path(VALUE body) {
return rb_funcall( body, rb_intern("to_path"), 0);
}
VALUE close_body(VALUE body) {
return rb_funcall( body, rb_intern("close"), 0);
}
VALUE iterate_body(VALUE body) {
#ifdef RUBY19
@@ -355,7 +386,6 @@ VALUE iterate_body(VALUE body) {
#else
return rb_iterate(rb_each, body, send_body, 0);
#endif
}
VALUE send_header(VALUE obj, VALUE headers) {
@@ -390,63 +420,50 @@ VALUE send_header(VALUE obj, VALUE headers) {
}
if (TYPE(hkey) != T_STRING || TYPE(hval) != T_STRING) {
goto clear2;
goto clear;
}
//uwsgi_log("header: %.*s: %.*s\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), RSTRING_LEN(hval), RSTRING_PTR(hval));
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
char *header_value = RSTRING_PTR(hval);
int header_value_len = RSTRING_LEN(hval);
size_t header_value_len = RSTRING_LEN(hval);
size_t i,cnt=0;
char *this_header = header_value;
char *header_value_splitted = memchr(header_value, '\n', header_value_len);
for(i=0;i<header_value_len;i++) {
// multiline header, send it !!!
if (header_value[i] == '\n') {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
if (!header_value_splitted) {
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_len);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
//uwsgi_log("(multi) --%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
wsgi_req->header_cnt++;
this_header += cnt+1;
cnt = 0;
continue;
}
cnt++;
}
else {
header_value_splitted[0] = 0;
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_splitted-header_value);
if (cnt > 0) {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
header_value = header_value_splitted+1;
header_value_len -= header_value_splitted-header_value;
while(header_value_len && (header_value_splitted = memchr(header_value, '\n', header_value_len))) {
header_value_splitted[0] = 0;
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, header_value, header_value_splitted-header_value);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
header_value = header_value_splitted+1;
header_value_len -= header_value_splitted-header_value;
}
//uwsgi_log("--%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
}
clear2:
rb_gc_unregister_address(&hkey);
rb_gc_unregister_address(&hval);
clear:
return Qnil;
@@ -502,6 +519,8 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
) {
rb_hash_aset(env, rb_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
rb_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len));
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
}
i++;
}
@@ -544,16 +563,10 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
if (ur.unprotected) {
ret = rb_funcall(ur.dispatcher, ur.call, 1, env);
}
else {
ret = rb_protect( call_dispatch, env, &error);
}
ret = rb_protect( call_dispatch, env, &error);
if (error) {
uwsgi_ruby_exception();
//return -1;
goto clear;
}
if (TYPE(ret) == T_ARRAY) {
@@ -600,21 +613,10 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
headers = RARRAY_PTR(ret)[1] ;
if (rb_respond_to( headers, rb_intern("each") )) {
if (ur.unprotected) {
#ifdef RUBY19
rb_block_call(headers, rb_intern("each"), 0, 0, send_header, headers);
#else
rb_iterate(rb_each, headers, send_header, headers);
#endif
}
else {
rb_protect( iterate_headers, headers, &error);
if (error) {
uwsgi_ruby_exception();
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
goto clear;
}
rb_protect( iterate_headers, headers, &error);
if (error) {
uwsgi_ruby_exception();
goto clear;
}
}
@@ -625,47 +627,38 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
body = RARRAY_PTR(ret)[2] ;
if (rb_respond_to( body, rb_intern("to_path") )) {
VALUE sendfile_path = rb_funcall( body, rb_intern("to_path"), 0);
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
if (wsgi_req->response_size > 0) {
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
rb_gc_unregister_address(&sendfile_path);
}
else if (rb_respond_to( body, rb_intern("each") )) {
if (ur.unprotected) {
#ifdef RUBY19
rb_block_call(body, rb_intern("each"), 0, 0, send_body, 0);
#else
rb_iterate(rb_each, body, send_body, 0);
#endif
VALUE sendfile_path = rb_protect( body_to_path, body, &error);
if (error) {
uwsgi_ruby_exception();
}
else {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
if (wsgi_req->response_size > 0) {
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
// we need to close it...
close(wsgi_req->sendfile_fd);
}
}
else if (rb_respond_to( body, rb_intern("each") )) {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
}
}
if (rb_respond_to( body, rb_intern("close") )) {
//uwsgi_log("calling close\n");
rb_funcall( body, rb_intern("close"), 0);
rb_protect( close_body, body, &error);
if (error) {
uwsgi_ruby_exception();
}
}
//fine:
/* unregister all the objects created */
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
rb_gc_unregister_address(&body);
}
else {
internal_server_error(wsgi_req, (char *)"Invalid RACK response");
@@ -673,10 +666,6 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
clear:
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&env);
if (ur.gc_freq <= 1 || ur.cycles%ur.gc_freq == 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("calling ruby GC\n");
@@ -732,6 +721,44 @@ void uwsgi_rack_resume(struct wsgi_request *wsgi_req) {
uwsgi_log("RESUMING RUBY\n");
}
#ifdef RUBY19
VALUE uwsgi_call_block(VALUE body, VALUE block) {
return rb_funcall(block, rb_intern("call"), 1, body );
}
VALUE uwsgi_rack_patch_body_proxy_each(int argc, VALUE *argv, VALUE self) {
VALUE block = Qnil;
rb_scan_args(argc, argv, "0&", &block);
if(!RTEST(block)) {
rb_raise(rb_eArgError, "a block is required");
return Qnil;
}
VALUE original_body = rb_iv_get(self, "@body");
if (original_body != Qnil) {
return rb_block_call(original_body, rb_intern("each"), 0, 0, uwsgi_call_block, block);
}
return Qnil;
}
VALUE uwsgi_rack_patch_body_proxy(VALUE foo) {
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
VALUE rack_body_proxy = rb_const_get(rack, rb_intern("BodyProxy"));
if (!rb_respond_to(rack_body_proxy, rb_intern("each"))) {
rb_define_method(rack_body_proxy, "each", uwsgi_rack_patch_body_proxy_each, -1);
return Qtrue;
}
return Qnil;
}
#endif
VALUE init_rack_app( VALUE script ) {
int error;
@@ -746,6 +773,14 @@ VALUE init_rack_app( VALUE script ) {
}
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
#ifdef RUBY19
VALUE ret = rb_protect(uwsgi_rack_patch_body_proxy, rack, &error);
if (!error && ret != Qnil) {
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
}
#endif
VALUE rackup = rb_funcall( rb_const_get(rack, rb_intern("Builder")), rb_intern("parse_file"), 1, script);
if (TYPE(rackup) != T_ARRAY) {
uwsgi_log("unable to parse %s file\n", RSTRING_PTR(script));
@@ -879,23 +914,14 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
rb_ary_store(args, 0, rbhandler);
VALUE rbsig = INT2NUM(sig);
rb_ary_store(args, 1, rbsig);
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
rb_protect(rack_call_signal_handler, args, &error);
if (error) {
uwsgi_ruby_exception();
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
rb_gc();
return -1;
}
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
rb_gc();
return 0;
}
-1
View File
@@ -62,7 +62,6 @@ struct uwsgi_rack {
VALUE rb_uwsgi_io_class;
ID call;
VALUE fibers[200];
int unprotected;
pthread_mutex_t gvl;
+3 -2
View File
@@ -6,6 +6,7 @@ extern struct uwsgi_server uwsgi;
int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
char *argv[256];
uint16_t argvs[256];
uint8_t argc = 0xff;
/* Standard RPC request */
@@ -24,7 +25,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
uwsgi_log("RPC pktsize %d\n", wsgi_req->uh.pktsize);
#endif
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
}
@@ -33,7 +34,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
uwsgi_log("RPC args %d\n", argc-1);
#endif
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, wsgi_req->buffer);
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, wsgi_req->buffer);
if (wsgi_req->uh.modifier2 == 0) {
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, (char *)&wsgi_req->uh, 4);
+1 -1
View File
@@ -46,7 +46,7 @@ int rrdtool_init() {
if (!u_rrd.max_ds) u_rrd.max_ds = 30;
uwsgi_log("*** RRDtool library available at %p ***\n", u_rrd.lib);
uwsgi_log_initial("*** RRDtool library available at %p ***\n", u_rrd.lib);
return 0;
}
+197 -66
View File
@@ -123,16 +123,21 @@ time_t parse_http_date(char *date, uint16_t len) {
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
char *udp_port;
ssize_t ret;
char udpbuff[1024];
if (message_size + 4 > 1024)
return -1;
struct uwsgi_header *uh;
if (message) {
uh = (struct uwsgi_header *) message;
}
else {
uh = (struct uwsgi_header *) uwsgi_malloc(4);
}
udp_port = strchr(host, ':');
if (udp_port == NULL) {
@@ -152,22 +157,15 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(host);
udpbuff[0] = modifier1;
uh->modifier1 = modifier1;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
uh->pktsize = uwsgi_swap16(message_size);
#else
uh->pktsize = message_size;
#endif
uh->modifier2 = modifier2;
memcpy(udpbuff+1, &message_size, 2);
udpbuff[3] = 0;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+4, message, message_size);
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
if (ret < 0) {
uwsgi_error("sendto()");
}
@@ -175,6 +173,10 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
udp_port[0] = ':';
if ((char *)uh != message) {
free(uh);
}
return ret;
}
@@ -342,6 +344,59 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
return ret;
}
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
char *ptr = (char *) uh;
size_t remains = 4;
int ret = -1;
int rlen;
ssize_t len;
while(remains > 0) {
rlen = uwsgi_waitfd(fd, timeout);
if (rlen > 0) {
len = read(fd, ptr, remains);
if (len <= 0) break;
remains -= len;
ptr += len;
if (remains == 0) {
ret = uh->modifier2;
break;
}
continue;
}
// timed out ?
else if (ret == 0) ret = -2;
break;
}
if (buf && uh->pktsize > 0) {
if (*buf == NULL)
*buf = uwsgi_malloc(uh->pktsize);
remains = uh->pktsize;
ptr = *buf;
ret = -1;
while(remains > 0) {
rlen = uwsgi_waitfd(fd, timeout);
if (rlen > 0) {
len = read(fd, ptr, remains);
if (len <= 0) break;
remains -= len;
ptr += len;
if (remains == 0) {
ret = uh->modifier2;
break;
}
continue;
}
// timed out ?
else if (ret == 0) ret = -2;
break;
}
}
return ret;
}
int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
int rlen;
@@ -369,9 +424,9 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
}
if (status < 0) {
if (status == -1)
uwsgi_log("error parsing request\n");
uwsgi_log_verbose("error parsing request\n");
else if (status == -2)
uwsgi_log("open-close packet (ping/check) received\n");
uwsgi_log_verbose("open-close packet (ping/check) received\n");
//close(upoll->fd);
return 0;
}
@@ -380,7 +435,7 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
return 1;
}
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint16_t argvs[], uint8_t *argc) {
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
@@ -405,6 +460,7 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
if (ptrbuf + strsize <= bufferend) {
// item
argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
argvs[*argc] = strsize;
#ifdef UWSGI_DEBUG
uwsgi_log("arg %s\n", argv[*argc]);
#endif
@@ -500,6 +556,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
struct uwsgi_dyn_dict *udd;
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->uh.pktsize;
@@ -807,25 +864,46 @@ next:
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
if (!uwsgi_file_serve(wsgi_req, uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len, uwsgi.check_static, uwsgi.check_static_len)) {
return -1;
if (wsgi_req->path_info_len > 1) {
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
udd->value = realpath(udd->key, NULL);
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
nextcs:
udd = udd->next;
}
}
// check static-map
struct uwsgi_static_map *usm = uwsgi.static_maps;
while(usm) {
udd = uwsgi.static_maps;
while(udd) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, usm->mountpoint_len, usm->mountpoint);
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
#endif
if (udd->status == 0) {
char *real_docroot = realpath(udd->value, NULL);
if (!real_docroot) goto nextsm;
udd->value = real_docroot;
udd->vallen = strlen(udd->value);
udd->status = 1;
}
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, usm->mountpoint, usm->mountpoint_len)) {
if (!uwsgi_file_serve(wsgi_req, usm->document_root, usm->document_root_len, wsgi_req->path_info+usm->mountpoint_len, wsgi_req->path_info_len-usm->mountpoint_len, usm->orig_document_root, usm->orig_document_root_len)) {
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
return -1;
}
}
usm = usm->next;
nextsm:
udd = udd->next;
}
return 0;
@@ -1383,17 +1461,20 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
return NULL;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, char *orig_document_root, uint16_t orig_document_root_len) {
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
struct stat st;
struct iovec headers_vec[8];
char real_filename[PATH_MAX];
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
char content_length[sizeof(UMAX64_STR)+1];
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("unable to get realpath() of the static file\n");
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
@@ -1402,9 +1483,10 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
free(filename);
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
uwsgi_log("security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
return -1;
}
if (!stat(real_filename, &st)) {
int mime_type_size = 0;
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
@@ -1412,13 +1494,21 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 304 Not Modified\r\n", 19);
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 304 Not Modified\r\n";
headers_vec[1].iov_len = 19;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
headers_vec[0].iov_base = ah->value;
headers_vec[0].iov_len = ah->len;
headers_vec[1].iov_base = "\r\n";
headers_vec[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
wsgi_req->header_cnt++;
ah = ah->next;
}
@@ -1429,58 +1519,99 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("file %s found\n", real_filename);
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 200 OK\r\n", 9);
// HTTP status
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 200 OK\r\n";
headers_vec[1].iov_len = 9;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
// uWSGI additional headers
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
headers_vec[0].iov_base = ah->value;
headers_vec[0].iov_len = ah->len;
headers_vec[1].iov_base = "\r\n";
headers_vec[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
wsgi_req->header_cnt++;
ah = ah->next;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
headers_vec[0].iov_base = "Content-Type: ";
headers_vec[0].iov_len = 14;
headers_vec[1].iov_base = mime_type;
headers_vec[1].iov_len = mime_type_size;
headers_vec[2].iov_base = "\r\n";
headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
wsgi_req->header_cnt++;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "Content-Type: ", 14);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, mime_type, mime_type_size);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
}
// nginx
if (uwsgi.file_serve_mode == 1) {
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
if (orig_document_root[orig_document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
headers_vec[0].iov_base = "X-Accel-Redirect: "; headers_vec[0].iov_len = 18 ;
headers_vec[1].iov_base = document_root; headers_vec[1].iov_len = document_root_len;
if (document_root[document_root_len-1] != '/') {
headers_vec[2].iov_base = "/"; headers_vec[2].iov_len = 1;
headers_vec[3].iov_base = path_info; headers_vec[3].iov_len = path_info_len;
headers_vec[4].iov_base = "\r\n"; headers_vec[4].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 5);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
else {
headers_vec[2].iov_base = path_info; headers_vec[2].iov_len = path_info_len;
headers_vec[3].iov_base = "\r\n"; headers_vec[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
}
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
}
else if (uwsgi.file_serve_mode == 2) {
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Sendfile: ", 12);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
if (orig_document_root[orig_document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
}
else {
wsgi_req->header_cnt += 1;
// apache
else if (uwsgi.file_serve_mode == 2) {
headers_vec[0].iov_base = "X-Sendfile: "; headers_vec[0].iov_len = 12 ;
headers_vec[1].iov_base = document_root; headers_vec[1].iov_len = document_root_len;
if (document_root[document_root_len-1] != '/') {
headers_vec[2].iov_base = "/"; headers_vec[2].iov_len = 1;
headers_vec[3].iov_base = path_info; headers_vec[3].iov_len = path_info_len;
headers_vec[4].iov_base = "\r\n"; headers_vec[4].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 5);
}
else {
headers_vec[2].iov_base = path_info; headers_vec[2].iov_len = path_info_len;
headers_vec[3].iov_base = "\r\n"; headers_vec[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
}
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->header_cnt += 2;
}
// raw
else {
// set Content-Length
headers_vec[0].iov_base = "Content-Length: ";
headers_vec[0].iov_len = 16;
headers_vec[1].iov_len = uwsgi_long2str2n(st.st_size, content_length, sizeof(UMAX64_STR)+1);
headers_vec[1].iov_base = content_length;
headers_vec[2].iov_base = "\r\n";
headers_vec[2].iov_len = 2;
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
headers_vec[3].iov_base = http_last_modified;
headers_vec[3].iov_len = 48;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
wsgi_req->header_cnt += 2;
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
// here we need to close the sendfile fd (no-GC involved)
close(wsgi_req->sendfile_fd);
}
+86 -2
View File
@@ -33,7 +33,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
return ret;
}
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
struct uwsgi_rpc *urpc = NULL;
int i;
@@ -50,9 +50,93 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
if (urpc) {
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, output);
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
}
}
return ret;
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t *len) {
uint8_t i;
uint16_t ulen;
struct uwsgi_header uh;
char *buffer = NULL;
*len = 0;
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
// connect to node
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return NULL;
// prepare a uwsgi array
uint16_t buffer_size = 2 + strlen(func);
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
// add func to the array
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
close(fd);
free(buffer);
return NULL;
}
close(fd);
*len = uh.pktsize;
if (*len == 0) {
free(buffer);
return NULL;
}
return buffer;
}
+11 -1
View File
@@ -106,6 +106,7 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
#else
static size_t nosf_buf_size = 0;
static char *nosf_buf;
char *nosf_buf2;
ssize_t jlen = 0;
ssize_t rlen = 0;
@@ -115,7 +116,16 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
nosf_buf = malloc(chunk);
}
else if (chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, chunk);
nosf_buf2 = realloc(nosf_buf, chunk);
if (!nosf_buf2) {
free(nosf_buf);
}
nosf_buf = nosf_buf2;
}
if (!nosf_buf) {
uwsgi_error("sendfile malloc()/realloc()");
return 0;
}
nosf_buf_size = chunk;
+15 -9
View File
@@ -10,13 +10,15 @@ from setuptools.command.install_lib import install_lib
from setuptools.command.build_ext import build_ext
"""
This is a hack allowing you installing uWSGI and uwsgidecorators via pip and easy_install
This is a hack allowing you installing
uWSGI and uwsgidecorators via pip and easy_install
"""
uwsgi_compiled = False
def get_profile():
profile = os.environ.get('UWSGI_PROFILE','buildconf/default.ini')
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
if not profile.endswith('.ini'):
profile = "%s.ini" % profile
if not '/' in profile:
@@ -24,6 +26,7 @@ def get_profile():
return profile
def patch_bin_path(cmd, conf):
bin_name = conf.get('bin_name')
@@ -33,7 +36,8 @@ def patch_bin_path(cmd, conf):
os.makedirs(cmd.install_scripts)
if not os.path.isabs(bin_name):
print('Patching "bin_name" to properly install_scripts dir')
conf.set('bin_name', os.path.join(cmd.install_scripts, conf.get('bin_name')))
conf.set('bin_name',
os.path.join(cmd.install_scripts, conf.get('bin_name')))
except:
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
@@ -45,7 +49,7 @@ class uWSGIBuilder(build_ext):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
@@ -56,10 +60,11 @@ class uWSGIInstall(install):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
install.run(self)
class uWSGIInstallLib(install_lib):
def run(self):
@@ -67,10 +72,11 @@ class uWSGIInstallLib(install_lib):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
install_lib.run(self)
class uWSGIDistribution(Distribution):
def __init__(self, *attrs):
@@ -79,6 +85,7 @@ class uWSGIDistribution(Distribution):
self.cmdclass['install_lib'] = uWSGIInstallLib
self.cmdclass['build_ext'] = uWSGIBuilder
setup(name='uWSGI',
version=uc.uwsgi_version,
description='The uWSGI server',
@@ -86,7 +93,6 @@ setup(name='uWSGI',
author_email='info@unbit.it',
url='http://projects.unbit.it/uwsgi/',
license='GPL2',
py_modules = ['uwsgidecorators'],
distclass = uWSGIDistribution,
py_modules=['uwsgidecorators'],
distclass=uWSGIDistribution,
)
+114 -22
View File
@@ -12,6 +12,28 @@ int uwsgi_signal_handler(uint8_t sig) {
return -1;
}
// check for COW
if (uwsgi.master_process) {
if (use->wid != 0 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// in lazy mode (without a master), only the same worker will be able to run handlers
else if (uwsgi.lazy) {
if (use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
else {
// when master is not active, worker1 is the COW-leader
if (use->wid != 1 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
@@ -81,15 +103,22 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
use = &uwsgi.shared->signal_table[sig];
if (use->handler) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
uwsgi_unlock(uwsgi.signal_table_lock);
return -1;
}
strcpy(use->receiver, receiver);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
if (use->receiver[0] == 0) {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: default, any worker)\n", sig, modifier1);
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: default, any worker)\n", sig, uwsgi.mywid, modifier1);
}
else {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: %s)\n", sig, modifier1, receiver);
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
}
uwsgi_unlock(uwsgi.signal_table_lock);
@@ -128,6 +157,87 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while(uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while(up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024-1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
uwsgi_lock(uwsgi.timer_table_lock);
@@ -232,8 +342,6 @@ void create_signal_pipe(int *sigpipe) {
int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
uh.modifier1 = 110;
uh.pktsize = 0;
@@ -248,26 +356,10 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
return -1;
}
while(remains > 0) {
int rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (rlen > 0) {
ssize_t len = read(fd, ptr, remains);
if (len <= 0) {
break;
}
remains -= len;
ptr += len;
if (remains == 0) {
close(fd);
return uh.modifier2;
}
continue;
}
break;
}
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
close(fd);
return -1;
return ret;
}
+14 -1
View File
@@ -412,7 +412,7 @@ char *generate_socket_name(char *socket_name) {
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
asterisk[0] = '*';
new_socket = uwsgi_concat3(new_addr, ":", tcp_port + 1);
uwsgi_log("found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
uwsgi_log("[uwsgi-autoip] found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
freeifaddrs(ifap);
return new_socket;
}
@@ -1014,3 +1014,16 @@ void uwsgi_del_sockets_from_queue(int queue) {
}
int uwsgi_is_bad_connection(int fd) {
int soopt = 0;
socklen_t solen = sizeof(int) ;
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
return -1;
}
// will be 0 if all ok
return soopt;
}
+196 -6
View File
@@ -14,8 +14,12 @@
This system is not mean to run on shared memory. If you have multiple processes for the same app, you have to create
a new subscriptions slot list.
To avoid removal of already using nodes, a reference count system has been implemented
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
struct uwsgi_subscribe_slot *current_slot = *slot;
@@ -57,6 +61,8 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
}
#endif
current_slot = current_slot->next;
// check for loopy optimization
if (current_slot == *slot) break;
}
return NULL;
@@ -72,23 +78,67 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
if (current_slot) {
// node found, move up in the list increasing hits
current_slot->hits++;
time_t current = time(NULL);
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
if (rr_pos == current_slot->rr) {
// is the node alive ?
if (current - node->last_check > uwsgi.subscription_tolerance) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-subscription] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
node->failcnt++;
node->death_mark = 1;
}
if (node->death_mark && node->reference == 0) {
// remove the node and move to next
struct uwsgi_subscribe_node *dead_node = node;
node = node->next;
// if the slot has been removed, return NULL;
if (uwsgi_remove_subscribe_node(slot, dead_node) == 1) {
return NULL;
}
continue;
}
// only unmarked nodes can respond
if (node->death_mark == 0 && rr_pos == current_slot->rr) {
current_slot->rr++;
node->reference++;
return node;
}
node = node->next;
rr_pos++;
}
current_slot->rr = 0;
current_slot->rr = 1;
if (current_slot->nodes) {
if (current_slot->nodes->death_mark)
return NULL;
current_slot->nodes->reference++;
}
return current_slot->nodes;
}
return NULL;
}
void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen, int regexp) {
if (keylen > 0xff) return NULL;
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
if (current_slot) {
struct uwsgi_subscribe_node *node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(val, vallen, node->name, node->len)) {
return node;
}
node = node->next;
}
}
return NULL;
}
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
int ret = 0;
struct uwsgi_subscribe_node *a_node;
struct uwsgi_subscribe_slot *node_slot = node->slot;
@@ -115,6 +165,20 @@ void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsg
free(node);
// no more nodes, remove the slot too
if (node_slot->nodes == NULL) {
ret = 1;
// first check if i am the only node
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
free(node_slot);
*slot = NULL;
goto end;
}
// if i am the main entry point, set the next value
if (node_slot == *slot) {
*slot = next_slot;
}
if (prev_slot) {
prev_slot->next = next_slot;
@@ -133,11 +197,16 @@ void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsg
#endif
free(node_slot);
// am i the only slot ?
if (!prev_slot && !next_slot) {
*slot = NULL;
struct uwsgi_subscribe_slot *x_slot = *slot;
while(x_slot) {
x_slot = x_slot->next;
}
}
end:
return ret;
}
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr, int regexp) {
@@ -151,7 +220,11 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
// remove death mark and update cores and load
node->death_mark = 0;
node->last_check = time(NULL);
node->cores = usr->cores;
node->load = usr->load;
return node;
}
old_node = node;
@@ -162,6 +235,13 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->len = usr->address_len;
node->modifier1 = usr->modifier1;
node->modifier2 = usr->modifier2;
node->requests = 0;
node->transferred = 0;
node->reference = 0;
node->death_mark = 0;
node->failcnt = 0;
node->cores = usr->cores;
node->load = usr->load;
node->last_check = time(NULL);
node->slot = current_slot;
memcpy(node->name, usr->address, usr->address_len);
@@ -195,8 +275,15 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
current_slot->nodes->slot = current_slot;
current_slot->nodes->len = usr->address_len;
current_slot->nodes->reference = 0;
current_slot->nodes->requests = 0;
current_slot->nodes->transferred = 0;
current_slot->nodes->death_mark = 0;
current_slot->nodes->failcnt = 0;
current_slot->nodes->modifier1 = usr->modifier1;
current_slot->nodes->modifier2 = usr->modifier2;
current_slot->nodes->cores = usr->cores;
current_slot->nodes->load = usr->load;
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
current_slot->nodes->last_check = time(NULL);
@@ -272,3 +359,106 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd) {
char value_cores[sizeof(UMAX64_STR)+1];
char value_load[sizeof(UMAX64_STR)+1];
char value_modifier1[4];
char value_modifier2[4];
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc*uwsgi.cores, value_cores, sizeof(UMAX64_STR));
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
if (!uwsgi.sockets) return;
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name)) + (2+9 + 2+value_modifier1_size) +
(2+9 + 2+value_modifier2_size) + (2+5 + 2+value_cores_size) + (2+4 + 2+value_load_size);
char *subscrbuf = uwsgi_malloc(ssb_size);
// leave space for uwsgi header
char *ssb = subscrbuf+4;
// key = "domain"
uint16_t ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb+=ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb+=ustrlen;
// address = "first uwsgi socket"
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb+=ustrlen;
ustrlen = strlen(uwsgi.sockets->name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, uwsgi.sockets->name, ustrlen);
ssb+=ustrlen;
// modifier1 = "modifier1"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = value_modifier1_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_modifier1, value_modifier1_size);
ssb+=ustrlen;
// modifier2 = "modifier2"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier2", ustrlen);
ssb+=ustrlen;
ustrlen = value_modifier2_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_modifier2, value_modifier2_size);
ssb+=ustrlen;
// cores = uwsgi.numproc * uwsgi.cores
ustrlen = 5;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "cores", ustrlen);
ssb+=ustrlen;
ustrlen = value_cores_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_cores, value_cores_size);
ssb+=ustrlen;
// load
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "load", ustrlen);
ssb+=ustrlen;
ustrlen = value_load_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_load, value_load_size);
ssb+=ustrlen;
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size-4);
free(subscrbuf);
}
+180 -117
View File
@@ -247,6 +247,12 @@ void logto(char *logfile) {
exit(1);
}
uwsgi.logfile = logfile;
if (uwsgi.chmod_logfile_value) {
if (chmod(uwsgi.logfile, uwsgi.chmod_logfile_value)) {
uwsgi_error("chmod()");
}
}
#ifdef UWSGI_UDP
}
#endif
@@ -314,7 +320,11 @@ void log_socket(char *socket_name) {
void create_logpipe(void) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
#endif
uwsgi_error("socketpair()\n");
exit(1);
}
@@ -470,7 +480,7 @@ void uwsgi_as_root() {
if (!getuid()) {
if (!uwsgi.master_as_root && !uwsgi.uidname) {
uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
uwsgi_log_initial("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
}
#ifdef UWSGI_CAP
@@ -571,7 +581,7 @@ void uwsgi_as_root() {
}
if (!getuid()) {
uwsgi_log("*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
uwsgi_log_initial("*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
}
#ifdef UWSGI_CAP
@@ -659,6 +669,8 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
}
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
// this is used for MAX_REQUESTS
uwsgi.workers[uwsgi.mywid].delta_requests++;
// after_request hook
if (uwsgi.p[wsgi_req->uh.modifier1]->after_request)
@@ -694,7 +706,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
memset(wsgi_req, 0, sizeof(struct wsgi_request));
wsgi_req->async_id = tmp_id;
if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]) {
goodbye_cruel_world();
}
@@ -731,76 +743,76 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
#ifdef __linux__
#ifdef MADV_MERGEABLE
unsigned long long *ksm_mappings_last = NULL;
int ksm_mappings_last_lines = 0;
unsigned long long *ksm_mappings_current = NULL;
int ksm_mappings_current_lines = 0;
void uwsgi_linux_ksm_map(void) {
char map_line_buf[1024];
unsigned long long start, end;
int dirty = 0;
int i;
int errors = 0;
unsigned long long *tmp_ptr;
size_t i;
unsigned long long start = 0, end = 0;
int errors = 0; int lines = 0;
ksm_mappings_current = NULL;
ksm_mappings_current_lines = 0;
int fd = open("/proc/self/maps", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("[uwsgi-KSM] /proc/self/maps");
return ;
}
FILE *process_maps = fopen("/proc/self/maps", "r");
// allocate memory if not available;
if (uwsgi.ksm_mappings_current == NULL) {
if (!uwsgi.ksm_buffer_size) uwsgi.ksm_buffer_size = 32768;
uwsgi.ksm_mappings_current = uwsgi_malloc(uwsgi.ksm_buffer_size);
uwsgi.ksm_mappings_current_size = 0;
}
if (uwsgi.ksm_mappings_last == NULL) {
if (!uwsgi.ksm_buffer_size) uwsgi.ksm_buffer_size = 32768;
uwsgi.ksm_mappings_last = uwsgi_malloc(uwsgi.ksm_buffer_size);
uwsgi.ksm_mappings_last_size = 0;
}
if (process_maps) {
while( fgets(map_line_buf, 1024, process_maps)) {
if (fscanf(process_maps, "%llx-%llx %*s", &start, &end) == 2) {
ksm_mappings_current_lines+=2;
tmp_ptr = ksm_mappings_current;
ksm_mappings_current = realloc(ksm_mappings_current, sizeof(unsigned long long) * ksm_mappings_current_lines);
if (!ksm_mappings_current) {
uwsgi_error("[uwsgi-KSM] /proc/self/maps realloc()");
fclose(process_maps);
if (tmp_ptr) {
free(tmp_ptr);
}
return;
}
ksm_mappings_current[ksm_mappings_current_lines-2] = start;
ksm_mappings_current[ksm_mappings_current_lines-1] = end;
}
}
fclose(process_maps);
uwsgi.ksm_mappings_current_size = read(fd, uwsgi.ksm_mappings_current, uwsgi.ksm_buffer_size);
close(fd);
if (uwsgi.ksm_mappings_current_size <= 0) {
uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
return;
}
if (ksm_mappings_last == NULL || ksm_mappings_last_lines == 0 || ksm_mappings_last_lines != ksm_mappings_current_lines) {
// we now have areas
if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
dirty = 1;
}
else {
if (memcmp(uwsgi.ksm_mappings_current, uwsgi.ksm_mappings_last, uwsgi.ksm_mappings_current_size) != 0) {
dirty = 1;
}
else {
for(i=0;i<ksm_mappings_current_lines;i+=2) {
if (ksm_mappings_current[i] != ksm_mappings_last[i]) {
dirty = 1;
break;
}
if (ksm_mappings_current[i+1] != ksm_mappings_last[i+1]) {
dirty = 1;
break;
}
// it is dirty, swap addresses and parse it
if (dirty) {
char *tmp = uwsgi.ksm_mappings_last;
uwsgi.ksm_mappings_last = uwsgi.ksm_mappings_current;
uwsgi.ksm_mappings_current = tmp;
size_t tmp_size = uwsgi.ksm_mappings_last_size;
uwsgi.ksm_mappings_last_size = uwsgi.ksm_mappings_current_size;
uwsgi.ksm_mappings_current_size = tmp_size;
// scan each line and call madvise on it
char *ptr = uwsgi.ksm_mappings_last;
for(i=0;i<uwsgi.ksm_mappings_last_size;i++) {
if (uwsgi.ksm_mappings_last[i] == '\n') {
lines++;
uwsgi.ksm_mappings_last[i] = 0;
if (sscanf(ptr, "%llx-%llx %*s", &start, &end) == 2) {
if (madvise((void *) (long) start, (size_t) (end-start), MADV_MERGEABLE)) {
errors ++;
}
}
uwsgi.ksm_mappings_last[i] = '\n';
ptr = uwsgi.ksm_mappings_last+i+1;
}
}
if (dirty) {
for(i=0;i<ksm_mappings_current_lines;i+=2) {
if (madvise((void *) (long) ksm_mappings_current[i], (size_t) (ksm_mappings_current[i+1]-ksm_mappings_current[i]), MADV_MERGEABLE)) {
errors += 2;
}
}
free(ksm_mappings_last);
ksm_mappings_last = ksm_mappings_current;
ksm_mappings_last_lines = ksm_mappings_current_lines;
if (errors >= ksm_mappings_current_lines) {
uwsgi_error("[uwsgi-KSM] unable to share pages");
}
if (errors >= lines) {
uwsgi_error("[uwsgi-KSM] unable to share pages");
}
}
}
@@ -1640,11 +1652,18 @@ int uwsgi_read_whole_body(struct wsgi_request *wsgi_req, char *buf, size_t len)
else {
post_chunk = read(wsgi_req->poll.fd, buf, post_remains);
}
if (post_chunk < 0) {
uwsgi_error("read()");
goto end;
}
if (!fwrite(buf, post_chunk, 1, wsgi_req->async_post)) {
if (post_chunk == 0) {
uwsgi_log("client did not send the whole body: %s\n", strerror(errno));
goto end;
}
if (fwrite(buf, post_chunk, 1, wsgi_req->async_post) != 1) {
uwsgi_error("fwrite()");
goto end;
}
@@ -1695,7 +1714,7 @@ int uwsgi_read_whole_body(struct wsgi_request *wsgi_req, char *buf, size_t len)
return 0;
}
void _add_exported_option(char *key, char *value, int configured) {
void add_exported_option(char *key, char *value, int configured) {
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
@@ -1715,32 +1734,6 @@ void _add_exported_option(char *key, char *value, int configured) {
uwsgi.exported_opts_cnt++;
}
void add_exported_option(char *key, char *value, int configured) {
char *v = value;
if (value && strchr(value, ';')) {
v = uwsgi_str(value);
if (v[0] == '\\') {
_add_exported_option(key, v+1, configured);
return;
}
}
if (v == NULL) {
_add_exported_option(key, v, configured);
return;
}
char *p = strtok(v, ";");
while(p != NULL) {
_add_exported_option(key, p, configured);
p = strtok(NULL, ";");
}
}
int uwsgi_waitfd(int fd, int timeout) {
int ret;
@@ -1855,6 +1848,44 @@ char *uwsgi_read_fd(int fd, int *size, int add_zero) {
}
char *uwsgi_simple_file_read(char *filename) {
struct stat sb;
char *buffer;
ssize_t len;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
goto end;
}
if (fstat(fd, &sb)) {
uwsgi_error("fstat()");
close(fd);
goto end;
}
buffer = uwsgi_malloc(sb.st_size+1);
len = read(fd, buffer, sb.st_size);
if (len != sb.st_size) {
uwsgi_error("read()");
free(buffer);
close(fd);
goto end;
}
close(fd);
if (buffer[sb.st_size-1] == '\n' || buffer[sb.st_size-1] == '\r') {
buffer[sb.st_size-1] = 0;
}
buffer[sb.st_size] = 0;
return buffer;
end:
return (char *) "";
}
char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[]) {
int fd;
@@ -2120,6 +2151,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
if (S_ISFIFO(sb.st_mode)) {
buffer = uwsgi_read_fd(fd, size, add_zero);
close(fd);
goto end;
}
@@ -2216,32 +2248,6 @@ char *uwsgi_get_last_char(char *what, char c) {
return ptr;
}
int uwsgi_attach_daemon(char *command) {
struct uwsgi_daemon *d;
int ret = -1;
uwsgi_lock(uwsgi.daemon_table_lock);
if (uwsgi.shared->daemons_cnt < MAX_DAEMONS) {
d = &uwsgi.shared->daemons[uwsgi.shared->daemons_cnt];
memcpy(d->command, command, UMIN(strlen(command), 0xff - 1));
d->registered = 0;
d->status = 0;
uwsgi.shared->daemons_cnt++;
ret = 0;
uwsgi_log("registered daemon %s\n", command);
}
uwsgi_unlock(uwsgi.daemon_table_lock);
return ret;
}
void spawn_daemon(struct uwsgi_daemon *ud) {
char *argv[64];
@@ -2298,7 +2304,11 @@ void spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_error("prctl()");
}
#endif
memcpy(ud->tmp_command, ud->command, 0xff);
// free the old area
if (ud->tmp_command) free(ud->tmp_command);
ud->tmp_command = uwsgi_str(ud->command);
a = strtok(ud->tmp_command, " ");
if (a) {
@@ -2318,14 +2328,15 @@ void spawn_daemon(struct uwsgi_daemon *ud) {
argv[cnt] = NULL;
if (throttle) {
uwsgi_log_verbose("throttling %s for %d seconds\n", argv[0], throttle);
uwsgi_log("[uwsgi-daemons] throttling \"%s\" (%s) for %d seconds\n", ud->command, argv[0], throttle);
sleep(throttle);
}
uwsgi_log_verbose("running %s\n", argv[0]);
uwsgi_log("[uwsgi-daemons] spawning \"%s\" (%s)\n", ud->command, argv[0]);
if (execvp(argv[0], argv)) {
uwsgi_error("execvp()");
}
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\" (%s)\n", ud->command, argv[0]);
// never here;
exit(1);
@@ -2351,6 +2362,12 @@ int uwsgi_num2str2n(int num, char *ptr, int size) {
return snprintf(ptr, size, "%d", num);
}
int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
int ret = snprintf(ptr, size, "%llu", num);
if (ret < 0) return 0;
return ret;
}
int is_unix(char *socket_name, int len) {
int i;
for (i = 0; i < len; i++) {
@@ -2638,6 +2655,39 @@ char *uwsgi_netstring(char *buf, size_t len, char **netstring, size_t *netstring
return NULL;
}
struct uwsgi_daemon *uwsgi_daemon_new(struct uwsgi_daemon **ud, char *command) {
struct uwsgi_daemon *uwsgi_ud = *ud, *old_ud;
if (!uwsgi_ud) {
*ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = *ud;
}
else {
while(uwsgi_ud) {
old_ud = uwsgi_ud;
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
uwsgi_ud->command = command;
uwsgi_ud->tmp_command = NULL;
uwsgi_ud->pid = 0;
uwsgi_ud->status = 0;
uwsgi_ud->registered = 0;
uwsgi_ud->next = NULL;
uwsgi_ud->respawns = 0;
uwsgi_ud->last_spawn = 0;
uwsgi.daemons_cnt++;
return uwsgi_ud;
}
struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **dd, char *key, int keylen, char *val, int vallen) {
struct uwsgi_dyn_dict *uwsgi_dd = *dd, *old_dd;
@@ -2663,6 +2713,7 @@ struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **dd, char *key,
uwsgi_dd->value = val;
uwsgi_dd->vallen = vallen;
uwsgi_dd->hits = 0;
uwsgi_dd->status = 0;
uwsgi_dd->next = NULL;
return uwsgi_dd;
@@ -3145,12 +3196,24 @@ static struct uwsgi_cap uwsgi_cap_list[] = {
{ "sys_time", CAP_SYS_TIME},
{ "sys_tty_config", CAP_SYS_TTY_CONFIG},
{ "mknod", CAP_MKNOD},
#ifdef CAP_LEASE
{ "lease", CAP_LEASE},
#endif
#ifdef CAP_AUDIT_WRITE
{ "audit_write", CAP_AUDIT_WRITE},
#endif
#ifdef CAP_AUDIT_CONTROL
{ "audit_control", CAP_AUDIT_CONTROL},
#endif
#ifdef CAP_SETFCAP
{ "setfcap", CAP_SETFCAP},
#endif
#ifdef CAP_MAC_OVERRIDE
{ "mac_override", CAP_MAC_OVERRIDE},
#endif
#ifdef CAP_MAC_ADMIN
{ "mac_admin", CAP_MAC_ADMIN},
#endif
#ifdef CAP_SYSLOG
{ "syslog", CAP_SYSLOG},
#endif
+187 -480
View File
File diff suppressed because it is too large Load Diff
+101 -38
View File
@@ -11,6 +11,7 @@ extern "C" {
#define UMAX64_STR "18446744073709551616"
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1);
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_req_error(x) if (wsgi_req->uri_len > 0 && wsgi_req->method_len > 0 && wsgi_req->remote_addr_len > 0) uwsgi_log_verbose("%s: %s [%s line %d] during %.*s %.*s (%.*s)\n", x, strerror(errno), __FILE__, __LINE__,\
@@ -38,7 +39,8 @@ extern "C" {
#define MAX_GENERIC_PLUGINS 64
#define MAX_RPC 64
#define MAX_GATEWAYS 64
#define MAX_DAEMONS 8
#define MAX_TIMERS 64
#define MAX_PROBES 64
#define MAX_CRONS 64
#ifndef UWSGI_LOAD_EMBEDDED_PLUGINS
@@ -272,20 +274,6 @@ struct uwsgi_config_template {
struct uwsgi_config_template *next;
};
struct uwsgi_static_map {
char *mountpoint;
int mountpoint_len;
char *document_root;
int document_root_len;
char *orig_document_root;
int orig_document_root_len;
struct uwsgi_static_map *next;
};
struct uwsgi_string_list {
char *value;
@@ -302,6 +290,7 @@ struct uwsgi_dyn_dict {
int vallen;
uint64_t hits;
int status;
struct uwsgi_dyn_dict *prev;
struct uwsgi_dyn_dict *next;
@@ -338,8 +327,8 @@ struct uwsgi_gateway {
// Daemons are external processes maintained by the master
struct uwsgi_daemon {
char command[0xff];
char tmp_command[0xff];
char *command;
char *tmp_command;
pid_t pid;
uint64_t respawns;
time_t born;
@@ -347,6 +336,8 @@ struct uwsgi_daemon {
int status;
int registered;
//int pipe[2];
struct uwsgi_daemon *next;
};
struct uwsgi_queue_header {
@@ -541,6 +532,9 @@ struct uwsgi_opt {
#define LONG_ARGS_SIGNAL_BUFSIZE 17162
#define LONG_ARGS_SIGNAL 17163
#define LONG_ARGS_KSM 17164
#define LONG_ARGS_LOGFILE_CHMOD 17165
#define LONG_ARGS_SUBSCRIBE_FREQ 17166
#define LONG_ARGS_SUBSCR_TOLERANCE 17167
#define UWSGI_OK 0
@@ -662,6 +656,7 @@ struct uwsgi_plugin {
int (*request) (struct wsgi_request *);
void (*after_request) (struct wsgi_request *);
void (*init_apps) (void);
void (*preinit_apps) (void);
void (*fixup) (void);
void (*master_fixup) (int);
void (*master_cycle) (void);
@@ -683,7 +678,7 @@ struct uwsgi_plugin {
int (*spooler) (char *, char *, uint16_t, char *, size_t);
uint16_t(*rpc) (void *, uint8_t, char **, char *);
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
void (*jail) (int (*)(void *), char **);
@@ -974,6 +969,34 @@ struct uwsgi_signal_rb_timer {
struct uwsgi_rb_timer *uwsgi_rb_timer;
};
struct uwsgi_signal_probe {
int (*func)(int, struct uwsgi_signal_probe *);
char args[1024];
int fd;
int state;
int bad;
int last_event;
void *data;
uint64_t cycles;
int timeout;
int freq;
int registered;
uint8_t sig;
};
struct uwsgi_probe {
char *name;
int (*func)(int, struct uwsgi_signal_probe *);
struct uwsgi_probe *next;
};
struct uwsgi_server {
@@ -1163,13 +1186,17 @@ struct uwsgi_server {
// static file serving
char *check_static;
size_t check_static_len;
int file_serve_mode;
int build_mime_dict;
char *mime_file;
struct uwsgi_static_map *static_maps;
struct uwsgi_probe *probes;
struct uwsgi_daemon *daemons;
int daemons_cnt;
struct uwsgi_dyn_dict *static_maps;
struct uwsgi_dyn_dict *check_static;
struct uwsgi_dyn_dict *mimetypes;
char *logfile;
@@ -1328,6 +1355,7 @@ struct uwsgi_server {
int chmod_socket;
char *chown_socket;
mode_t chmod_socket_value;
mode_t chmod_logfile_value;
int listen_queue;
#ifdef UWSGI_XML
@@ -1510,6 +1538,7 @@ struct uwsgi_server {
void *signal_table_lock;
void *fmon_table_lock;
void *timer_table_lock;
void *probe_table_lock;
void *rb_timer_table_lock;
void *cron_table_lock;
void *rpc_table_lock;
@@ -1518,17 +1547,19 @@ struct uwsgi_server {
void *spooler_lock;
#endif
void *daemon_table_lock;
char *startup_daemons[MAX_DAEMONS];
int startup_daemons_cnt;
// subscription client
int subscribe_freq;
int subscription_tolerance;
struct uwsgi_string_list *subscriptions;
#ifdef __linux__
#ifdef MADV_MERGEABLE
int linux_ksm;
int ksm_buffer_size;
char *ksm_mappings_last;
char *ksm_mappings_current;
size_t ksm_mappings_last_size;
size_t ksm_mappings_current_size;
#endif
#endif
@@ -1548,6 +1579,7 @@ struct uwsgi_lb_group {
struct uwsgi_signal_entry {
int wid;
uint8_t modifier1;
char receiver[64];
void *handler;
@@ -1659,10 +1691,13 @@ struct uwsgi_shared {
struct uwsgi_fmon files_monitored[64];
int files_monitored_cnt;
struct uwsgi_timer timers[64];
struct uwsgi_signal_probe probes[MAX_PROBES];
int probes_cnt;
struct uwsgi_timer timers[MAX_TIMERS];
int timers_cnt;
struct uwsgi_signal_rb_timer rb_timers[64];
struct uwsgi_signal_rb_timer rb_timers[MAX_TIMERS];
int rb_timers_cnt;
struct uwsgi_rpc rpc_table[MAX_RPC];
@@ -1670,12 +1705,10 @@ struct uwsgi_shared {
int worker_log_pipe[2];
struct uwsgi_daemon daemons[MAX_DAEMONS];
int daemons_cnt;
#ifdef __linux__
struct tcp_info ti;
#endif
uint64_t load;
struct uwsgi_cron cron[MAX_CRONS];
int cron_cnt;
};
@@ -1717,6 +1750,7 @@ struct uwsgi_worker {
uint64_t respawn_count;
uint64_t requests;
uint64_t delta_requests;
uint64_t failed_requests;
time_t harakiri;
@@ -1854,7 +1888,7 @@ uint64_t uwsgi_swap64(uint64_t);
#endif
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t, char *, char *, uint16_t);
ssize_t send_udp_message(uint8_t, uint8_t, char *, char *, uint16_t);
#endif
int uwsgi_parse_packet(struct wsgi_request *, int);
@@ -2069,11 +2103,12 @@ void uwsgi_route_signal(uint8_t);
int uwsgi_start(void *);
int uwsgi_register_rpc(char *, uint8_t, uint8_t, void *);
uint16_t uwsgi_rpc(char *, uint8_t, char **, char *);
uint16_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
char *uwsgi_cheap_string(char *, int);
int uwsgi_parse_array(char *, uint16_t, char **, uint8_t *);
int uwsgi_parse_array(char *, uint16_t, char **, uint16_t *, uint8_t *);
void log_syslog(char *);
@@ -2108,7 +2143,6 @@ ssize_t fcgi_send_record(int, uint8_t, uint16_t, char *);
ssize_t fcgi_send_param(int, char *, uint16_t, char *, uint16_t);
uint16_t fcgi_get_record(int, char *);
int uwsgi_attach_daemon(char *);
void spawn_daemon(struct uwsgi_daemon *);
void emperor_loop(void);
@@ -2184,6 +2218,9 @@ struct uwsgi_subscribe_req {
uint8_t modifier1;
uint8_t modifier2;
uint64_t cores;
uint64_t load;
};
#ifndef _NO_UWSGI_RB
@@ -2251,7 +2288,7 @@ int uwsgi_netlink_del(char *);
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *);
char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, char *, uint16_t);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
inline int uwsgi_starts_with(char *, int, char *, int);
#ifdef __sun__
@@ -2425,6 +2462,12 @@ struct uwsgi_subscribe_node {
uint64_t requests;
uint64_t transferred;
int death_mark;
uint64_t reference;
uint64_t cores;
uint64_t load;
uint64_t failcnt;
struct uwsgi_subscribe_slot *slot;
struct uwsgi_subscribe_node *next;
@@ -2455,8 +2498,9 @@ void mule_send_msg(int, char *, size_t);
void create_signal_pipe(int *);
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t, int);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_node *);
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_node *);
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_req *, int);
ssize_t uwsgi_mule_get_msg(int, int, char *, size_t, int);
@@ -2466,6 +2510,25 @@ void uwsgi_add_app(int, uint8_t, char *, int);
int uwsgi_signal_send(int, uint8_t);
int uwsgi_remote_signal_send(char *, uint8_t);
void uwsgi_configure(void);
void cluster_setup(void);
void manage_cluster_announce(char *, uint16_t, char *, uint16_t, void *);
int uwsgi_read_response(int, struct uwsgi_header *, int, char **);
char *uwsgi_simple_file_read(char *);
void uwsgi_send_subscription(char *, char *, size_t , uint8_t, uint8_t , uint8_t);
void uwsgi_subscribe(char *, uint8_t);
struct uwsgi_daemon *uwsgi_daemon_new(struct uwsgi_daemon **, char *);
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **, char *, int (*)(int, struct uwsgi_signal_probe *));
int uwsgi_add_probe(uint8_t sig, char *, char *, int, int);
int uwsgi_is_bad_connection(int);
int uwsgi_long2str2n(unsigned long long, char *, int);
#ifdef __linux__
#ifdef MADV_MERGEABLE
void uwsgi_linux_ksm_map(void);
+20 -4
View File
@@ -99,7 +99,7 @@ def compile(cflags, objfile, srcfile):
except:
pass
cmdline = "%s -c %s -o %s %s" % (GCC, cflags, objfile, srcfile)
print(cmdline)
print("[%s] %s" % (GCC, objfile))
ret = os.system(cmdline)
if ret != 0:
sys.exit(1)
@@ -126,6 +126,8 @@ def build_uwsgi(uc):
cflags.append(epc)
cflags.append(eplc)
print("configured CFLAGS: %s" % ' '.join(cflags))
print("*** uWSGI compiling server core ***")
for file in gcc_list:
objfile = file
@@ -237,17 +239,25 @@ class uConf(object):
self.config.read(filename)
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify', 'mule', 'subscription',
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'cluster', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
self.gcc_list.append('proto/http')
self.gcc_list.append('proto/fastcgi')
self.include_path = []
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
if uwsgi_os == 'Linux':
self.gcc_list.append('lib/linux_ns')
self.gcc_list.append('lib/netlink')
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
try:
lk_ver = uwsgi_os_k.split('.')
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]) <= 9:
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')
except:
pass
try:
gcc_version = str(spcall("%s -dumpversion" % GCC))
@@ -799,11 +809,16 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
try:
p_cflags.remove('-Winline')
except:
pass
#for ofile in up.OBJ_LIST:
# gcc_list.insert(0,ofile)
gccline = "%s -fPIC %s -o %s.so %s %s %s %s" % (GCC, shared_flag, plugin_dest, ' '.join(p_cflags), ' '.join(p_ldflags), ' '.join(gcc_list), ' '.join(p_libs) )
print(gccline)
print("[%s] %s.so" % (GCC, plugin_dest))
ret = os.system(gccline)
if ret != 0:
@@ -854,6 +869,7 @@ if __name__ == "__main__":
name = sys.argv[4]
except:
name = None
print("*** uWSGI building and linking plugin %s ***" % sys.argv[2] )
build_plugin(sys.argv[2], uc, cflags, ldflags, libs, name)
elif cmd == '--clean':
os.system("rm -f *.o")
+39 -23
View File
@@ -8,15 +8,14 @@ except:
if uwsgi.masterpid() == 0:
raise Exception("you have to enable the uWSGI master process to use this module")
if uwsgi.opt.get('lazy'):
raise Exception("uWSGI lazy mode is not supported by this module")
raise Exception(
"you have to enable the uWSGI master process to use this module")
spooler_functions = {}
mule_functions = {}
postfork_chain = []
def get_free_signal():
for signum in xrange(0, 256):
if not uwsgi.signal_registered(signum):
@@ -24,12 +23,14 @@ def get_free_signal():
raise Exception("No free uwsgi signal available")
def manage_spool_request(vars):
ret = spooler_functions[vars['ud_spool_func']](vars)
if not vars.has_key('ud_spool_ret'):
if not 'ud_spool_ret' in vars:
return ret
return int(vars['ud_spool_ret'])
def postfork_chain_hook():
for f in postfork_chain:
f()
@@ -37,10 +38,12 @@ def postfork_chain_hook():
uwsgi.spooler = manage_spool_request
uwsgi.post_fork_hook = postfork_chain_hook
class postfork(object):
def __init__(self, f):
postfork_chain.append(f)
class spool(object):
def spool(self, *args, **kwargs):
@@ -53,12 +56,14 @@ class spool(object):
return uwsgi.spool(arguments)
def __init__(self, f):
if not uwsgi.opt.has_key('spooler'):
raise Exception("you have to enable the uWSGI spooler to use the @spool decorator")
if not 'spooler' in uwsgi.opt:
raise Exception(
"you have to enable the uWSGI spooler to use @spool decorator")
self.f = f
spooler_functions[f.__name__] = self.f
self.f.spool = self.spool
self.base_dict = {'ud_spool_func':self.f.__name__}
self.base_dict = {'ud_spool_func': self.f.__name__}
class spoolforever(spool):
@@ -71,6 +76,7 @@ class spoolforever(spool):
arguments.update(kwargs)
return uwsgi.spool(arguments)
class spoolraw(spool):
def spool(self, *args, **kwargs):
@@ -97,15 +103,13 @@ class mulefunc(object):
uwsgi.mule_msg(pickle.dumps(
{
'service': 'uwsgi_mulefunc',
'func':self.fname,
'func': self.fname,
'args': args,
'kwargs': kwargs
}
), self.mule)
def __call__(self, *args, **kwargs):
if not self.fname:
self.fname = args[0].__name__
mule_functions[self.fname] = args[0]
@@ -117,7 +121,7 @@ class mulefunc(object):
def mule_msg_dispatcher(message):
msg = pickle.loads(message)
if msg['service'] == 'uwsgi_mulefunc':
return mule_functions[msg['func']](*msg['args'],**msg['kwargs'])
return mule_functions[msg['func']](*msg['args'], **msg['kwargs'])
uwsgi.mule_msg_hook = mule_msg_dispatcher
@@ -131,12 +135,13 @@ class rpc(object):
uwsgi.register_rpc(self.name, f)
return f
class farm_loop(object):
def __init__(self, f, farm):
self.f = f
self.farm = farm
def __call__(self):
if uwsgi.mule_id() == 0:
return
@@ -147,6 +152,7 @@ class farm_loop(object):
if message:
self.f(message)
class farm(object):
def __init__(self, name=None, **kwargs):
@@ -155,6 +161,7 @@ class farm(object):
def __call__(self, f):
postfork_chain.append(farm_loop(f, self.name))
class mule_brain(object):
def __init__(self, f, num):
@@ -165,13 +172,14 @@ class mule_brain(object):
if uwsgi.mule_id() == self.num:
self.f()
class mule_brainloop(mule_brain):
def __call__(self):
if uwsgi.mule_id() == self.num:
while True:
self.f()
class mule(object):
def __init__(self, num):
@@ -180,10 +188,12 @@ class mule(object):
def __call__(self, f):
postfork_chain.append(mule_brain(f, self.num))
class muleloop(mule):
def __call__(self, f):
postfork_chain.append(mule_brainloop(f, self.num))
class mulemsg_loop(object):
def __init__(self, f, num):
@@ -198,6 +208,7 @@ class mulemsg_loop(object):
if message:
self.f(message)
class mulemsg(object):
def __init__(self, num):
self.num = num
@@ -205,28 +216,31 @@ class mulemsg(object):
def __call__(self, f):
postfork_chain.append(mulemsg_loop(f, self.num))
class signal(object):
def __init__(self, num, **kwargs):
self.num = num
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
return f
class timer(object):
def __init__(self, secs, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.secs = secs
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_timer(self.num, self.secs)
return f
class cron(object):
def __init__(self, minute, hour, day, month, dayweek, **kwargs):
@@ -236,39 +250,41 @@ class cron(object):
self.day = day
self.month = month
self.dayweek = dayweek
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_cron(self.num, self.minute, self.hour, self.day, self.month, self.dayweek)
uwsgi.add_cron(self.num, self.minute, self.hour,
self.day, self.month, self.dayweek)
return f
class rbtimer(object):
def __init__(self, secs, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.secs = secs
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_rb_timer(self.num, self.secs)
return f
class filemon(object):
def __init__(self, fsobj, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.fsobj = fsobj
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_file_monitor(self.num, self.fsobj)
return f
class erlang(object):
def __init__(self, name):
@@ -278,6 +294,7 @@ class erlang(object):
uwsgi.erlang_register_process(self.name, f)
return f
class lock(object):
def __init__(self, f):
self.f = f
@@ -292,6 +309,7 @@ class lock(object):
finally:
uwsgi.unlock()
class thread(object):
def __init__(self, f):
@@ -302,5 +320,3 @@ class thread(object):
t.daemon = True
t.start()
return self.f
+8 -2
View File
@@ -59,7 +59,10 @@ def application(env, start_response):
uwsgi.setprocname("worker %d managed %d requests" % (uwsgi.worker_id(), req))
gc.collect(2)
try:
gc.collect(2)
except:
pass
if DEBUG:
print(env['wsgi.input'].fileno())
@@ -71,7 +74,10 @@ def application(env, start_response):
if DEBUG:
print(env['wsgi.input'].fileno())
gc.collect(2)
try:
gc.collect(2)
except:
pass
if DEBUG:
print(len(gc.get_objects()))
+12
View File
@@ -154,6 +154,10 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
@@ -170,6 +174,8 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
@@ -180,6 +186,12 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
}
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;