mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 07:58:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0af1f800b | ||
|
|
543271e856 | ||
|
|
a1564a44fa | ||
|
|
571029cfd3 | ||
|
|
579eaa630a | ||
|
|
9530c8ffe0 | ||
|
|
0d8690091b | ||
|
|
5b5e3a1ec1 | ||
|
|
869ae5e3ed | ||
|
|
d6dc8d86f8 | ||
|
|
758745be68 | ||
|
|
2adfa56d6a | ||
|
|
a4c728f5df | ||
|
|
5c06341b7f | ||
|
|
6f57902a9b | ||
|
|
a3e118893d | ||
|
|
ff2d3c29d6 | ||
|
|
59a8df85f2 | ||
|
|
e303bd182a | ||
|
|
dcef9a497c | ||
|
|
8d4fd66aaf | ||
|
|
471bd23acf | ||
|
|
ffcef81dd0 | ||
|
|
317df5d06b | ||
|
|
ad7b5efd6f | ||
|
|
891f770724 | ||
|
|
0b6d715982 | ||
|
|
76c2415516 | ||
|
|
3260faca17 | ||
|
|
feb493158c | ||
|
|
a5c1556cb7 | ||
|
|
89e640bdd9 | ||
|
|
3ade8daff8 | ||
|
|
049ea3fbed | ||
|
|
715d26beed | ||
|
|
1f5064094c | ||
|
|
7ed522dc29 | ||
|
|
2086500405 | ||
|
|
8f79409ed1 | ||
|
|
c2a3cd1476 | ||
|
|
e195a5d72c | ||
|
|
c86b757904 | ||
|
|
6800d2ac95 | ||
|
|
90fda2b4bb | ||
|
|
bf7ded9058 | ||
|
|
6615dc3a62 | ||
|
|
c35054085c | ||
|
|
fdf2bd7f96 | ||
|
|
1c10b9dfe1 | ||
|
|
6854394e5c | ||
|
|
78a0d5f432 | ||
|
|
5fe5aa70a4 | ||
|
|
e9c0c6bd0b | ||
|
|
5d12b3dc9c | ||
|
|
169a4b66db | ||
|
|
fbd6329db9 | ||
|
|
69c2e56857 | ||
|
|
18f7d1edd3 | ||
|
|
3f7cd5ff92 | ||
|
|
785e1dbf83 | ||
|
|
bc6acf8d14 | ||
|
|
3a099d0b2e | ||
|
|
f9ad5e4144 | ||
|
|
ce9f6650a0 | ||
|
|
fdeef04343 | ||
|
|
fe72ec82e1 | ||
|
|
fd0f308273 | ||
|
|
f4e9ab43cb | ||
|
|
3a141b523c |
@@ -36,3 +36,5 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
|
||||
@@ -14,3 +14,4 @@ Cal Leeming, Simplicity Media Ltd
|
||||
Luigi Scarso
|
||||
Corey Farwell
|
||||
Charles Duffy
|
||||
Lukas Lalinsky
|
||||
|
||||
@@ -3,7 +3,7 @@ xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
sqlite3 = false
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
sctp = false
|
||||
@@ -27,7 +27,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, rpc, fastrouter, http, ugreen
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = true
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
|
||||
@@ -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
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
require 'stringio'
|
||||
require 'uwsgidsl'
|
||||
|
||||
|
||||
|
||||
signal 17,'mule5' do |signum|
|
||||
end
|
||||
|
||||
puts UWSGI::VERSION
|
||||
puts UWSGI::NUMPROC
|
||||
puts UWSGI::HOSTNAME
|
||||
|
||||
puts UWSGI::OPT.inspect
|
||||
|
||||
timer 2 do |signum|
|
||||
puts "ciao sono un dsl ruby: #{signum} #{UWSGI::OPT.inspect}"
|
||||
end
|
||||
|
||||
timer 1,'mule1' do |signum|
|
||||
puts "1 second elapsed (signum #{signum})"
|
||||
end
|
||||
|
||||
filemon '/tmp' do |signum|
|
||||
puts "/tmp has been modified"
|
||||
end
|
||||
|
||||
cron 5,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
cron 58,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
postfork do
|
||||
puts "fork() called"
|
||||
end
|
||||
|
||||
rpc 'pippo' do
|
||||
"i am an rpc function"
|
||||
end
|
||||
|
||||
rpc 'pluto' do |x,y|
|
||||
"i am another rpc function #{x} #{y}"
|
||||
end
|
||||
|
||||
begin
|
||||
foo_func
|
||||
rescue
|
||||
end
|
||||
|
||||
puts UWSGI.cache_exists('nilkey')
|
||||
puts UWSGI.cache_exists?('nilkey')
|
||||
|
||||
UWSGI.cache_set!('foobar_key?a=1', UWSGI::OPT.inspect)
|
||||
begin
|
||||
puts UWSGI.cache_get(nil)
|
||||
rescue
|
||||
end
|
||||
puts UWSGI.cache_get('foobar_key?a=1')
|
||||
|
||||
|
||||
run lambda { |env|
|
||||
puts env.inspect
|
||||
UWSGI.setprocname("i am the uWSGI rack plugin")
|
||||
UWSGI.signal(17)
|
||||
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World! #{UWSGI.mem.inspect}\n")]
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
@@ -62,6 +63,11 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -1) {
|
||||
via = msg3;
|
||||
}
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
|
||||
@@ -13,6 +13,31 @@ void uwsgi_restore_auto_snapshot(int signum) {
|
||||
|
||||
}
|
||||
|
||||
void suspend_resume_them_all(int signum) {
|
||||
|
||||
int i;
|
||||
int suspend = 0;
|
||||
|
||||
if (uwsgi.workers[0].suspended == 1) {
|
||||
uwsgi_log_verbose("*** (SIGTSTP received) resuming workers ***\n");
|
||||
uwsgi.workers[0].suspended = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** PAUSE (press start to resume, if you do not have a joypad send SIGTSTP) ***\n");
|
||||
suspend = 1;
|
||||
uwsgi.workers[0].suspended = 1;
|
||||
}
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
uwsgi.workers[i].suspended = suspend;
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
if (kill(uwsgi.workers[i].pid, SIGTSTP)) {
|
||||
uwsgi_error("kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void expire_rb_timeouts(struct rb_root *root) {
|
||||
|
||||
time_t current = time(NULL);
|
||||
@@ -42,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;
|
||||
@@ -124,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, modifier1, modifier1_len, cmd);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
@@ -142,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, modifier1, modifier1_len, cmd);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
@@ -166,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), modifier1, modifier1_len, cmd);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
}
|
||||
@@ -208,35 +184,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) {
|
||||
|
||||
@@ -308,6 +255,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
uwsgi.current_time = time(NULL);
|
||||
|
||||
uwsgi_unix_signal(SIGTSTP, suspend_resume_them_all);
|
||||
uwsgi_unix_signal(SIGHUP, grace_them_all);
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_unix_signal(SIGTERM, kill_them_all);
|
||||
@@ -506,10 +454,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;
|
||||
}
|
||||
|
||||
@@ -686,7 +645,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);
|
||||
}
|
||||
|
||||
@@ -695,7 +654,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);
|
||||
}
|
||||
|
||||
@@ -705,9 +664,9 @@ healthy:
|
||||
}
|
||||
|
||||
uwsgi_log( "binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
@@ -763,7 +722,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
|
||||
@@ -814,16 +773,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
|
||||
@@ -876,6 +825,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) {
|
||||
@@ -1137,6 +1102,7 @@ healthy:
|
||||
|
||||
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) {
|
||||
@@ -1147,6 +1113,7 @@ healthy:
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_unlock(uwsgi.timer_table_lock);
|
||||
if (next_iteration) continue;
|
||||
|
||||
|
||||
@@ -1406,6 +1373,14 @@ healthy:
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
if (uwsgi.linux_ksm > 0 && (uwsgi.master_cycles % uwsgi.linux_ksm) == 0) {
|
||||
uwsgi_linux_ksm_map();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
// check for cluster nodes
|
||||
master_check_cluster_nodes();
|
||||
@@ -1415,11 +1390,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;
|
||||
}
|
||||
}
|
||||
@@ -1507,12 +1482,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;
|
||||
@@ -1555,11 +1532,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)) {
|
||||
@@ -1624,14 +1603,7 @@ next:
|
||||
}
|
||||
gettimeofday(&last_respawn, NULL);
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
// close the communication pipe
|
||||
/*
|
||||
close(uwsgi.workers[uwsgi.mywid].pipe[0]);
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.workers[uwsgi.mywid].pipe)) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid)) return 0;
|
||||
|
||||
}
|
||||
|
||||
+37
-40
@@ -96,6 +96,7 @@ int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
if (pid == 0) {
|
||||
signal(SIGWINCH, worker_wakeup);
|
||||
signal(SIGTSTP, worker_wakeup);
|
||||
uwsgi.mywid = wid;
|
||||
uwsgi.mypid = getpid();
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
@@ -103,12 +104,15 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 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;
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
|
||||
uwsgi.workers[uwsgi.mywid].cheaped = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].suspended = 0;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
|
||||
// reset the apps count with a copy from the master
|
||||
@@ -177,32 +181,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);
|
||||
@@ -250,31 +248,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) {
|
||||
@@ -339,12 +332,16 @@ 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);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output,"\"status\": \"cheap\", ");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended) {
|
||||
fprintf(output,"\"status\": \"pause\", ");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
|
||||
@@ -12,6 +12,24 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_mule_handler(void);
|
||||
|
||||
void mule_send_msg(int fd, char *message, size_t len) {
|
||||
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
int so_bufsize = 0;
|
||||
|
||||
if (write(fd, message, len) != (ssize_t) len) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("getsockopt()");
|
||||
}
|
||||
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("mule_send_msg()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule(int id) {
|
||||
|
||||
int i;
|
||||
@@ -233,3 +251,108 @@ struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct
|
||||
return uwsgi_mf;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
|
||||
|
||||
ssize_t len = 0;
|
||||
struct pollfd *mulepoll;
|
||||
int count = 4;
|
||||
int farms_count = 0;
|
||||
uint8_t uwsgi_signal;
|
||||
int i;
|
||||
|
||||
if (uwsgi.muleid == 0) return -1;
|
||||
|
||||
if (manage_signals) count = 2;
|
||||
|
||||
if (!manage_farms) goto next;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
|
||||
}
|
||||
next:
|
||||
|
||||
if (timeout > -1) timeout = timeout*1000;
|
||||
|
||||
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
|
||||
|
||||
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
|
||||
mulepoll[0].events = POLLIN;
|
||||
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
|
||||
mulepoll[1].events = POLLIN;
|
||||
if (count > 2) {
|
||||
mulepoll[2].fd = uwsgi.signal_socket;
|
||||
mulepoll[2].events = POLLIN;
|
||||
mulepoll[3].fd = uwsgi.my_signal_socket;
|
||||
mulepoll[3].events = POLLIN;
|
||||
}
|
||||
|
||||
if (farms_count > 0) {
|
||||
int tmp_cnt = 0;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
|
||||
mulepoll[count+tmp_cnt].events = POLLIN;
|
||||
tmp_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count+farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
}
|
||||
else {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else if (mulepoll[1].revents & POLLIN) {
|
||||
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else {
|
||||
if (count > 2) {
|
||||
int interesting_fd = -1;
|
||||
if (mulepoll[2].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[2].fd;
|
||||
}
|
||||
else if (mulepoll[3].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[3].fd;
|
||||
}
|
||||
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
// read messages in the farm
|
||||
for(i=0;i<farms_count;i++) {
|
||||
if (mulepoll[count+i].revents & POLLIN) {
|
||||
len = read(mulepoll[count+i].fd, message, buffer_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
clear:
|
||||
free(mulepoll);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from uwsgidecorators import *
|
||||
|
||||
@timer(3, target='mule1')
|
||||
def hello_timer(signum):
|
||||
print "3 seconds elapsed"
|
||||
|
||||
|
||||
@mulefunc
|
||||
def conto_fino_a_dieci(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_dieci" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc(2)
|
||||
def conto_fino_a_venti(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_venti" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc('topogigio')
|
||||
def conto_fino_a_trenta(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_trenta" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
|
||||
|
||||
def application(e, sr):
|
||||
conto_fino_a_dieci(1,2,3)
|
||||
conto_fino_a_venti(4,5,6)
|
||||
conto_fino_a_trenta(7,8,9)
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
return "MULE !!!"
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define CARBON_OPT_BASE 178000
|
||||
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
|
||||
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
|
||||
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
|
||||
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
|
||||
|
||||
struct uwsgi_carbon {
|
||||
struct uwsgi_string_list *servers;
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
} u_carbon;
|
||||
|
||||
struct option carbon_options[] = {
|
||||
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
|
||||
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
|
||||
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
|
||||
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
int carbon_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carbon_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case CARBON_OPT_CARBON:
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi_string_new_list(&u_carbon.servers, optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_ID:
|
||||
u_carbon.id = optarg;
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_FREQ:
|
||||
u_carbon.freq = atoi(optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_TIMEOUT:
|
||||
u_carbon.timeout = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void carbon_post_init() {
|
||||
|
||||
int i;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
if (!uwsgi.sockets) return;
|
||||
if (!u_carbon.servers) return;
|
||||
|
||||
while(usl) {
|
||||
uwsgi_log("added carbon server %s\n", usl->value);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (u_carbon.freq < 1) u_carbon.freq = 60;
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
if (u_carbon.id[i] == '.') u_carbon.id[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void carbon_master_cycle() {
|
||||
|
||||
static time_t last_update = 0;
|
||||
char ptr[4096];
|
||||
int rlen, i;
|
||||
int fd;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
|
||||
if (!u_carbon.servers) return ;
|
||||
|
||||
if (last_update == 0) last_update = time(NULL);
|
||||
|
||||
// update
|
||||
if (uwsgi.current_time - last_update >= u_carbon.freq) {
|
||||
while(usl) {
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
if (fd < 0) goto nxt;
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin carbon_plugin = {
|
||||
|
||||
.options = carbon_options,
|
||||
.manage_opt = carbon_opt,
|
||||
|
||||
.master_cycle = carbon_master_cycle,
|
||||
|
||||
.post_init = carbon_post_init,
|
||||
.init = carbon_init,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='carbon'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['carbon']
|
||||
@@ -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;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#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 FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
@@ -71,8 +72,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) {
|
||||
|
||||
@@ -165,41 +179,28 @@ 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->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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -437,15 +438,34 @@ 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->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 {
|
||||
@@ -524,6 +544,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 +581,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;
|
||||
|
||||
+18
-19
@@ -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
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='probeconnect'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['connectprobe']
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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']
|
||||
@@ -300,26 +300,9 @@ void uwsgi_psgi_app() {
|
||||
close(uperl.fd);
|
||||
}
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[id];
|
||||
memset(wi, 0, sizeof(struct uwsgi_app));
|
||||
|
||||
wi->modifier1 = 5;
|
||||
wi->mountpoint = "";
|
||||
wi->mountpoint_len = 0;
|
||||
|
||||
uwsgi_add_app(id, 5, "", 0);
|
||||
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
|
||||
// check if we need to emulate fork() COW
|
||||
int i;
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
|
||||
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -106,9 +106,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 +160,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 +253,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
if (!pyfile) {
|
||||
uwsgi_error_open(real_filename);
|
||||
free(real_filename);
|
||||
fclose(pyfile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1091,8 +1090,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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1263,7 +1288,7 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
|
||||
if (ret) {
|
||||
if (PyString_Check(ret)) {
|
||||
rv = PyString_AsString(ret);
|
||||
rl = strlen(rv);
|
||||
rl = PyString_Size(ret);
|
||||
if (rl <= 0xffff) {
|
||||
memcpy(buffer, rv, rl);
|
||||
Py_DECREF(ret);
|
||||
|
||||
+130
-190
@@ -11,8 +11,6 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
int ret;
|
||||
struct pollfd pfd[2];
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
@@ -23,60 +21,18 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
wsgi_req->sigwait = 1;
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
if (wait_for_specific_signal) {
|
||||
received_signal = uwsgi_signal_wait(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
pfd[0].fd = uwsgi.signal_socket;
|
||||
pfd[0].events = POLLIN;
|
||||
pfd[1].fd = uwsgi.my_signal_socket;
|
||||
pfd[1].events = POLLIN;
|
||||
cycle:
|
||||
ret = poll(pfd, 2, -1);
|
||||
if (ret > 0) {
|
||||
if (pfd[0].revents == POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
if (uwsgi_signal_handler(received_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
|
||||
}
|
||||
wsgi_req->signal_received = received_signal;
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents == POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi_signal_handler(received_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
|
||||
}
|
||||
wsgi_req->signal_received = received_signal;
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
return PyString_FromString("");
|
||||
}
|
||||
@@ -264,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) {
|
||||
@@ -508,23 +483,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;
|
||||
|
||||
@@ -562,22 +520,31 @@ PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
ssize_t rlen;
|
||||
char *remote = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "B:signal", &uwsgi_signal)) {
|
||||
if (!PyArg_ParseTuple(args, "B|s:signal", &uwsgi_signal, &remote)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sending %d to master\n", uwsgi_signal);
|
||||
uwsgi_log("sending signal %d to node %s\n", uwsgi_signal, remote);
|
||||
#endif
|
||||
|
||||
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
|
||||
if (rlen != 1) {
|
||||
uwsgi_error("write()");
|
||||
int ret = uwsgi_remote_signal_send(remote, uwsgi_signal);
|
||||
if (ret == 1) goto clear;
|
||||
if (ret == -1)
|
||||
return PyErr_Format(PyExc_IOError, "unable to deliver signal %d to node %s", uwsgi_signal, remote);
|
||||
if (ret == 0)
|
||||
return PyErr_Format(PyExc_ValueError, "node %s rejected signal %d", remote, uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sending signal %d to master\n", uwsgi_signal);
|
||||
#endif
|
||||
uwsgi_signal_send(uwsgi.signal_socket, uwsgi_signal);
|
||||
}
|
||||
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
@@ -1154,7 +1121,6 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
char *message = NULL;
|
||||
Py_ssize_t message_len = 0;
|
||||
PyObject *mule_obj = NULL;
|
||||
ssize_t len;
|
||||
int fd = -1;
|
||||
int mule_id = -1;
|
||||
|
||||
@@ -1166,10 +1132,7 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "no mule configured");
|
||||
|
||||
if (mule_obj == NULL) {
|
||||
len = write(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
}
|
||||
else {
|
||||
if (PyString_Check(mule_obj)) {
|
||||
@@ -1196,10 +1159,7 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
len = write(fd, message, message_len);
|
||||
if (len < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
mule_send_msg(fd, message, message_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,17 +1171,13 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_mule_get_msg(PyObject * self, PyObject * args, PyObject *kwargs) {
|
||||
|
||||
ssize_t len = 0;
|
||||
// this buffer will be configurable
|
||||
// this buffer is configurable (default 64k)
|
||||
char *message;
|
||||
struct pollfd *mulepoll;
|
||||
int count = 4;
|
||||
int farms_count = 0;
|
||||
uint8_t uwsgi_signal;
|
||||
PyObject *manage_signals = NULL;
|
||||
PyObject *manage_farms = NULL;
|
||||
int buffer_size = 65536;
|
||||
PyObject *py_manage_signals = NULL;
|
||||
PyObject *py_manage_farms = NULL;
|
||||
size_t buffer_size = 65536;
|
||||
int timeout = -1;
|
||||
int i;
|
||||
int manage_signals = 1, manage_farms = 1;
|
||||
|
||||
static char *kwlist[] = {"signals", "buffer_size", "timeout", "farms", NULL};
|
||||
|
||||
@@ -1229,109 +1185,34 @@ PyObject *py_uwsgi_mule_get_msg(PyObject * self, PyObject * args, PyObject *kwar
|
||||
return PyErr_Format(PyExc_ValueError, "you can receive mule messages only in a mule !!!");
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii:mule_get_msg", kwlist, &manage_signals, &manage_farms, &buffer_size, &timeout)) {
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii:mule_get_msg", kwlist, &py_manage_signals, &py_manage_farms, &buffer_size, &timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (manage_signals == Py_None || manage_signals == Py_False) {
|
||||
count = 2;
|
||||
// signals and farms are managed by default
|
||||
if (py_manage_signals == Py_None || py_manage_signals == Py_False) {
|
||||
manage_signals = 0;
|
||||
}
|
||||
|
||||
if (manage_farms == Py_None || manage_farms == Py_False) {
|
||||
goto next;
|
||||
if (py_manage_farms == Py_None || py_manage_farms == Py_False) {
|
||||
manage_farms = 0;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
|
||||
}
|
||||
|
||||
|
||||
next:
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
if (timeout > -1) timeout = timeout*1000;
|
||||
|
||||
message = uwsgi_malloc(buffer_size);
|
||||
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
|
||||
|
||||
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
|
||||
mulepoll[0].events = POLLIN;
|
||||
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
|
||||
mulepoll[1].events = POLLIN;
|
||||
if (count > 2) {
|
||||
mulepoll[2].fd = uwsgi.signal_socket;
|
||||
mulepoll[2].events = POLLIN;
|
||||
mulepoll[3].fd = uwsgi.my_signal_socket;
|
||||
mulepoll[3].events = POLLIN;
|
||||
}
|
||||
|
||||
for(i=0;i<farms_count;i++) {
|
||||
mulepoll[count+i].fd = uwsgi.farms[i].queue_pipe[1];
|
||||
mulepoll[count+i].events = POLLIN;
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count+farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
}
|
||||
else {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else if (mulepoll[1].revents & POLLIN) {
|
||||
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else {
|
||||
if (count > 2) {
|
||||
int interesting_fd = -1;
|
||||
if (mulepoll[2].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[2].fd;
|
||||
}
|
||||
else if (mulepoll[3].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[3].fd;
|
||||
}
|
||||
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<farms_count;i++) {
|
||||
if (mulepoll[count+i].revents & POLLIN) {
|
||||
len = read(mulepoll[count+i].fd, message, buffer_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UWSGI_RELEASE_GIL;
|
||||
len = uwsgi_mule_get_msg(manage_signals, manage_farms, message, buffer_size, timeout) ;
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
goto clear2;
|
||||
free(message);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *msg = PyString_FromStringAndSize(message, len);
|
||||
free(message);
|
||||
free(mulepoll);
|
||||
return msg;
|
||||
clear:
|
||||
UWSGI_GET_GIL;
|
||||
clear2:
|
||||
free(message);
|
||||
free(mulepoll);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_farm_get_msg(PyObject * self, PyObject * args) {
|
||||
@@ -2063,13 +1944,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);
|
||||
@@ -2419,6 +2305,51 @@ PyObject *py_uwsgi_fcgi(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
|
||||
|
||||
char *addr = NULL;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:route", &addr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
int uwsgi_fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (uwsgi_fd < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to connect to host %s", addr);
|
||||
}
|
||||
|
||||
if (uwsgi_send_message(uwsgi_fd, wsgi_req->uh.modifier1, wsgi_req->uh.modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, wsgi_req->poll.fd, wsgi_req->post_cl, 0) < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to send uwsgi request to host %s", addr);
|
||||
}
|
||||
|
||||
// request sent, return the iterator response
|
||||
uwsgi_Iter *ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
|
||||
if (!ui) {
|
||||
uwsgi_log("unable to create uwsgi response object, better to reap the process\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ui->fd = uwsgi_fd;
|
||||
ui->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
ui->close = 1;
|
||||
ui->started = 0;
|
||||
ui->has_cl = 0;
|
||||
ui->sent = 0;
|
||||
ui->size = 0;
|
||||
ui->func = NULL;
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->status = -1;
|
||||
|
||||
return (PyObject *) ui;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *destination = NULL, *pyobj = NULL;
|
||||
@@ -2561,6 +2492,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;
|
||||
@@ -2576,6 +2513,9 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
zero = PyString_FromString("cheap");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended) {
|
||||
zero = PyString_FromString("pause");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
zero = PyString_FromFormat("sig%d",uwsgi.workers[i + 1].signum);
|
||||
@@ -3055,6 +2995,7 @@ PyObject *py_uwsgi_cluster_best_node(PyObject * self, PyObject * args) {
|
||||
|
||||
static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"send_message", py_uwsgi_send_message, METH_VARARGS, ""},
|
||||
{"route", py_uwsgi_route, METH_VARARGS, ""},
|
||||
{"send_multi_message", py_uwsgi_send_multi_message, METH_VARARGS, ""},
|
||||
{"reload", py_uwsgi_reload, METH_VARARGS, ""},
|
||||
{"stop", py_uwsgi_stop, METH_VARARGS, ""},
|
||||
@@ -3082,8 +3023,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, ""},
|
||||
@@ -3091,6 +3030,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, ""},
|
||||
|
||||
@@ -3175,7 +3115,7 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, strlen(key))) {
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -3204,7 +3144,7 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %d bytes", (unsigned long long)uwsgi.cache_blocksize, (int) vallen);
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
@@ -3240,7 +3180,7 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %d bytes", (unsigned long long)uwsgi.cache_blocksize, (int) vallen);
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
@@ -3284,7 +3224,7 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
else if (uwsgi_cache_exists(key, strlen(key))) {
|
||||
else if (uwsgi_cache_exists(key, keylen)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,777 @@
|
||||
#include "uwsgi_rack.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
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);
|
||||
char *name = RSTRING_PTR(rbname);
|
||||
uwsgi_set_processname(name);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mem(VALUE *class) {
|
||||
|
||||
uint64_t rss=0, vsz = 0;
|
||||
VALUE ml = rb_ary_new2(2);
|
||||
|
||||
get_memusage(&rss, &vsz);
|
||||
|
||||
rb_ary_store(ml, 0, LONG2NUM(rss));
|
||||
rb_ary_store(ml, 1, LONG2NUM(vsz));
|
||||
|
||||
return ml;
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_request_id(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_worker_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.mywid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.muleid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_logsize(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.shared->logsize);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int fd = -1;
|
||||
int mule_id = -1;
|
||||
|
||||
if (argc == 0) return Qnil;
|
||||
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
char *message = RSTRING_PTR(argv[0]);
|
||||
size_t message_len = RSTRING_LEN(argv[0]);
|
||||
|
||||
if (uwsgi.mules_cnt < 1) {
|
||||
rb_raise(rb_eRuntimeError, "no mule configured");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
}
|
||||
else {
|
||||
if (TYPE(argv[1]) == T_STRING) {
|
||||
struct uwsgi_farm *uf = get_farm_by_name(RSTRING_PTR(argv[1]));
|
||||
if (uf == NULL) {
|
||||
rb_raise(rb_eRuntimeError, "unknown farm");
|
||||
return Qnil;
|
||||
}
|
||||
fd = uf->queue_pipe[0];
|
||||
}
|
||||
else if (TYPE(argv[1]) == T_FIXNUM) {
|
||||
mule_id = NUM2INT(argv[1]);
|
||||
if (mule_id < 0 && mule_id > uwsgi.mules_cnt) {
|
||||
rb_raise(rb_eRuntimeError, "invalid mule number");
|
||||
return Qnil;
|
||||
}
|
||||
if (mule_id == 0) {
|
||||
fd = uwsgi.shared->mule_queue_pipe[0];
|
||||
}
|
||||
else {
|
||||
fd = uwsgi.mules[mule_id-1].queue_pipe[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eRuntimeError, "invalid mule");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
mule_send_msg(fd, message, message_len);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
|
||||
Check_Type(key, T_SYMBOL);
|
||||
ID key_id = SYM2ID(key);
|
||||
const char *key_name = rb_id2name(key_id);
|
||||
|
||||
if (!strcmp(key_name, "signals")) {
|
||||
rb_ary_store(arg_array, 0, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "farms")) {
|
||||
rb_ary_store(arg_array, 1, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "timeout")) {
|
||||
rb_ary_store(arg_array, 2, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "buffer_size")) {
|
||||
rb_ary_store(arg_array, 3, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int manage_signals = 1;
|
||||
int manage_farms = 1;
|
||||
int timeout = -1;
|
||||
size_t buffer_size = 65536;
|
||||
ssize_t len = 0;
|
||||
char *message;
|
||||
|
||||
if (uwsgi.muleid == 0) {
|
||||
rb_raise(rb_eRuntimeError, "you can receive mule messages only in a mule !!!");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
// 0 = manage_signals
|
||||
// 1 = manage_farms
|
||||
// 2 = timeout
|
||||
// 3 = buffer_size
|
||||
VALUE arg_array = rb_ary_new2(4);
|
||||
Check_Type(argv[0], T_HASH);
|
||||
rb_hash_foreach(argv[0], uwsgi_ruby_hash_mule_callback, arg_array);
|
||||
|
||||
if (rb_ary_entry(arg_array, 0) == Qfalse) {
|
||||
manage_signals = 0;
|
||||
}
|
||||
|
||||
if (rb_ary_entry(arg_array, 1) == Qfalse) {
|
||||
manage_farms = 0;
|
||||
}
|
||||
|
||||
if (TYPE(rb_ary_entry(arg_array,2)) == T_FIXNUM) {
|
||||
timeout = NUM2INT(rb_ary_entry(arg_array,2));
|
||||
}
|
||||
|
||||
if (TYPE(rb_ary_entry(arg_array,3)) == T_FIXNUM || TYPE(rb_ary_entry(arg_array,3)) == T_BIGNUM) {
|
||||
buffer_size = NUM2ULONG(rb_ary_entry(arg_array,3));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message = uwsgi_malloc(buffer_size);
|
||||
|
||||
len = uwsgi_mule_get_msg(manage_signals, manage_farms, message, buffer_size, timeout) ;
|
||||
|
||||
if (len < 0) {
|
||||
free(message);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE msg = rb_str_new(message, len);
|
||||
free(message);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
lock_num = NUM2INT(argv[0]);
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
rb_raise(rb_eRuntimeError, "Invalid lock number");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
lock_num = NUM2INT(argv[0]);
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
rb_raise(rb_eRuntimeError, "Invalid lock number");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_set(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
Check_Type(rbvalue, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
uint64_t keylen = RSTRING_LEN(rbkey);
|
||||
char *value = RSTRING_PTR(rbvalue);
|
||||
uint64_t vallen = RSTRING_LEN(rbvalue);
|
||||
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (vallen > uwsgi.cache_blocksize) {
|
||||
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
VALUE rack_uwsgi_cache_update(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
Check_Type(rbvalue, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
uint64_t keylen = RSTRING_LEN(rbkey);
|
||||
char *value = RSTRING_PTR(rbvalue);
|
||||
uint64_t vallen = RSTRING_LEN(rbvalue);
|
||||
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (vallen > uwsgi.cache_blocksize) {
|
||||
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_set_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_set(class, rbkey, rbvalue);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_update_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_update(class, rbkey, rbvalue);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_del(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_exists(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
if (uwsgi_cache_exists(key, keylen)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_get(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
uint64_t valsize;
|
||||
char *value = NULL;
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
VALUE res = rb_str_new(value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return res;
|
||||
|
||||
}
|
||||
VALUE rack_uwsgi_cache_get_exc(VALUE *class, VALUE rbkey) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_get(class, rbkey);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbmin, T_FIXNUM);
|
||||
Check_Type(rbhour, T_FIXNUM);
|
||||
Check_Type(rbday, T_FIXNUM);
|
||||
Check_Type(rbmon, T_FIXNUM);
|
||||
Check_Type(rbweek, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int minute = NUM2INT(rbmin);
|
||||
int hour = NUM2INT(rbhour);
|
||||
int day = NUM2INT(rbday);
|
||||
int month = NUM2INT(rbmon);
|
||||
int week = NUM2INT(rbweek);
|
||||
|
||||
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add cron");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
|
||||
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbfilename, T_STRING);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
char *filename = RSTRING_PTR(rbfilename);
|
||||
|
||||
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add file monitor");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_read(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_write(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_STRING);
|
||||
|
||||
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
|
||||
|
||||
return INT2FIX(fd);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_FIXNUM);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int timeout = NUM2INT(arg);
|
||||
|
||||
if (timeout >= 0) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
return INT2NUM(uwsgi.workers[0].pid);
|
||||
}
|
||||
return INT2NUM(0);
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
uwsgi_signal = NUM2INT(argv[0]);
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
if (wait_for_specific_signal) {
|
||||
received_signal = uwsgi_signal_wait(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_signal_received(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
return INT2NUM(wsgi_req->signal_received);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
|
||||
if (uwsgi_signal_registered(uwsgi_signal)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int rb_argc = 0;
|
||||
|
||||
if (argc < 2) goto clear;
|
||||
if (argc > 2) {
|
||||
Check_Type(argv[2], T_FIXNUM);
|
||||
rb_argc = NUM2INT(argv[2]);
|
||||
}
|
||||
|
||||
Check_Type(argv[0], T_STRING);
|
||||
char *name = RSTRING_PTR(argv[0]);
|
||||
void *func = (void *) argv[1];
|
||||
|
||||
|
||||
if (uwsgi_register_rpc(name, 7, rb_argc, func)) {
|
||||
clear:
|
||||
rb_raise(rb_eRuntimeError, "unable to register rpc function");
|
||||
return Qnil;
|
||||
}
|
||||
rb_gc_register_address(&argv[1]);
|
||||
rb_ary_push(ur.rpc_protector, argv[1]);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
Check_Type(sigkind, T_STRING);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
char *signal_kind = RSTRING_PTR(sigkind);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_gc_register_address(&rbhandler);
|
||||
rb_ary_push(ur.signals_protector, rbhandler);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc < 1) {
|
||||
rb_raise(rb_eRuntimeError, "you have to specify a signum");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(argv[0]);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_STRING);
|
||||
char *remote = RSTRING_PTR(argv[1]);
|
||||
|
||||
int ret = uwsgi_remote_signal_send(remote, uwsgi_signal);
|
||||
if (ret == 1) return Qtrue;
|
||||
if (ret == -1) {
|
||||
rb_raise(rb_eRuntimeError, "unable to deliver signal %d to node %s", uwsgi_signal, remote);
|
||||
return Qnil;
|
||||
}
|
||||
if (ret == 0) {
|
||||
rb_raise(rb_eRuntimeError, "node %s rejected signal %d", remote, uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_signal_send(uwsgi.signal_socket, uwsgi_signal);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_rack_init_api() {
|
||||
|
||||
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
|
||||
uwsgi_rack_api("suspend", uwsgi_ruby_suspend, 0);
|
||||
uwsgi_rack_api("masterpid", uwsgi_ruby_masterpid, 0);
|
||||
uwsgi_rack_api("async_sleep", uwsgi_ruby_async_sleep, 1);
|
||||
uwsgi_rack_api("wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
|
||||
uwsgi_rack_api("wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
|
||||
uwsgi_rack_api("async_connect", uwsgi_ruby_async_connect, 1);
|
||||
uwsgi_rack_api("signal", uwsgi_ruby_signal, -1);
|
||||
uwsgi_rack_api("register_signal", uwsgi_ruby_register_signal, 3);
|
||||
uwsgi_rack_api("register_rpc", uwsgi_ruby_register_rpc, -1);
|
||||
uwsgi_rack_api("signal_registered", uwsgi_ruby_signal_registered, 1);
|
||||
uwsgi_rack_api("signal_wait", uwsgi_ruby_signal_wait, -1);
|
||||
uwsgi_rack_api("signal_received", uwsgi_ruby_signal_received, 0);
|
||||
uwsgi_rack_api("add_cron", rack_uwsgi_add_cron, 6);
|
||||
uwsgi_rack_api("add_timer", rack_uwsgi_add_timer, 2);
|
||||
uwsgi_rack_api("add_rb_timer", rack_uwsgi_add_rb_timer, 2);
|
||||
uwsgi_rack_api("add_file_monitor", rack_uwsgi_add_file_monitor, 2);
|
||||
|
||||
uwsgi_rack_api("setprocname", rack_uwsgi_setprocname, 1);
|
||||
uwsgi_rack_api("mem", rack_uwsgi_mem, 0);
|
||||
|
||||
uwsgi_rack_api("lock", rack_uwsgi_lock, -1);
|
||||
uwsgi_rack_api("unlock", rack_uwsgi_unlock, -1);
|
||||
|
||||
uwsgi_rack_api("mule_get_msg", rack_uwsgi_mule_get_msg, -1);
|
||||
uwsgi_rack_api("mule_msg", rack_uwsgi_mule_msg, -1);
|
||||
|
||||
uwsgi_rack_api("request_id", rack_uwsgi_request_id, 0);
|
||||
uwsgi_rack_api("worker_id", rack_uwsgi_worker_id, 0);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, 1);
|
||||
uwsgi_rack_api("cache_get!", rack_uwsgi_cache_get_exc, 1);
|
||||
uwsgi_rack_api("cache_exists", rack_uwsgi_cache_exists, 1);
|
||||
uwsgi_rack_api("cache_exists?", rack_uwsgi_cache_exists, 1);
|
||||
uwsgi_rack_api("cache_del", rack_uwsgi_cache_del, 1);
|
||||
uwsgi_rack_api("cache_set", rack_uwsgi_cache_set, 2);
|
||||
uwsgi_rack_api("cache_set!", rack_uwsgi_cache_set_exc, 2);
|
||||
uwsgi_rack_api("cache_update", rack_uwsgi_cache_update, 2);
|
||||
uwsgi_rack_api("cache_update!", rack_uwsgi_cache_update_exc, 2);
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_opt_hash = rb_hash_new();
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
VALUE rb_uwsgi_opt_key = rb_str_new2(uwsgi.exported_opts[i]->key);
|
||||
if ( rb_funcall(uwsgi_rb_opt_hash, rb_intern("has_key?"), 1, rb_uwsgi_opt_key) == Qtrue) {
|
||||
VALUE rb_uwsgi_opt_item = rb_hash_aref(uwsgi_rb_opt_hash, rb_uwsgi_opt_key);
|
||||
if (TYPE(rb_uwsgi_opt_item) == T_ARRAY) {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_ary_push(rb_uwsgi_opt_item, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(rb_uwsgi_opt_item, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
VALUE rb_uwsgi_opt_list = rb_ary_new();
|
||||
rb_ary_push(rb_uwsgi_opt_list, rb_uwsgi_opt_item);
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_ary_push(rb_uwsgi_opt_list, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(rb_uwsgi_opt_list, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_uwsgi_opt_list);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("OPT"), uwsgi_rb_opt_hash);
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("VERSION"), rb_str_new2(UWSGI_VERSION));
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("HOSTNAME"), rb_str_new(uwsgi.hostname, uwsgi.hostname_len));
|
||||
if (uwsgi.pidfile) {
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("PIDFILE"), rb_str_new2(uwsgi.pidfile));
|
||||
}
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("NUMPROC"), INT2NUM(uwsgi.numproc));
|
||||
|
||||
|
||||
}
|
||||
+273
-253
@@ -9,6 +9,12 @@ struct option uwsgi_rack_options[] = {
|
||||
{"rails", required_argument, 0, LONG_ARGS_RAILS},
|
||||
{"rack", required_argument, 0, LONG_ARGS_RACK},
|
||||
{"ruby-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
|
||||
{"rb-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
|
||||
{"rb-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"ruby-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rbrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rubyrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
@@ -127,6 +133,10 @@ VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
|
||||
RUBY_GLOBAL_SETUP
|
||||
#endif
|
||||
|
||||
VALUE uwsgi_require_file(VALUE arg) {
|
||||
return rb_funcall(rb_cObject, rb_intern("require"), 1, arg);
|
||||
}
|
||||
|
||||
VALUE require_rack(VALUE arg) {
|
||||
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("rack"));
|
||||
}
|
||||
@@ -141,200 +151,51 @@ VALUE require_rails(VALUE arg) {
|
||||
|
||||
VALUE init_rack_app(VALUE);
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
|
||||
if (uwsgi_signal_registered(uwsgi_signal)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
VALUE rack_call_rpc_handler(VALUE args) {
|
||||
VALUE rpc_args = rb_ary_entry(args, 1);
|
||||
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
char *signal_kind = RSTRING_PTR(sigkind);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_gc_register_address(&rbhandler);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
|
||||
if (rlen != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_call_signal_handler(VALUE args) {
|
||||
|
||||
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
|
||||
}
|
||||
|
||||
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
|
||||
|
||||
uint8_t i;
|
||||
VALUE rb_args = rb_ary_new2(2);
|
||||
VALUE rb_rpc_args = rb_ary_new2(argc);
|
||||
VALUE ret;
|
||||
int error = 0;
|
||||
char *rv;
|
||||
size_t rl;
|
||||
|
||||
VALUE rbhandler = (VALUE) handler;
|
||||
VALUE args = rb_ary_new2(2);
|
||||
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);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
return -1;
|
||||
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_args, 1, rb_rpc_args);
|
||||
|
||||
|
||||
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int minute = NUM2INT(rbmin);
|
||||
int hour = NUM2INT(rbhour);
|
||||
int day = NUM2INT(rbday);
|
||||
int month = NUM2INT(rbmon);
|
||||
int week = NUM2INT(rbweek);
|
||||
|
||||
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add cron");
|
||||
return Qnil;
|
||||
if (TYPE(ret) == T_STRING) {
|
||||
rv = RSTRING_PTR(ret);
|
||||
rl = RSTRING_LEN(ret);
|
||||
if (rl <= 0xffff) {
|
||||
memcpy(buffer, rv, rl);
|
||||
return rl;
|
||||
}
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
|
||||
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
char *filename = RSTRING_PTR(rbfilename);
|
||||
|
||||
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add file monitor");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_read(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_write(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
|
||||
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
|
||||
|
||||
return INT2FIX(fd);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int timeout = NUM2INT(arg);
|
||||
|
||||
if (timeout >= 0) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
@@ -350,15 +211,12 @@ 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
|
||||
ruby_init();
|
||||
ruby_process_options(argc, argv);
|
||||
#else
|
||||
|
||||
ruby_init();
|
||||
ruby_init_loadpath();
|
||||
#endif
|
||||
@@ -366,19 +224,14 @@ int uwsgi_rack_init(){
|
||||
|
||||
ruby_script("uwsgi");
|
||||
|
||||
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
|
||||
rb_define_module_function(rb_uwsgi_embedded, "suspend", uwsgi_ruby_suspend, 0);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "async_sleep", uwsgi_ruby_async_sleep, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_cron", rack_uwsgi_add_cron, 6);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_timer", rack_uwsgi_add_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_rb_timer", rack_uwsgi_add_rb_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_file_monitor", rack_uwsgi_add_file_monitor, 2);
|
||||
ur.signals_protector = rb_ary_new();
|
||||
ur.rpc_protector = rb_ary_new();
|
||||
rb_gc_register_address(&ur.signals_protector);
|
||||
rb_gc_register_address(&ur.rpc_protector);
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
uwsgi_rack_init_api();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -386,6 +239,17 @@ int uwsgi_rack_init(){
|
||||
void uwsgi_rack_init_apps(void) {
|
||||
|
||||
int error;
|
||||
ur.app_id = uwsgi_apps_cnt;
|
||||
struct uwsgi_string_list *usl = ur.rbrequire;
|
||||
|
||||
while(usl) {
|
||||
error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (ur.rack) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
|
||||
@@ -448,6 +312,14 @@ ready:
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
|
||||
|
||||
uwsgi_add_app(ur.app_id, 7, (char*)"", 0);
|
||||
if (ur.gc_freq <= 1) {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, ur.call);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: %d)\n", ur.app_id, ur.call, ur.gc_freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VALUE call_dispatch(VALUE env) {
|
||||
@@ -456,7 +328,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;
|
||||
@@ -474,6 +346,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
|
||||
@@ -481,7 +362,6 @@ VALUE iterate_body(VALUE body) {
|
||||
#else
|
||||
return rb_iterate(rb_each, body, send_body, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
VALUE send_header(VALUE obj, VALUE headers) {
|
||||
@@ -523,7 +403,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
|
||||
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, ": ", 2);
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
|
||||
char *header_value = RSTRING_PTR(hval);
|
||||
@@ -534,7 +414,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
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, "\r\n", 2);
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
@@ -542,7 +422,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
header_value_splitted[0] = 0;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_splitted-header_value);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, "\r\n", 2);
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
@@ -554,12 +434,12 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
|
||||
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, ": ", 2);
|
||||
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, "\r\n", 2);
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
@@ -608,6 +488,9 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = ur.app_id;
|
||||
uwsgi_apps[wsgi_req->app_id].requests++;
|
||||
|
||||
|
||||
env = rb_hash_new();
|
||||
|
||||
@@ -667,13 +550,7 @@ 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;
|
||||
@@ -723,62 +600,53 @@ 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();
|
||||
rb_gc_unregister_address(&status);
|
||||
rb_gc_unregister_address(&headers);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2) != 2) {
|
||||
if (wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2) != 2) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
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);
|
||||
// TODO protect to_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
|
||||
if (rb_respond_to( body, rb_intern("to_path") )) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
rb_gc_unregister_address(&sendfile_path);
|
||||
}
|
||||
}
|
||||
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:
|
||||
@@ -791,7 +659,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
else {
|
||||
internal_server_error(wsgi_req, "Invalid RACK response");
|
||||
internal_server_error(wsgi_req, (char *)"Invalid RACK response");
|
||||
}
|
||||
|
||||
clear:
|
||||
@@ -801,7 +669,9 @@ clear:
|
||||
rb_gc_unregister_address(&env);
|
||||
|
||||
if (ur.gc_freq <= 1 || ur.cycles%ur.gc_freq == 0) {
|
||||
//uwsgi_log("calling ruby GC\n");
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("calling ruby GC\n");
|
||||
#endif
|
||||
rb_gc();
|
||||
}
|
||||
|
||||
@@ -835,6 +705,9 @@ int uwsgi_rack_manage_options(int i, char *optarg) {
|
||||
case LONG_ARGS_RUBY_GC_FREQ:
|
||||
ur.gc_freq = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_RUBY_REQUIRE:
|
||||
uwsgi_string_new_list(&ur.rbrequire, optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -850,6 +723,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;
|
||||
@@ -864,6 +775,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));
|
||||
@@ -924,6 +843,102 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
void uwsgi_rack_hijack(void) {
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule(char *opt) {
|
||||
int error = 0;
|
||||
|
||||
if (uwsgi_endswith(opt, (char *)".rb")) {
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_pfh(VALUE args) {
|
||||
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("post_fork_hook"))) {
|
||||
return rb_funcall(uwsgi_rb_embedded, rb_intern("post_fork_hook"), 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void uwsgi_rb_post_fork() {
|
||||
int error = 0;
|
||||
|
||||
// call the post_fork_hook
|
||||
rb_protect(uwsgi_rb_pfh, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_mmh(VALUE args) {
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
return rb_funcall(uwsgi_rb_embedded, rb_intern("mule_msg_hook"), 1, args);
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule_msg(char *message, size_t len) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("mule_msg_hook"))) {
|
||||
VALUE arg = rb_str_new(message, len);
|
||||
rb_protect(uwsgi_rb_mmh, arg, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_call_signal_handler(VALUE args) {
|
||||
|
||||
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
|
||||
}
|
||||
|
||||
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
|
||||
VALUE rbhandler = (VALUE) handler;
|
||||
VALUE args = rb_ary_new2(2);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.name = "rack",
|
||||
@@ -936,7 +951,8 @@ struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.signal_handler = uwsgi_rack_signal_handler,
|
||||
|
||||
.hijack = uwsgi_rack_hijack,
|
||||
.hijack_worker = uwsgi_rack_hijack,
|
||||
.post_fork = uwsgi_rb_post_fork,
|
||||
|
||||
.init_apps = uwsgi_rack_init_apps,
|
||||
//.mount_app = uwsgi_rack_mount_app,
|
||||
@@ -944,6 +960,10 @@ struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.magic = uwsgi_rack_magic,
|
||||
|
||||
.mule = uwsgi_rack_mule,
|
||||
.mule_msg = uwsgi_rack_mule_msg,
|
||||
.rpc = uwsgi_ruby_rpc,
|
||||
|
||||
.suspend = uwsgi_rack_suspend,
|
||||
.resume = uwsgi_rack_resume,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define LONG_ARGS_RUBY_GC_FREQ LONG_ARGS_RACK_BASE + 2
|
||||
#define LONG_ARGS_RACK LONG_ARGS_RACK_BASE + 3
|
||||
#define LONG_ARGS_RUBY_SHELL LONG_ARGS_RACK_BASE + 4
|
||||
#define LONG_ARGS_RUBY_REQUIRE LONG_ARGS_RACK_BASE + 5
|
||||
|
||||
#ifndef RUBY19
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
@@ -52,16 +53,24 @@ struct uwsgi_rack {
|
||||
uint64_t cycles;
|
||||
|
||||
int call_gc;
|
||||
|
||||
// why why why !!!!????!!!???
|
||||
VALUE signals_protector;
|
||||
VALUE rpc_protector;
|
||||
|
||||
VALUE dispatcher;
|
||||
VALUE rb_uwsgi_io_class;
|
||||
ID call;
|
||||
VALUE fibers[200];
|
||||
int unprotected;
|
||||
|
||||
pthread_mutex_t gvl;
|
||||
|
||||
int rb_shell;
|
||||
int app_id;
|
||||
|
||||
struct uwsgi_string_list *rbrequire;
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_ruby_exception(void);
|
||||
void uwsgi_rack_init_api(void);
|
||||
|
||||
+22
-18
@@ -7,33 +7,37 @@ try:
|
||||
except:
|
||||
RUBYPATH = 'ruby'
|
||||
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
rbconfig = 'Config'
|
||||
|
||||
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
|
||||
v = version.split('.')
|
||||
|
||||
GCC_LIST = ['rack_plugin']
|
||||
GCC_LIST = ['rack_plugin', 'rack_api']
|
||||
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
rbconfig = 'RbConfig'
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip()
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
|
||||
LDFLAGS.append('-L' + libpath )
|
||||
os.environ['LD_RUN_PATH'] = libpath
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ extern struct uwsgi_server uwsgi;
|
||||
#define RRDTOOL_OPT_BASE 177000
|
||||
#define RRDTOOL_OPT_RRDTOOL RRDTOOL_OPT_BASE+1
|
||||
#define RRDTOOL_OPT_RRDTOOL_MAX_DS RRDTOOL_OPT_BASE+2
|
||||
#define RRDTOOL_OPT_RRDTOOL_FREQ RRDTOOL_OPT_BASE+3
|
||||
|
||||
struct uwsgi_rrdtool {
|
||||
void *lib;
|
||||
@@ -12,12 +13,14 @@ struct uwsgi_rrdtool {
|
||||
int (*update)(int, char **);
|
||||
struct uwsgi_string_list *rrd;
|
||||
int max_ds;
|
||||
int freq;
|
||||
|
||||
char *update_area;
|
||||
} u_rrd;
|
||||
|
||||
struct option rrdtool_options[] = {
|
||||
{"rrdtool", required_argument, 0, RRDTOOL_OPT_RRDTOOL},
|
||||
{"rrdtool-freq", required_argument, 0, RRDTOOL_OPT_RRDTOOL_FREQ},
|
||||
{"rrdtool-max-ds", required_argument, 0, RRDTOOL_OPT_RRDTOOL_MAX_DS},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -43,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;
|
||||
}
|
||||
@@ -58,6 +61,9 @@ int rrdtool_opt(int i, char *optarg) {
|
||||
case RRDTOOL_OPT_RRDTOOL_MAX_DS:
|
||||
u_rrd.max_ds = atoi(optarg);
|
||||
return 1;
|
||||
case RRDTOOL_OPT_RRDTOOL_FREQ:
|
||||
u_rrd.freq = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -132,6 +138,8 @@ void rrdtool_post_init() {
|
||||
|
||||
u_rrd.update_area[0] = 'N';
|
||||
|
||||
if (u_rrd.freq < 1) u_rrd.freq = 300;
|
||||
|
||||
}
|
||||
|
||||
void rrdtool_master_cycle() {
|
||||
@@ -146,8 +154,8 @@ void rrdtool_master_cycle() {
|
||||
|
||||
if (last_update == 0) last_update = time(NULL);
|
||||
|
||||
// update every 5 minutes
|
||||
if (uwsgi.current_time - last_update >= 300) {
|
||||
// update
|
||||
if (uwsgi.current_time - last_update >= u_rrd.freq) {
|
||||
ptr = u_rrd.update_area+1;
|
||||
rlen = snprintf(ptr, 1+sizeof(UMAX64_STR), ":%llu", (unsigned long long )uwsgi.workers[0].requests);
|
||||
if (rlen < 2) return;
|
||||
|
||||
@@ -3,34 +3,43 @@ import os,sys
|
||||
NAME='ruby19'
|
||||
|
||||
try:
|
||||
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
|
||||
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
|
||||
except:
|
||||
RUBYPATH = 'ruby'
|
||||
RUBYPATH = 'ruby'
|
||||
|
||||
GCC_LIST = ['../rack/rack_plugin']
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
rbconfig = 'Config'
|
||||
|
||||
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
|
||||
v = version.split('.')
|
||||
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS.append('-DRUBY19')
|
||||
GCC_LIST = ['../rack/rack_plugin', '../rack/rack_api']
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
rbconfig = 'RbConfig'
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
|
||||
CFLAGS.append('-Drack_plugin=ruby19_plugin')
|
||||
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
|
||||
LDFLAGS.append('-L' + os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip() )
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
|
||||
LDFLAGS.append('-L' + libpath )
|
||||
os.environ['LD_RUN_PATH'] = libpath
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* request 110 */
|
||||
int uwsgi_request_signal(struct wsgi_request *wsgi_req) {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t ret_status = 1;
|
||||
if (uwsgi_signal_send(uwsgi.signal_socket, wsgi_req->uh.modifier2) < 0) {
|
||||
ret_status = 0;
|
||||
}
|
||||
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = ret_status;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin signal_plugin = {
|
||||
|
||||
.name = "signal",
|
||||
.modifier1 = 110,
|
||||
.request = uwsgi_request_signal,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='signal'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['signal_plugin']
|
||||
+111
-31
@@ -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;
|
||||
|
||||
}
|
||||
@@ -280,7 +282,9 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &pfd, sizeof(int));
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("passing fd\n");
|
||||
#endif
|
||||
cnt = sendmsg(fd, &msg, 0);
|
||||
}
|
||||
else {
|
||||
@@ -340,6 +344,58 @@ 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) {
|
||||
*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;
|
||||
@@ -403,7 +459,9 @@ 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);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arg %s\n", argv[*argc]);
|
||||
#endif
|
||||
ptrbuf += strsize;
|
||||
*argc = *argc + 1;
|
||||
}
|
||||
@@ -496,6 +554,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;
|
||||
@@ -803,25 +862,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;
|
||||
@@ -1379,7 +1459,7 @@ 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;
|
||||
char real_filename[PATH_MAX];
|
||||
@@ -1450,8 +1530,8 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
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, document_root, document_root_len);
|
||||
if (document_root[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);
|
||||
@@ -1462,8 +1542,8 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
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, document_root, document_root_len);
|
||||
if (document_root[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);
|
||||
|
||||
@@ -84,8 +84,13 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
strcpy(use->receiver, receiver);
|
||||
use->handler = handler;
|
||||
use->modifier1 = modifier1;
|
||||
|
||||
uwsgi_log("registered signal %d\n", sig);
|
||||
|
||||
if (use->receiver[0] == 0) {
|
||||
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: default, any worker)\n", sig, modifier1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: %s)\n", sig, modifier1, receiver);
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.signal_table_lock);
|
||||
|
||||
@@ -123,6 +128,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);
|
||||
@@ -198,24 +284,92 @@ int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
}
|
||||
|
||||
void create_signal_pipe(int *sigpipe) {
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_socket_nb(sigpipe[0]);
|
||||
uwsgi_socket_nb(sigpipe[1]);
|
||||
|
||||
if (uwsgi.signal_bufsize) {
|
||||
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
|
||||
uh.modifier1 = 110;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = sig;
|
||||
|
||||
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
if (write(fd, (char *) &uh, 4) != 4) {
|
||||
uwsgi_error("uwsgi_remote_signal_send()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
int so_bufsize = 0;
|
||||
|
||||
if (write(fd, &sig, 1) != 1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("getsockopt()");
|
||||
}
|
||||
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_route_signal(uint8_t sig) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
|
||||
int i;
|
||||
|
||||
// send to first available worker
|
||||
if (use->receiver[0] == 0 || !strcmp(use->receiver, "worker") || !strcmp(use->receiver, "worker0")) {
|
||||
if (write(ushared->worker_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->worker_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to workers pool\n", sig);
|
||||
}
|
||||
}
|
||||
// send to all workers
|
||||
else if (!strcmp(use->receiver, "workers")) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
@@ -226,8 +380,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
if (i > uwsgi.numproc) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
@@ -238,8 +391,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (!strcmp(use->receiver, "spooler")) {
|
||||
if (ushared->worker_signal_pipe[0] != -1) {
|
||||
if (write(ushared->spooler_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
|
||||
}
|
||||
}
|
||||
@@ -247,8 +399,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
#endif
|
||||
else if (!strcmp(use->receiver, "mules")) {
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (write(uwsgi.mules[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
|
||||
}
|
||||
}
|
||||
@@ -259,14 +410,12 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else if (i == 0) {
|
||||
if (write(ushared->mule_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to a mule\n", sig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(uwsgi.mules[i-1].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.mules[i-1].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
@@ -278,8 +427,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
uwsgi_log("unknown farm: %s\n", name);
|
||||
return;
|
||||
}
|
||||
if (write(uf->signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
|
||||
}
|
||||
}
|
||||
@@ -289,8 +437,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else {
|
||||
if (write(uwsgi.farms[i-1].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.farms[i-1].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
|
||||
}
|
||||
}
|
||||
@@ -300,4 +447,53 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
// unregistered signal, sending it to all the workers
|
||||
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t uwsgi_signal_wait(int signum) {
|
||||
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
int ret;
|
||||
struct pollfd pfd[2];
|
||||
|
||||
if (signum > -1) {
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
pfd[0].fd = uwsgi.signal_socket;
|
||||
pfd[0].events = POLLIN;
|
||||
pfd[1].fd = uwsgi.my_signal_socket;
|
||||
pfd[1].events = POLLIN;
|
||||
cycle:
|
||||
ret = poll(pfd, 2, -1);
|
||||
if (ret > 0) {
|
||||
if (pfd[0].revents == POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void)uwsgi_signal_handler(received_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents == POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void)uwsgi_signal_handler(received_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return received_signal;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+110
-1
@@ -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;
|
||||
@@ -72,23 +76,63 @@ 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) {
|
||||
// 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->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;
|
||||
}
|
||||
if (rr_pos == current_slot->rr) {
|
||||
current_slot->rr++;
|
||||
node->reference++;
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
rr_pos++;
|
||||
}
|
||||
current_slot->rr = 0;
|
||||
if (current_slot->nodes) {
|
||||
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;
|
||||
@@ -132,12 +176,15 @@ void uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsg
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = 1;
|
||||
free(node_slot);
|
||||
// am i the only slot ?
|
||||
if (!prev_slot && !next_slot) {
|
||||
*slot = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr, int regexp) {
|
||||
@@ -151,6 +198,8 @@ 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
|
||||
node->death_mark = 0;
|
||||
node->last_check = time(NULL);
|
||||
return node;
|
||||
}
|
||||
@@ -162,6 +211,8 @@ 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->reference = 0;
|
||||
node->death_mark = 0;
|
||||
node->last_check = time(NULL);
|
||||
node->slot = current_slot;
|
||||
memcpy(node->name, usr->address, usr->address_len);
|
||||
@@ -195,6 +246,8 @@ 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->death_mark = 0;
|
||||
current_slot->nodes->modifier1 = usr->modifier1;
|
||||
current_slot->nodes->modifier2 = usr->modifier2;
|
||||
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
|
||||
@@ -272,3 +325,59 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len, uint8_t cmd) {
|
||||
|
||||
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name));
|
||||
|
||||
if (modifier1) {
|
||||
ssb_size += (2 + 9) + (2 + modifier1_len);
|
||||
}
|
||||
|
||||
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"
|
||||
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, cmd, udp_address, subscrbuf, ssb_size-4);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -470,7 +476,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 +577,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 +665,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 +702,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();
|
||||
}
|
||||
|
||||
@@ -717,8 +725,101 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.loyal = 1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
// run the ksm mapper
|
||||
if (uwsgi.linux_ksm > 0 && (uwsgi.workers[uwsgi.mywid].requests % uwsgi.linux_ksm) == 0) {
|
||||
uwsgi_linux_ksm_map();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
ksm_mappings_current = NULL;
|
||||
ksm_mappings_current_lines = 0;
|
||||
|
||||
FILE *process_maps = fopen("/proc/self/maps", "r");
|
||||
|
||||
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);
|
||||
|
||||
if (ksm_mappings_last == NULL || ksm_mappings_last_lines == 0 || ksm_mappings_last_lines != ksm_mappings_current_lines) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (ksm_mappings_last)
|
||||
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 not dirty, free ksm_mappings_current
|
||||
else {
|
||||
free(ksm_mappings_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
wsgi_req->poll.events = POLLIN;
|
||||
@@ -747,6 +848,16 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_so
|
||||
|
||||
uwsgi.core[wsgi_req->async_id]->in_request = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
|
||||
// now check for suspend request
|
||||
if (uwsgi.workers[uwsgi.mywid].suspended == 1) {
|
||||
uwsgi_log_verbose("*** worker %d suspended ***\n", uwsgi.mywid);
|
||||
cycle:
|
||||
// wait for some signal (normally SIGTSTP) or 10 seconds (as fallback)
|
||||
(void) poll(NULL, 0, 10*1000);
|
||||
if (uwsgi.workers[uwsgi.mywid].suspended == 1) goto cycle;
|
||||
uwsgi_log_verbose("*** worker %d resumed ***\n", uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
@@ -1597,7 +1708,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 *));
|
||||
@@ -1617,28 +1728,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 == 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;
|
||||
@@ -1753,6 +1842,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;
|
||||
@@ -2114,32 +2241,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];
|
||||
@@ -2196,7 +2297,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) {
|
||||
@@ -2216,14 +2321,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);
|
||||
@@ -2536,6 +2642,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;
|
||||
@@ -2561,6 +2700,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;
|
||||
@@ -3043,14 +3183,30 @@ 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
|
||||
#ifdef CAP_WAKE_ALARM
|
||||
{ "wake_alarm", CAP_WAKE_ALARM},
|
||||
#endif
|
||||
{ NULL, -1}
|
||||
};
|
||||
|
||||
@@ -3285,3 +3441,24 @@ void http_url_decode(char *buf, uint16_t *len, char *dst) {
|
||||
*len = new_len;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int mountpoint_len) {
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[id];
|
||||
memset(wi, 0, sizeof(struct uwsgi_app));
|
||||
|
||||
wi->modifier1 = modifier1;
|
||||
wi->mountpoint = mountpoint;
|
||||
wi->mountpoint_len = mountpoint_len;
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
// check if we need to emulate fork() COW
|
||||
int i;
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
|
||||
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -537,6 +528,13 @@ struct uwsgi_opt {
|
||||
#define LONG_ARGS_MULES 17158
|
||||
#define LONG_ARGS_PROCNAME_PREFIX_SP 17159
|
||||
#define LONG_ARGS_UMASK 17160
|
||||
#define LONG_ARGS_PAUSE 17161
|
||||
#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
|
||||
@@ -970,6 +968,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 {
|
||||
|
||||
|
||||
@@ -1159,13 +1185,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;
|
||||
@@ -1251,6 +1281,7 @@ struct uwsgi_server {
|
||||
int lazy_respawned;
|
||||
|
||||
int buffer_size;
|
||||
int signal_bufsize;
|
||||
|
||||
// post buffering
|
||||
int post_buffering;
|
||||
@@ -1323,6 +1354,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
|
||||
@@ -1505,6 +1537,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;
|
||||
@@ -1513,14 +1546,17 @@ 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;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -1648,10 +1684,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];
|
||||
@@ -1659,8 +1698,6 @@ struct uwsgi_shared {
|
||||
|
||||
int worker_log_pipe[2];
|
||||
|
||||
struct uwsgi_daemon daemons[MAX_DAEMONS];
|
||||
int daemons_cnt;
|
||||
#ifdef __linux__
|
||||
struct tcp_info ti;
|
||||
#endif
|
||||
@@ -1706,6 +1743,7 @@ struct uwsgi_worker {
|
||||
uint64_t respawn_count;
|
||||
|
||||
uint64_t requests;
|
||||
uint64_t delta_requests;
|
||||
uint64_t failed_requests;
|
||||
|
||||
time_t harakiri;
|
||||
@@ -1728,6 +1766,7 @@ struct uwsgi_worker {
|
||||
|
||||
int busy;
|
||||
int cheaped;
|
||||
int suspended;
|
||||
int sig;
|
||||
uint8_t signum;
|
||||
|
||||
@@ -1842,7 +1881,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);
|
||||
@@ -2096,7 +2135,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);
|
||||
@@ -2239,7 +2277,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__
|
||||
@@ -2413,6 +2451,9 @@ struct uwsgi_subscribe_node {
|
||||
uint64_t requests;
|
||||
uint64_t transferred;
|
||||
|
||||
int death_mark;
|
||||
uint64_t reference;
|
||||
|
||||
struct uwsgi_subscribe_slot *slot;
|
||||
|
||||
struct uwsgi_subscribe_node *next;
|
||||
@@ -2439,12 +2480,46 @@ struct uwsgi_subscribe_slot {
|
||||
struct uwsgi_subscribe_slot *next;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
uint8_t uwsgi_signal_wait(int);
|
||||
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 , char *, size_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);
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
void uwsgi_linux_ksm_map(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
void uwsgi_build_cap(char *);
|
||||
#endif
|
||||
|
||||
+25
-4
@@ -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
|
||||
@@ -160,6 +162,11 @@ def build_uwsgi(uc):
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Werror=declaration-after-statement')
|
||||
except:
|
||||
pass
|
||||
|
||||
for cfile in up.GCC_LIST:
|
||||
if not cfile.endswith('.a'):
|
||||
compile(' '.join(p_cflags),
|
||||
@@ -232,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]):
|
||||
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
gcc_version = str(spcall("%s -dumpversion" % GCC))
|
||||
@@ -789,11 +804,16 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Werror=declaration-after-statement')
|
||||
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:
|
||||
@@ -844,6 +864,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")
|
||||
|
||||
+14
-2
@@ -155,7 +155,7 @@ class farm(object):
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(farm_loop(f, self.name))
|
||||
|
||||
class mule_loop(object):
|
||||
class mule_brain(object):
|
||||
|
||||
def __init__(self, f, num):
|
||||
self.f = f
|
||||
@@ -165,12 +165,24 @@ class mule_loop(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):
|
||||
self.num = num
|
||||
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(mule_loop(f, self.num))
|
||||
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):
|
||||
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
# based on uwsgidecorators.py
|
||||
|
||||
if UWSGI.masterpid == 0
|
||||
raise "you have to enable the uWSGI master process to use this module"
|
||||
end
|
||||
|
||||
def get_free_signal()
|
||||
for signum in 0..255
|
||||
if not UWSGI.signal_registered(signum)
|
||||
return signum
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$postfork_chain = []
|
||||
$mulefunc_list = []
|
||||
|
||||
module UWSGI
|
||||
module_function
|
||||
def post_fork_hook()
|
||||
$postfork_chain.each {|func| func.call }
|
||||
end
|
||||
|
||||
module_function
|
||||
def mule_msg_hook(message)
|
||||
service = Marshal.load(message)
|
||||
if service['service'] == 'uwsgi_mulefunc'
|
||||
mulefunc_manager(service)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def timer(secs, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_timer(freesig, secs)
|
||||
end
|
||||
|
||||
def rbtimer(secs, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_rb_timer(freesig, secs)
|
||||
end
|
||||
|
||||
def filemon(file, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_file_monitor(freesig, file)
|
||||
end
|
||||
|
||||
def cron(minute, hour, day, month, dayweek, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_cron(freesig, minute, hour, day, month, dayweek)
|
||||
end
|
||||
|
||||
def signal(signum, target='', &block)
|
||||
UWSGI.register_signal(signum, target, block)
|
||||
end
|
||||
|
||||
def postfork(&block)
|
||||
$postfork_chain << block
|
||||
end
|
||||
|
||||
def rpc(name, &block)
|
||||
if block.arity <= 0
|
||||
UWSGI.register_rpc(name, block, 0)
|
||||
else
|
||||
UWSGI.register_rpc(name, block, block.arity)
|
||||
end
|
||||
end
|
||||
|
||||
def mulefunc_manager(service)
|
||||
$mulefunc_list[service['func']].real_call(service['args'])
|
||||
end
|
||||
|
||||
class MuleFunc < Proc
|
||||
|
||||
def initialize(id=0, &block)
|
||||
@id = id
|
||||
@block = block
|
||||
@func_pos = (($mulefunc_list << self).length)-1
|
||||
end
|
||||
|
||||
def real_call(*args)
|
||||
@block.call(*args)
|
||||
end
|
||||
|
||||
def call(*args)
|
||||
UWSGI.mule_msg( Marshal.dump( {
|
||||
'service' => 'uwsgi_mulefunc',
|
||||
'func' => @func_pos,
|
||||
'args'=> args
|
||||
}), @id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class MuleProc < Proc
|
||||
def initialize(id, block)
|
||||
@id = id
|
||||
@block = block
|
||||
end
|
||||
|
||||
def call()
|
||||
if UWSGI.mule_id == @id
|
||||
@block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MuleLoopProc < MuleProc
|
||||
def call()
|
||||
if UWSGI.mule_id == @id
|
||||
loop do
|
||||
@block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mule(id, &block)
|
||||
$postfork_chain << MuleProc.new(id, block)
|
||||
end
|
||||
|
||||
def muleloop(id, &block)
|
||||
$postfork_chain << MuleLoopProc.new(id, block)
|
||||
end
|
||||
+8
-2
@@ -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()))
|
||||
|
||||
Reference in New Issue
Block a user