mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-06 05:31:44 +00:00
Merge branch 'master' of https://github.com/unbit/uwsgi
This commit is contained in:
+4
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ struct uwsgi_perl {
|
||||
int shell_oneshot;
|
||||
|
||||
CV *spooler;
|
||||
|
||||
int no_plack;
|
||||
};
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
|
||||
+46
-37
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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"]
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user