This commit is contained in:
Unbit
2014-03-08 05:44:05 +01:00
16 changed files with 404 additions and 235 deletions
+4 -4
View File
@@ -18,18 +18,18 @@ void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
if (msg[len-1] != '\n') {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
uwsgi_log_verbose("ALARM: %s %.*s\n", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s\n", len, msg);
uwsgi_log_verbose("ALARM: %.*s\n", len, msg);
}
}
else {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
uwsgi_log_verbose("ALARM: %s %.*s", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s", len, msg);
uwsgi_log_verbose("ALARM: %.*s", len, msg);
}
}
}
+18
View File
@@ -387,6 +387,23 @@ end:
}
static int uwsgi_async_wait_milliseconds_hook(int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
timeout = timeout / 1000;
if (!timeout) timeout = 1;
async_add_timeout(wsgi_req, timeout);
wsgi_req->async_force_again = 1;
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
return -1;
}
void async_loop() {
if (uwsgi.async < 2) {
@@ -414,6 +431,7 @@ void async_loop() {
uwsgi.wait_write_hook = async_wait_fd_write;
uwsgi.wait_read_hook = async_wait_fd_read;
uwsgi.wait_read2_hook = async_wait_fd_read2;
uwsgi.wait_milliseconds_hook = uwsgi_async_wait_milliseconds_hook;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
+80 -20
View File
@@ -39,6 +39,65 @@ struct uwsgi_emperor_blacklist_item {
struct uwsgi_emperor_blacklist_item *emperor_blacklist;
/*
this should be placed in core/socket.c but we realized it was needed
only after 2.0 so we cannot change uwsgi.h
basically it is a stripped down bind_to_tcp/bind_to_unix with rollback
*/
static int on_demand_bind(char *socket_name) {
union uwsgi_sockaddr us;
socklen_t addr_len = sizeof(struct sockaddr_un);
char *is_tcp = strchr(socket_name, ':');
int af_family = is_tcp ? AF_INET : AF_UNIX;
int fd = socket(af_family, SOCK_STREAM, 0);
if (fd < 0) return -1;
memset(&us, 0, sizeof(union uwsgi_sockaddr));
if (is_tcp) {
int reuse = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
goto error;
}
us.sa_in.sin_family = AF_INET;
us.sa_in.sin_port = htons(atoi(is_tcp+1));
*is_tcp = 0;
us.sa_in.sin_addr.s_addr = inet_addr(socket_name);
*is_tcp = ':';
addr_len = sizeof(struct sockaddr_in);
}
else {
if (unlink(socket_name) != 0 && errno != ENOENT) {
goto error;
}
us.sa_un.sun_family = AF_UNIX;
memcpy(us.sa_un.sun_path, socket_name, UMIN(strlen(socket_name), 102));
addr_len = strlen(socket_name) + ((void *) us.sa_un.sun_path - (void *) &us.sa_un);
}
if (bind(fd, (struct sockaddr *) &us, addr_len) != 0) {
goto error;
}
if (!is_tcp) {
if (chmod(socket_name, 0666)) {
goto error;
}
}
if (listen(fd, uwsgi.listen_queue) != 0) {
goto error;
}
return fd;
error:
close(fd);
return -1;
}
struct uwsgi_emperor_blacklist_item *uwsgi_emperor_blacklist_check(char *id) {
struct uwsgi_emperor_blacklist_item *uebi = emperor_blacklist;
while (uebi) {
@@ -157,7 +216,7 @@ static char *emperor_check_on_demand_socket(char *filename) {
if (fd < 0) return NULL;
char *ret = uwsgi_read_fd(fd, &len, 1);
close(fd);
// change the first non prinabel character to 0
// change the first non printable character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
@@ -629,6 +688,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
free(c_ui->socket_name);
}
if (c_ui->on_demand_fd != -1) {
close(c_ui->on_demand_fd);
}
free(c_ui);
}
@@ -637,8 +700,10 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("emperor_stop()/write()");
if (c_ui->pid != -1) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("emperor_stop()/write()");
}
}
c_ui->status = 1;
@@ -797,18 +862,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
// ok here we check if we need to bind to the specified socket or continue with the activation
if (socket_name) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
n_ui->on_demand_fd = on_demand_bind(socket_name);
if (n_ui->on_demand_fd < 0) {
uwsgi_error("emperor_add()/bind()");
free(n_ui);
@@ -1743,12 +1797,18 @@ void emperor_loop() {
break;
}
}
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
ui_current->cursed_at = now;
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill");
else if (ui_current->cursed_at > 0) {
if (ui_current->pid == -1) {
emperor_del(ui_current);
break;
}
else if (now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
ui_current->cursed_at = now;
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill");
}
break;
}
break;
}
}
+3
View File
@@ -967,6 +967,7 @@ int uwsgi_read_nb(int fd, char *buf, size_t remains, int timeout) {
ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
int ret;
errno = 0;
ssize_t rlen = read(fd, buf, len);
if (rlen > 0) {
return rlen;
@@ -977,8 +978,10 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
}
return -1;
wait:
errno = 0;
ret = uwsgi.wait_read_hook(fd, timeout);
if (ret > 0) {
errno = 0;
rlen = read(fd, buf, len);
if (rlen > 0) {
return rlen;
+5
View File
@@ -190,6 +190,11 @@ static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, ui
}
if (!uwsgi_strncmp(key, key_len, "at", 2)) {
// at can be a float...
char *dot = memchr(value, '.', value_len);
if (dot) {
value_len = dot - value;
}
sr->at = uwsgi_str_num(value, value_len);
return;
}
+214 -169
View File
@@ -2,6 +2,8 @@
extern struct uwsgi_server uwsgi;
#define kill_on_error if (!uc.do_not_kill_on_error) { if (kill(cgi_pid, SIGKILL)) uwsgi_error("kill()");}
struct uwsgi_cgi {
struct uwsgi_dyn_dict *mountpoint;
struct uwsgi_dyn_dict *helpers;
@@ -16,6 +18,8 @@ struct uwsgi_cgi {
int has_mountpoints;
struct uwsgi_dyn_dict *default_cgi;
int path_info;
int do_not_kill_on_error;
int async_max_attempts;
} uc ;
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
@@ -62,6 +66,9 @@ struct uwsgi_option uwsgi_cgi_options[] = {
{"cgi-path-info", no_argument, 0, "disable PATH_INFO management in cgi scripts", uwsgi_opt_true, &uc.path_info, 0},
{"cgi-do-not-kill-on-error", no_argument, 0, "do not send SIGKILL to cgi script on errors", uwsgi_opt_true, &uc.do_not_kill_on_error, 0},
{"cgi-async-max-attempts", no_argument, 0, "max waitpid() attempts in cgi async mode (default 10)", uwsgi_opt_set_int, &uc.async_max_attempts, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -179,118 +186,154 @@ static char *uwsgi_cgi_get_helper(char *filename) {
}
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
size_t i;
/*
start reading each line until Status or Location are found
-1 error
0 not found
1 found
*/
static int uwsgi_cgi_check_status(struct wsgi_request *wsgi_req, char *buf, size_t len) {
char *key = buf, *value = NULL;
size_t header_size = 0;
int status_sent = 0;
size_t i;
// Search for Status/Location headers
for(i=0;i<len;i++) {
// end of a line
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
// Default status
// end of a line
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
// Default status
#ifdef UWSGI_DEBUG
uwsgi_log("setting default Status header\n");
#endif
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
break;
return 1;
}
// invalid header
else if (value == NULL) {
return -1;
}
header_size = (buf+i) - key;
// security check
if (buf+i > buf) {
if ((buf[i-1]) == '\r') {
header_size--;
}
// invalid header
else if (value == NULL) return -1;
header_size = (buf+i) - key;
// security check
if (buf+i > buf) {
// remove \r
if ((buf[i-1]) == '\r') {
header_size--;
}
}
// enough space for Status ?
if (header_size >= 11) {
// "Status: NNN"
if (!strncasecmp("Status: ", key, 8)) {
#ifdef UWSGI_DEBUG
uwsgi_log("found Status header: %.*s\n", header_size, key);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
return 1;
}
// Location: X
if (!strncasecmp("Location: ", key, 10)) {
#ifdef UWSGI_DEBUG
uwsgi_log("found Location header: %.*s\n", header_size, key);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
return 1;
}
}
if (header_size >= 11) {
// "Status: NNN"
if (!strncasecmp("Status: ", key, 8)) {
#ifdef UWSGI_DEBUG
uwsgi_log("found Status header: %.*s\n", header_size, key);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
break;
}
// Location: X
if (!strncasecmp("Location: ", key, 10)) {
#ifdef UWSGI_DEBUG
uwsgi_log("found Location header: %.*s\n", header_size, key);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
break;
}
}
key = NULL;
value = NULL;
key = NULL;
value = NULL;
}
else if (buf[i] == ':') {
else if (buf[i] == ':') {
value = buf+i;
}
else if (buf[i] != '\r') {
if (key == NULL) {
key = buf + i;
}
}
}
else if (buf[i] != '\r') {
if (key == NULL) key = buf + i;
}
}
key = buf;
value = NULL;
// no Status/Location found
return 0;
for(i=0;i<len;i++) {
// end of a line
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
i++;
goto send_body;
}
// invalid header
else if (value == NULL) {
return -1;
}
header_size = (buf+i) - key;
// security check
if (buf+i > buf) {
if ((buf[i-1]) == '\r') {
header_size--;
}
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, int fd, char *buf, size_t blen) {
size_t i;
size_t header_size = 0;
int status_sent = 0;
size_t remains = blen;
char *ptr = buf;
size_t len = 0;
while(remains > 0) {
ssize_t rlen = uwsgi_read_true_nb(fd, ptr, remains, uc.timeout);
if (rlen < 0) {
if (!errno) return 1;
return -1;
}
// timed out
if (rlen == 0) return -1;
remains -= rlen;
len += rlen;
ptr += rlen;
// Search for Status/Location headers
if (!status_sent) {
status_sent = uwsgi_cgi_check_status(wsgi_req, buf, len);
if (status_sent < 0) return -1;
// need more data ?
if (status_sent == 0) continue;
}
// send headers
char *key = buf;
char *value = NULL;
for(i=0;i<len;i++) {
// end of a line
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
i++;
goto send_body;
}
// invalid header
else if (value == NULL) {
return -1;
}
header_size = (buf+i) - key;
// security check
if (buf+i > buf) {
if ((buf[i-1]) == '\r') {
header_size--;
}
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("found CGI header: %.*s\n", header_size, key);
uwsgi_log("found CGI header: %.*s\n", header_size, key);
#endif
// Ignore "Status: NNN" header
if (status_sent == 0 && header_size >= 11) {
if (!strncasecmp("Status: ", key, 8)) {
status_sent = 1;
key = NULL;
value = NULL;
continue;
// Ignore "Status: NNN" header
if (header_size >= 11) {
if (!strncasecmp("Status: ", key, 8)) {
key = NULL;
value = NULL;
continue;
}
}
uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
key = NULL;
value = NULL;
}
uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
key = NULL;
value = NULL;
}
else if (buf[i] == ':') {
value = buf+i;
}
else if (buf[i] != '\r') {
if (key == NULL) {
key = buf + i;
else if (buf[i] == ':') {
value = buf+i;
}
else if (buf[i] != '\r') {
if (key == NULL) {
key = buf + i;
}
}
}
}
@@ -592,7 +635,6 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do
int post_pipe[2];
int nargs = 0;
int waitpid_status;
ssize_t len;
int i;
char **argv;
@@ -630,126 +672,96 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do
close(cgi_pipe[1]);
close(post_pipe[0]);
uwsgi_socket_nb(cgi_pipe[0]);
uwsgi_socket_nb(post_pipe[1]);
// ok start sending post data...
size_t remains = wsgi_req->post_cl;
while(remains > 0) {
ssize_t rlen = 0;
char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen);
if (!buf) {
close(post_pipe[1]);
goto clear2;
}
if (buf == uwsgi.empty) break;
// write data to the node
if (uwsgi_write_true_nb(post_pipe[1], buf, rlen, uc.timeout)) {
close(post_pipe[1]);
goto clear2;
}
remains -= rlen;
}
close(post_pipe[1]);
// wait for data
char *headers_buf = uwsgi_malloc(uc.buffer_size);
char *ptr = headers_buf;
remains = uc.buffer_size;
int completed = 0;
while(remains > 0) {
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
if (ret > 0) {
len = read(cgi_pipe[0], ptr, remains);
if (len > 0) {
ptr+=len;
remains -= len;
}
else if (len == 0) {
completed = 1;
break;
}
else {
uwsgi_error("read()");
goto clear;
}
continue;
}
else if (ret == 0) {
uwsgi_log("CGI timeout !!!\n");
goto clear;
}
break;
}
char *buf = uwsgi_malloc(uc.buffer_size);
if (uwsgi_cgi_parse(wsgi_req, headers_buf, uc.buffer_size-remains)) {
uwsgi_log("invalid CGI output !!!\n");
int completed = uwsgi_cgi_parse(wsgi_req, cgi_pipe[0], buf, uc.buffer_size);
if (completed < 0) {
uwsgi_log("invalid CGI response !!!\n");
kill_on_error
goto clear;
}
while (!completed) {
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
if (ret > 0) {
len = read(cgi_pipe[0], headers_buf, uc.buffer_size);
if (len > 0) {
uwsgi_response_write_body_do(wsgi_req, headers_buf, len);
}
// end of output
else if (len == 0) {
break;
}
else {
uwsgi_error("read()");
ssize_t rlen = uwsgi_read_true_nb(cgi_pipe[0], buf, uc.buffer_size, uc.timeout);
if (rlen > 0) {
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
kill_on_error
goto clear;
}
continue;
}
else if (ret == 0) {
uwsgi_log("CGI timeout !!!\n");
goto clear;
}
break;
else if (rlen == 0) {
uwsgi_log("CGI timeout !!!\n");
kill_on_error
goto clear;
}
else {
if (errno) {
uwsgi_req_error("error reading CGI response\n");
kill_on_error
}
goto clear;
}
}
clear:
free(headers_buf);
free(buf);
clear2:
close(cgi_pipe[0]);
close(post_pipe[1]);
// now wait for process exit/death
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
// in async mode we need a trick...
if (uwsgi.async > 1) {
pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG);
if (diedpid < 0) {
uwsgi_error("waitpid()");
}
else if (diedpid == 0) {
// pass the pid of the cgi to async_plagued (the after request hook will clear the process)
wsgi_req->async_plagued = (int) cgi_pid;
}
}
else {
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
return UWSGI_OK;
}
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (post_pipe[0] == i) {
continue;
}
if (wsgi_req->post_file) {
if (fileno(wsgi_req->post_file) == i) {
continue;
}
}
if (i != wsgi_req->fd && i != 2 && i != cgi_pipe[1]) {
close(i);
}
}
// now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1
if (post_pipe[0] != 0) {
dup2(post_pipe[0], 0);
close(post_pipe[0]);
}
#ifdef UWSGI_DEBUG
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
#endif
dup2(post_pipe[0], 0);
close(post_pipe[0]);
dup2(cgi_pipe[1],1);
close(cgi_pipe[1]);
// close all the fd > 2
for(i=3;i<(int)uwsgi.max_fd;i++) {
close(i);
}
// fill cgi env
for(i=0;i<wsgi_req->var_cnt;i++) {
// no need to free the putenv() memory
@@ -913,6 +925,39 @@ clear2:
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_plagued > 0) {
int waitpid_status;
pid_t cgi_pid = (pid_t) wsgi_req->async_plagued;
int max_attempts = uc.async_max_attempts;
if (!max_attempts) max_attempts = 10;
while(max_attempts) {
pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG);
if (diedpid < 0) {
uwsgi_error("waitpid()");
break;
}
else if (diedpid == 0) {
int ret = uwsgi.wait_milliseconds_hook(1000);
if (ret < 0) {
kill_on_error
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
}
else {
break;
}
max_attempts--;
}
if (max_attempts == 0) {
kill_on_error
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
}
log_request(wsgi_req);
}
+5 -2
View File
@@ -20,7 +20,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
try {
// requested fields
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 );
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 << "socket" << 1 );
mongo::BSONObj q = mongo::fromjson(uems->json);
// the connection object (will be automatically destroyed at each cycle)
mongo::DBClientConnection c;
@@ -31,7 +31,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
// run the query
std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p);
while( cursor->more() ) {
while(cursor.get() && cursor->more() ) {
mongo::BSONObj p = cursor->next();
// checking for an empty string is not required, but we reduce the load
@@ -40,6 +40,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
if (strlen(name) == 0) continue;
const char *config = p.getStringField("config");
if (strlen(config) == 0) config = NULL;
time_t vassal_ts = 0;
// ts must be a Date object !!!
@@ -61,6 +62,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
}
const char *socket_name = p.getStringField("socket");
if (strlen(socket_name) == 0) socket_name = NULL;
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
}
@@ -76,6 +78,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
b.append("name", c_ui->name);
mongo::BSONObj q2 = b.obj();
cursor = c.query(uems->collection, q2, 0, 0, &p);
if (!cursor.get()) return;
#ifdef UWSGI_DEBUG
uwsgi_log("JSON: %s\n", q2.toString().c_str());
#endif
+3 -1
View File
@@ -574,6 +574,7 @@ static void mongrel2_register_proto() {
static void mongrel2_connect() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->proto != uwsgi_proto_zeromq_parser) goto next;
uwsgi_sock->ctx = zmq_init(1);
if (!uwsgi_sock->ctx) {
uwsgi_error("mongrel2_connect()/zmq_init()");
@@ -581,7 +582,7 @@ static void mongrel2_connect() {
}
char *responder = strchr(uwsgi_sock->name, ',');
if (!responder) {
uwsgi_log("invalid zeromq address\n");
uwsgi_log("invalid zeromq address: %s\n", uwsgi_sock->name);
exit(1);
}
uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0);
@@ -653,6 +654,7 @@ static void mongrel2_connect() {
#else
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
#endif
next:
uwsgi_sock = uwsgi_sock->next;
}
}
+2
View File
@@ -65,6 +65,8 @@ struct uwsgi_perl {
int shell_oneshot;
CV *spooler;
int no_plack;
};
void init_perl_embedded_module(void);
+46 -37
View File
@@ -313,9 +313,6 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
size_t size;
char *buf = uwsgi_open_and_read(app_name, &size, 1, NULL);
if (uwsgi_file_exists(app_name)) {
// prepare for $0 (if the file is local)
uperl.embedding[1] = app_name;
@@ -368,38 +365,30 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
uperl.tmp_current_i = i;
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = app_name;
if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
}
else {
if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
// We need to initialize the interpreter to execute
// our xs_init hook, but we're *not* calling it with
// uperl.embedding as an argument so we won't execute
// BEGIN blocks in app_name twice.
{
char *perl_init_arg[] = { "", "-e", "0" };
if (perl_parse(interpreters[i], xs_init, 3, perl_init_arg, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
}
}
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
char *local_lib_use = uwsgi_concat3("use local::lib qw(", uperl.locallib, ");");
perl_eval_pv(local_lib_use, 1);
free(local_lib_use);
}
perl_eval_pv("use IO::Handle;", 1);
perl_eval_pv("use IO::File;", 1);
perl_eval_pv("use IO::Socket;", 1);
perl_eval_pv("use Scalar::Util;", 1);
if (!uperl.no_die_catch) {
perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0);
}
if (uperl.argv_items || uperl.argv_item) {
AV *uperl_argv = GvAV(PL_argvgv);
@@ -417,12 +406,32 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
}
}
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(app, app_len));
callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
if (!callables[i]) {
SV *has_plack = NULL;
if (!uperl.no_plack) {
has_plack = perl_eval_pv("use Plack::Util;", 0);
}
if (!has_plack || SvTRUE(ERRSV)) {
if (!uperl.no_plack) {
uwsgi_log("Plack::Util is not installed, using \"do\" instead of \"load_psgi\"\n");
}
char *code = uwsgi_concat3("my $app = do '", app_name, "'; if ( !$app && ( my $error = $@ || $! )) { die $error; }; $app");
callables[i] = perl_eval_pv(code, 0);
free(code);
}
else {
char *code = uwsgi_concat3("Plack::Util::load_psgi '", app_name , "';");
callables[i] = perl_eval_pv(code, 0);
free(code);
}
if (!callables[i] || SvTYPE(callables[i]) == SVt_NULL || SvTRUE(ERRSV)) {
if (SvTRUE(ERRSV)) {
uwsgi_log("%s", SvPV_nolen(ERRSV));
}
uwsgi_log("unable to find PSGI function entry point.\n");
// what to do here ? i hope no-one will use threads with dynamic apps...
free(callables);
@@ -430,18 +439,16 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
goto clear;
}
if (!uperl.no_die_catch) {
perl_eval_pv("use Devel::StackTrace; $SIG{__DIE__} = sub { print Devel::StackTrace->new()->as_string() };", 0);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s", SvPV_nolen(ERRSV));
}
}
PERL_SET_CONTEXT(interpreters[0]);
}
free(buf);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s", SvPV_nolen(ERRSV));
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
goto clear;
@@ -504,6 +511,8 @@ void uwsgi_psgi_preinit_apps() {
perl_parse(uperl.main[0], xs_init, 3, uperl.embedding, NULL);
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec) {
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(usl->value, usl->len));
uwsgi_perl_exec(usl->value);
}
}
+4
View File
@@ -44,6 +44,8 @@ struct uwsgi_option uwsgi_perl_options[] = {
{"plshell", optional_argument, 0, "run a perl interactive shell", uwsgi_opt_plshell, NULL, 0},
{"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0},
{"perl-no-plack", no_argument, 0, "force the use of do instead of Plack::Util::load_psgi", uwsgi_opt_true, &uperl.no_plack, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -705,6 +707,8 @@ void uwsgi_perl_post_fork() {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec_post_fork) {
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(usl->value, usl->len));
uwsgi_perl_exec(usl->value);
}
+2 -1
View File
@@ -21,12 +21,13 @@ int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) {
char *content = NULL;
size_t content_len = 0;
if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict;
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
Py_buffer pbuf;
int has_buffer = 0;
#endif
if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict;
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
if (PyObject_CheckBuffer(chunk)) {
if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) {
+4
View File
@@ -93,7 +93,11 @@ ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
ul->configured = 1;
}
#ifdef __APPLE__
syslog(LOG_NOTICE, "%.*s", (int) len, message);
#else
syslog(LOG_INFO, "%.*s", (int) len, message);
#endif
return 0;
}
+4
View File
@@ -1,5 +1,9 @@
use strict;
use warnings;
BEGIN {
die "PANIC: We should only load this once" if ++$main::count_BEGIN > 1;
}
die "PANIC: We should only run this once" if ++$main::count_runs > 1;
uwsgi::register_rpc('hello', sub {
my ($one, $two, $three) = @_;
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2014-02-09'
s.date = '2014-02-26'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+9
View File
@@ -367,6 +367,15 @@ def build_uwsgi(uc, print_only=False, gcll=None):
if len(kv) > 1:
p = kv[1]
p = p.strip()
if p.startswith('http://') or p.startswith('https://') or p.startswith('git://') or p.startswith('ssh://'):
git_dir = p.split('/').pop()
if not os.path.isdir(git_dir):
if os.system('git clone %s' % p) != 0:
sys.exit(1)
else:
if os.system('cd %s ; git pull' % git_dir) != 0:
sys.exit(1)
p = git_dir
path = os.path.abspath(p)
else:
p = kv[0]