mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ef7819080 | ||
|
|
319ad13af2 | ||
|
|
fe28e90ae3 | ||
|
|
f604a0a533 | ||
|
|
4ab78d42a3 | ||
|
|
c631e7dae6 | ||
|
|
da8e88d638 | ||
|
|
4707d9250d | ||
|
|
d719960411 | ||
|
|
734818c995 | ||
|
|
a35335a820 | ||
|
|
aca4dbfbe7 | ||
|
|
b036029b32 | ||
|
|
52f3e757ed | ||
|
|
c4ce1cf7d8 | ||
|
|
48175d0759 | ||
|
|
2932168db7 | ||
|
|
e8d96b8f84 | ||
|
|
bd15fd9da1 | ||
|
|
6e98eda963 | ||
|
|
ec9bb3601e | ||
|
|
02e4840b29 | ||
|
|
d7e8523fcf | ||
|
|
41464c3bfa | ||
|
|
a3617d0b5a | ||
|
|
10ff849ebd | ||
|
|
c2f7d487d0 | ||
|
|
395cf57e21 | ||
|
|
4c854a83c9 | ||
|
|
881b3b7e0c | ||
|
|
bb28e4279b | ||
|
|
c65b8ce162 | ||
|
|
8a303b1965 | ||
|
|
adca811941 | ||
|
|
f79e9d8773 | ||
|
|
629fbf4f07 | ||
|
|
da9ce52294 | ||
|
|
205605a3c4 | ||
|
|
e39127be92 | ||
|
|
0b2458d74a | ||
|
|
9d661122bd | ||
|
|
8518747a51 | ||
|
|
2f6450a560 | ||
|
|
c72889c10f | ||
|
|
bb7456e3f8 | ||
|
|
5aff13543e | ||
|
|
c7d967d43c | ||
|
|
1a42194304 | ||
|
|
312563437c | ||
|
|
5972ac1ed7 | ||
|
|
75d4123b34 | ||
|
|
89ef4f68a9 | ||
|
|
ed72677e52 | ||
|
|
08ab27c36c | ||
|
|
af8bb8fd05 | ||
|
|
57bade7eae | ||
|
|
3c6de0e84d | ||
|
|
24e3fea334 | ||
|
|
6af77aab8b | ||
|
|
12325633ed | ||
|
|
3a108b61ee | ||
|
|
b2eaf384ac | ||
|
|
3d17ef9603 | ||
|
|
3b031872f7 | ||
|
|
e97d39f37c | ||
|
|
763f715279 | ||
|
|
af9f79f3eb | ||
|
|
01ab3e2895 | ||
|
|
7a34344632 | ||
|
|
9714cb6790 | ||
|
|
aa981d03e8 | ||
|
|
9a09164fc3 | ||
|
|
9674a81323 | ||
|
|
aba7280691 | ||
|
|
ef9908b058 | ||
|
|
4da4fb4cbd | ||
|
|
b4f8a3b179 | ||
|
|
b48a955848 | ||
|
|
5ea4e3bcc3 | ||
|
|
6732cb01a8 | ||
|
|
0b5ca736d4 | ||
|
|
a2358c6bec | ||
|
|
10775dd2ac | ||
|
|
d33d12c642 | ||
|
|
af3ccfeed4 | ||
|
|
1d64267aba | ||
|
|
9bbef9b0c5 | ||
|
|
c95ec82b03 | ||
|
|
46108a00f0 | ||
|
|
d6c3fd7771 | ||
|
|
ad783ccaf0 | ||
|
|
f58be4241f | ||
|
|
cb1d22d88b | ||
|
|
6c8453d98e | ||
|
|
061de3b037 | ||
|
|
ded065ef38 | ||
|
|
822959238c | ||
|
|
4ebb9d7b46 | ||
|
|
cc49964c43 | ||
|
|
3787d5e84a | ||
|
|
7329606a6a | ||
|
|
5facafadea | ||
|
|
d3102df2bf | ||
|
|
87860da238 | ||
|
|
4a8aa01f40 | ||
|
|
9d35067b4b | ||
|
|
1c29be3745 | ||
|
|
bf3c3a3768 | ||
|
|
b25de79ae4 | ||
|
|
ba663ef2cc | ||
|
|
19185640a5 | ||
|
|
eafe8c4fff | ||
|
|
bdd3e69024 | ||
|
|
b5a7ab3688 | ||
|
|
cc0fa8dee6 | ||
|
|
14941cc1c0 | ||
|
|
910cb3a790 | ||
|
|
355e989eea | ||
|
|
bfcd9dad25 | ||
|
|
73ed5fd7cf | ||
|
|
d21cc0970c | ||
|
|
eb8b03139d | ||
|
|
1558145985 | ||
|
|
4ea9a29e62 | ||
|
|
72c8d9cd5e | ||
|
|
fb4fc38f14 | ||
|
|
de25db9e75 | ||
|
|
4ba558430d | ||
|
|
e4711484ac | ||
|
|
5081a3f635 | ||
|
|
b31fa366a2 | ||
|
|
c1b24b390a | ||
|
|
b7461442b0 | ||
|
|
c072e9b609 | ||
|
|
5236c58255 | ||
|
|
4f5280ea2b | ||
|
|
4d1c3fcaea | ||
|
|
310acaf4cc | ||
|
|
8111acaad1 | ||
|
|
c80b10d2b2 | ||
|
|
9807192bd1 | ||
|
|
9386c97851 | ||
|
|
7f3e9b10c4 | ||
|
|
360719582b | ||
|
|
a1a6d4a248 | ||
|
|
015ea78927 | ||
|
|
ad32841aaa | ||
|
|
2a3771dccf | ||
|
|
26af8af48f | ||
|
|
5829c3a843 | ||
|
|
c723d6d9d5 | ||
|
|
2c0c9a918a | ||
|
|
8f9bc7170e | ||
|
|
ee002167d4 | ||
|
|
4ddeb26cca | ||
|
|
a1514e2eaf | ||
|
|
5d1c7ab8b0 | ||
|
|
27698e34f5 | ||
|
|
c06b4773c7 | ||
|
|
e431936a8e | ||
|
|
de3d22a401 | ||
|
|
22778d9de7 | ||
|
|
069f517b04 | ||
|
|
1017dda1ec | ||
|
|
581b4a4216 | ||
|
|
e1f00cbf96 | ||
|
|
32ad0a7b87 | ||
|
|
aa4b9b16fb | ||
|
|
73721ab73a | ||
|
|
90cc3dc389 | ||
|
|
f4f4d5a6c0 | ||
|
|
4bd2410ee7 | ||
|
|
6bc264d33b | ||
|
|
c7d1c6818b | ||
|
|
937e68bf67 | ||
|
|
434fb96be7 | ||
|
|
e2fe86027c | ||
|
|
06ca891d94 | ||
|
|
57c00c9b12 | ||
|
|
b320e1e222 | ||
|
|
c72ddc9dd8 | ||
|
|
c37a386674 | ||
|
|
ad6a79b5b7 | ||
|
|
ff733cd50b | ||
|
|
53128a2391 | ||
|
|
d01fc8804c | ||
|
|
e520d7a58f | ||
|
|
7846ea636c | ||
|
|
0025ad8329 | ||
|
|
1a1f270f4e | ||
|
|
517f4498f5 | ||
|
|
87a165477f | ||
|
|
1e657f0b77 | ||
|
|
a8e399db1e | ||
|
|
66f9607404 | ||
|
|
27319c2da3 | ||
|
|
de21abb21c | ||
|
|
94cae4ac17 | ||
|
|
3b5e1f98f5 | ||
|
|
594f67c6d7 | ||
|
|
f1b415df2f | ||
|
|
c07e0ef581 | ||
|
|
0d4f6501b0 | ||
|
|
d2cbb7eea2 | ||
|
|
f4cb3c67c1 | ||
|
|
a51877cd1d | ||
|
|
c0c3287f74 | ||
|
|
83378802af | ||
|
|
f05d712923 | ||
|
|
5b2df55b8e | ||
|
|
865ec4dd8f | ||
|
|
6ddf1afc81 | ||
|
|
7bd44f4f14 | ||
|
|
a92c2003ee | ||
|
|
97a8c5e4b6 | ||
|
|
a5aa31f13e | ||
|
|
1a0161cb6b | ||
|
|
b8c17baf7c | ||
|
|
e161ea3f0a | ||
|
|
fb827a274b | ||
|
|
7281318ef6 | ||
|
|
80be7385ed | ||
|
|
8913dda413 | ||
|
|
b8ad90104b | ||
|
|
2646109986 | ||
|
|
cf247c828a | ||
|
|
28106e624e | ||
|
|
30e8420342 | ||
|
|
99e4d55e9b | ||
|
|
f9daec9e43 | ||
|
|
68a2902ce3 | ||
|
|
4b2db3de57 | ||
|
|
c4c526df17 | ||
|
|
15ad5531b0 | ||
|
|
c0af1c1094 | ||
|
|
9b89333244 | ||
|
|
1863030078 | ||
|
|
15055ffa0d | ||
|
|
8391ce28f7 | ||
|
|
b38791a357 | ||
|
|
53ba043168 | ||
|
|
d46a8dba7b | ||
|
|
1e62afc161 | ||
|
|
03cf6e868f | ||
|
|
e1da28ccc3 | ||
|
|
4173ca36cb | ||
|
|
c393de492d | ||
|
|
f9a716d70f | ||
|
|
2e8655c203 | ||
|
|
42b7164f33 | ||
|
|
602d49b045 | ||
|
|
58a67df534 | ||
|
|
de6cc04685 | ||
|
|
33763e074d | ||
|
|
32b0f8efb6 | ||
|
|
644618963a | ||
|
|
97ac31376e | ||
|
|
e5ec0f0221 | ||
|
|
5875ddc355 | ||
|
|
f7d5f4692d | ||
|
|
d85bc64aa9 | ||
|
|
a18ed0503c | ||
|
|
77a4e3771b | ||
|
|
7523eb1cb0 | ||
|
|
46f8ee9410 | ||
|
|
f0aa9f9fd2 | ||
|
|
73d5cadd8c | ||
|
|
1a0e2076d5 | ||
|
|
6db3dab5ea | ||
|
|
20856549c1 | ||
|
|
d570845592 | ||
|
|
eed27c0aac | ||
|
|
daef139496 | ||
|
|
3690d836b0 | ||
|
|
93faeb4177 | ||
|
|
095b9154e0 | ||
|
|
f86aa55220 | ||
|
|
40f7aecbba | ||
|
|
5d9d67caa4 | ||
|
|
0f00d6fb23 | ||
|
|
61b0e68641 | ||
|
|
6ed38ced3c | ||
|
|
7a681a97b5 | ||
|
|
41008fa594 | ||
|
|
fb13084b87 | ||
|
|
3f9023281e | ||
|
|
4e21fe6607 | ||
|
|
7a95c726cd | ||
|
|
940401e0f8 | ||
|
|
86bfb20903 | ||
|
|
e21cf87285 | ||
|
|
65f1445b64 | ||
|
|
f87761d092 | ||
|
|
0c712ac28d | ||
|
|
db301531d0 | ||
|
|
4c82a72fd5 | ||
|
|
7417e582c3 | ||
|
|
e32564c7b2 | ||
|
|
798bc482dc | ||
|
|
c7e7f756bc | ||
|
|
24358701f7 | ||
|
|
f1e392c0a0 | ||
|
|
5e8d38d8bc | ||
|
|
4650d2edbb | ||
|
|
b153033514 | ||
|
|
6dcbce5eb7 | ||
|
|
4ceeab439a | ||
|
|
8b1a6be9da | ||
|
|
baeb864075 | ||
|
|
c88e1c3619 | ||
|
|
1b04df7c5e | ||
|
|
237f11dba3 | ||
|
|
313f1c2f29 | ||
|
|
f0862f3bc7 |
@@ -42,3 +42,8 @@ a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
|
||||
@@ -17,3 +17,4 @@ Charles Duffy
|
||||
Lukas Lalinsky
|
||||
Steven Fernandez
|
||||
Łukasz Mierzwa
|
||||
Roy Marples
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.4 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.5 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.6 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.7 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.0 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.1 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.2 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python uwsgiconfig.py --build pylua
|
||||
@@ -1,5 +1,5 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
@@ -15,19 +15,20 @@ threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
@@ -35,6 +36,9 @@ event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
ini = true
|
||||
yaml = false
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
spooler = true
|
||||
embedded = true
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins =
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
@@ -83,8 +83,7 @@ void uwsgi_init_cache() {
|
||||
|
||||
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
|
||||
|
||||
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
|
||||
uwsgi_rwlock_init(uwsgi.cache_lock);
|
||||
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
|
||||
|
||||
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
|
||||
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
|
||||
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
|
||||
|
||||
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
|
||||
|
||||
}
|
||||
|
||||
void cluster_setup() {
|
||||
|
||||
int rlen;
|
||||
@@ -31,8 +39,8 @@ void cluster_setup() {
|
||||
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();
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure(-1);
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use IO::Socket::INET;
|
||||
|
||||
my $s = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $ARGV[0]);
|
||||
|
||||
my $mountpoint = $ARGV[1];
|
||||
my $app = $ARGV[2];
|
||||
|
||||
my $uwsgi_appid = pack('v', length('UWSGI_APPID')).'UWSGI_APPID'.pack('v', length($mountpoint)).$mountpoint;
|
||||
my $uwsgi_script = pack('v', length('UWSGI_SCRIPT')).'UWSGI_SCRIPT'.pack('v', length($app)).$app;
|
||||
|
||||
$s->send(pack('CvC', 5, length($uwsgi_appid.$uwsgi_script),0).$uwsgi_appid.$uwsgi_script);
|
||||
|
||||
while((my $cnt = $s->recv(my $buf, 4096))> 0) {
|
||||
print $buf;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMMAND=./uwsgi
|
||||
CONFIG_FILE=
|
||||
|
||||
|
||||
FIRST=0
|
||||
|
||||
for ARG in $@;do
|
||||
if [ $FIRST -eq 0 ];then
|
||||
FIRST=1
|
||||
else
|
||||
ARGS="$ARGS $ARG"
|
||||
fi
|
||||
done
|
||||
|
||||
export UWSGI_INHERIT=CONFIG_FILE
|
||||
export UWSGI_PYRUN=$1
|
||||
export UWSGI_PYARGV=$ARGS
|
||||
|
||||
exec $COMMAND
|
||||
@@ -336,7 +336,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
}
|
||||
|
||||
counter = 4;
|
||||
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
@@ -373,14 +373,32 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->filename;
|
||||
vassal_argv[counter+1] = uct->value;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0)) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
|
||||
for(i=3;i<(int)uwsgi.max_fd;i++) {
|
||||
if (n_ui->use_config) {
|
||||
if (i == n_ui->pipe_config[1])
|
||||
continue;
|
||||
}
|
||||
if (i != n_ui->pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
@@ -435,6 +453,7 @@ void emperor_loop() {
|
||||
int nevents;
|
||||
int interesting_fd;
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
@@ -446,6 +465,13 @@ void emperor_loop() {
|
||||
|
||||
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl)) {
|
||||
uwsgi_error("getrlimit()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.max_fd = rl.rlim_cur;
|
||||
|
||||
|
||||
emperor_queue = event_queue_init();
|
||||
|
||||
@@ -515,7 +541,11 @@ reconnect:
|
||||
exit(1);
|
||||
}
|
||||
globfree(&g);
|
||||
emperor_absolute_dir = realpath(".", NULL);
|
||||
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
|
||||
if (realpath(".", emperor_absolute_dir) == NULL) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ui = &ui_base;
|
||||
@@ -627,7 +657,9 @@ reconnect:
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
if (!ui_current->config_len) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
|
||||
@@ -172,6 +172,7 @@ int event_queue_init() {
|
||||
|
||||
int epfd;
|
||||
|
||||
|
||||
epfd = epoll_create(256);
|
||||
|
||||
if (epfd < 0) {
|
||||
@@ -403,7 +404,8 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
if (errno != EINTR)
|
||||
uwsgi_error("kevent()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -443,7 +445,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
if (errno != EINTR)
|
||||
uwsgi_error("kevent()");
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
|
||||
@@ -2,121 +2,76 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
|
||||
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int)) {
|
||||
|
||||
struct uwsgi_gateway *ug;
|
||||
int num=1,i;
|
||||
|
||||
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
|
||||
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
|
||||
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
if (!strcmp(name, uwsgi.gateways[i].name)) {
|
||||
for(i=0;i<ushared->gateways_cnt;i++) {
|
||||
if (!strcmp(name, ushared->gateways[i].name)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
|
||||
|
||||
ug = &ushared->gateways[ushared->gateways_cnt];
|
||||
ug->pid = 0;
|
||||
ug->name = name;
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
ug->fullname = fullname;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
ushared->gateways_cnt++;
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
return ug;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
|
||||
pid_t gw_pid;
|
||||
pid_t orig_pid = getpid();
|
||||
struct uwsgi_gateway *ug;
|
||||
int num=1,i;
|
||||
|
||||
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
|
||||
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
if (!strcmp(name, uwsgi.gateways[i].name)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
gw_pid = uwsgi_fork(name);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process) {
|
||||
if (gw_pid > 0) {
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!uwsgi.sockets) {
|
||||
// wait for child end
|
||||
//waitpid(-1, &i, 0);
|
||||
}
|
||||
loop();
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
ug->pid = orig_pid;
|
||||
}
|
||||
else {
|
||||
if (gw_pid == 0) {
|
||||
if (uwsgi.master_as_root) uwsgi_as_root();
|
||||
loop();
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
ug->pid = gw_pid;
|
||||
}
|
||||
|
||||
|
||||
ug->name = name;
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
return ug;
|
||||
|
||||
}
|
||||
|
||||
void gateway_respawn(int id) {
|
||||
|
||||
pid_t gw_pid;
|
||||
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
|
||||
struct uwsgi_gateway *ug = &ushared->gateways[id];
|
||||
|
||||
if (uwsgi.master_process)
|
||||
uwsgi.shared->gateways_harakiri[id] = 0;
|
||||
|
||||
gw_pid = uwsgi_fork(ug->name);
|
||||
gw_pid = uwsgi_fork(ug->fullname);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
if (uwsgi.master_as_root) uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
ug->loop();
|
||||
uwsgi.mypid = getpid();
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
ug->loop(id);
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
@@ -131,3 +86,71 @@ void gateway_respawn(int id) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
||||
|
||||
if (!uwsgi_sock) {
|
||||
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock = uwsgi.gateway_sockets;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_sock) {
|
||||
old_uwsgi_sock = uwsgi_sock;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
old_uwsgi_sock->next = uwsgi_sock;
|
||||
}
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock->fd = -1;
|
||||
uwsgi_sock->shared = 0;
|
||||
uwsgi_sock->name = name;
|
||||
uwsgi_sock->owner = owner;
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
||||
|
||||
if (!uwsgi_sock) {
|
||||
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock = uwsgi.gateway_sockets;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_sock) {
|
||||
old_uwsgi_sock = uwsgi_sock;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
old_uwsgi_sock->next = uwsgi_sock;
|
||||
}
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock->fd = fd;
|
||||
uwsgi_sock->name = uwsgi_getsockname(fd);
|
||||
uwsgi_sock->owner = owner;
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
|
||||
|
||||
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_del_fd(queue, ugs->fd, event_queue_read());
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,6 @@ import uwsgi
|
||||
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar"
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
uWSGI version <b><?=uwsgi_version()?></b><br/>
|
||||
workerd id: <b><?=uwsgi_worker_id()?></b><br/>
|
||||
master pid: <b><?=uwsgi_masterpid()?></b><br/>
|
||||
|
||||
uri: <b><?= $_SERVER['REQUEST_URI'] ?></b><br/>
|
||||
docroot: <b><?= $_SERVER['DOCUMENT_ROOT'] ?></b><br/>
|
||||
PATH_INFO: <b><?= $_SERVER['PATH_INFO'] ?></b><br/>
|
||||
|
||||
<? uwsgi_signal(17) ?>
|
||||
|
||||
<? uwsgi_setprocname("test test test"); ?>
|
||||
|
||||
rpc result:<br/>
|
||||
<? echo uwsgi_rpc("", "hello", "one", "two", "three"); ?>
|
||||
|
||||
<?
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
uwsgi_cache_update('foobar', $_POST['cache_val']);
|
||||
}
|
||||
|
||||
?>
|
||||
<form method="POST">
|
||||
<input type="text" name="cache_val" value="<?=uwsgi_cache_get('foobar')?>"/>
|
||||
<input type="submit" value="cache set" />
|
||||
</form>
|
||||
@@ -14,7 +14,7 @@ void ini_rstrip(char *line) {
|
||||
off_t i;
|
||||
|
||||
for(i = strlen(line)-1;i>=0; i--) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
|
||||
line[i] = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ char *ini_lstrip(char *line) {
|
||||
char *ptr = line;
|
||||
|
||||
for(i=0;i< (int) strlen(line);i++) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -108,56 +108,37 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct option *aopt, *lopt;
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
char ldap_name[1024];
|
||||
static int counter = 30000000;
|
||||
|
||||
*count = 0;
|
||||
lopt = uwsgi.long_options;
|
||||
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
while( op && op->name ) {
|
||||
|
||||
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
|
||||
uwsgi_name_to_ldap((char *)op->name, ldap_name);
|
||||
|
||||
entry = search_ldap_cache(ule, ldap_name, *count);
|
||||
|
||||
if (entry) goto next;
|
||||
|
||||
if (aopt->flag) {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = counter;
|
||||
strcpy(entry->names, ldap_name);
|
||||
counter++;
|
||||
*count = *count+1;
|
||||
}
|
||||
else {
|
||||
entry = get_ldap_by_num(ule, aopt->val, *count);
|
||||
if (entry) {
|
||||
strcat(entry->names, ldap_name);
|
||||
}
|
||||
else {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = aopt->val;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count+1;
|
||||
}
|
||||
}
|
||||
entry = &ule[*count] ;
|
||||
entry->num = *count;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count+1;
|
||||
|
||||
entry->has_arg = aopt->has_arg;
|
||||
entry->has_arg = op->type;
|
||||
|
||||
next:
|
||||
lopt++;
|
||||
op++;
|
||||
}
|
||||
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump_ldif() {
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -210,7 +191,7 @@ void uwsgi_ldap_schema_dump_ldif() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump() {
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -258,7 +239,7 @@ void uwsgi_ldap_schema_dump() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config() {
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
@@ -267,7 +248,6 @@ void uwsgi_ldap_config() {
|
||||
char *attr;
|
||||
char *uwsgi_attr;
|
||||
|
||||
char *url = "ldap:///";
|
||||
char *url_slash;
|
||||
|
||||
int desired_version = LDAP_VERSION3;
|
||||
@@ -275,10 +255,6 @@ void uwsgi_ldap_config() {
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (uwsgi.ldap) {
|
||||
url = uwsgi.ldap;
|
||||
}
|
||||
|
||||
if (!ldap_is_ldap_url(url)) {
|
||||
uwsgi_log("invalid LDAP url.\n");
|
||||
exit(1);
|
||||
|
||||
+3
-34
@@ -27,22 +27,6 @@ struct amqp_frame_method {
|
||||
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
|
||||
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
|
||||
|
||||
/*
|
||||
static char *amqp_get_longstr(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t longstr_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&longstr_size, ptr, 4);
|
||||
longstr_size = ntohl(longstr_size);
|
||||
|
||||
if (ptr+4+longstr_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+longstr_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
|
||||
uint8_t str_size;
|
||||
@@ -58,23 +42,6 @@ static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static char *amqp_get_table(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t table_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&table_size, ptr, 4);
|
||||
|
||||
table_size = ntohl(table_size);
|
||||
|
||||
if (ptr+4+table_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+table_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
|
||||
|
||||
uint16_t tmp_short;
|
||||
@@ -197,7 +164,9 @@ char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
|
||||
|
||||
free(frame);
|
||||
frame = NULL;
|
||||
free(header);
|
||||
header = NULL;
|
||||
|
||||
char *fullbody = uwsgi_malloc(*msgsize);
|
||||
char *message;
|
||||
@@ -501,7 +470,7 @@ static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
len = 0;
|
||||
|
||||
char *frame = malloc(fh->size+1);
|
||||
char *frame = uwsgi_malloc(fh->size+1);
|
||||
ptr = frame;
|
||||
|
||||
while(len < fh->size+1) {
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
|
||||
common functions for various routers (fastrouter, http...)
|
||||
|
||||
*/
|
||||
static void uwsgi_corerouter_setup_sockets(char *gw_id) {
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(gw_id, ugs->owner)) {
|
||||
#ifdef UWSGI_SCTP
|
||||
if (!ugs->subscription && !ugs->sctp) {
|
||||
#else
|
||||
if (!ugs->subscription) {
|
||||
#endif
|
||||
if (ugs->name[0] == '=') {
|
||||
int shared_socket = atoi(ugs->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
ugs->shared = 1;
|
||||
if (ugs->fd == -1) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
exit(1);
|
||||
}
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
|
||||
int fd_socket = atoi(ugs->name+5);
|
||||
if (fd_socket >= 0) {
|
||||
ugs->fd = fd_socket;
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
if (!ugs->name) {
|
||||
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ugs->port = strchr(ugs->name, ':');
|
||||
if (ugs->fd == -1) {
|
||||
if (ugs->port) {
|
||||
ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port);
|
||||
ugs->port++;
|
||||
ugs->port_len = strlen(ugs->port);
|
||||
}
|
||||
else {
|
||||
ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
// put socket in non-blocking mode
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
uwsgi_log("%s bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
else if (ugs->subscription) {
|
||||
if (ugs->fd == -1) {
|
||||
ugs->fd = bind_to_udp(ugs->name, 0, 0);
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
}
|
||||
uwsgi_log("%s subscription server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
#ifdef UWSGI_SCTP
|
||||
else if (ugs->sctp) {
|
||||
if (ugs->fd == -1) {
|
||||
ugs->fd = bind_to_sctp(ugs->name);
|
||||
}
|
||||
uwsgi_log("%s SCTP server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void *uwsgi_corerouter_setup_event_queue(char *gw_id, int id, int nevents, int *efd, int cheap) {
|
||||
|
||||
*efd = event_queue_init();
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(gw_id, ugs->owner)) {
|
||||
if (!cheap || ugs->subscription) {
|
||||
event_queue_add_fd_read(*efd, ugs->fd);
|
||||
}
|
||||
ugs->gateway = &ushared->gateways[id];
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
|
||||
return event_queue_alloc(nevents);
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused)) uwsgi_corerouter_manage_subscription(char *gw_id, int id, struct uwsgi_gateway_socket *ugs, int queue, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 0;
|
||||
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
|
||||
}
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (node->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(subscriptions, node);
|
||||
}
|
||||
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
|
||||
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// propagate the subscription to other nodes
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (i == id)
|
||||
continue;
|
||||
if (!strcmp(ushared->gateways[i].name, gw_id)) {
|
||||
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
|
||||
uwsgi_error("send()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused)) uwsgi_corerouter_manage_internal_subscription(char *gw_id, int queue, int fd, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
|
||||
|
||||
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(queue, fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 0;
|
||||
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
|
||||
}
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (node->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(subscriptions, node);
|
||||
}
|
||||
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
|
||||
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,6 +33,22 @@ void linux_namespace_start(void *argv) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
|
||||
pid = waitpid(pid, &waitpid_status, 0);
|
||||
if (pid < 0) {
|
||||
|
||||
@@ -1,217 +1,487 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
if (!uli) {
|
||||
uwsgi.registered_locks = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
|
||||
uwsgi.registered_locks->id = id;
|
||||
uwsgi.registered_locks->pid = 0;
|
||||
if (rw) {
|
||||
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
}
|
||||
else {
|
||||
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
|
||||
}
|
||||
uwsgi.registered_locks->rw = rw;
|
||||
uwsgi.registered_locks->next = NULL;
|
||||
return uwsgi.registered_locks;
|
||||
}
|
||||
|
||||
while(uli) {
|
||||
if (!uli->next) {
|
||||
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
|
||||
if (rw) {
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
}
|
||||
else {
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
|
||||
}
|
||||
uli->next->id = id;
|
||||
uli->next->pid = 0;
|
||||
uli->next->rw = rw;
|
||||
uli->next->next = NULL;
|
||||
return uli->next;
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
uwsgi_log("*** DANGER: unable to allocate lock %s ***\n", id);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_MUTEX
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
|
||||
#else
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
|
||||
#define UWSGI_RWLOCK_SIZE 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) {
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
|
||||
if (pthread_mutexattr_init(&attr)) {
|
||||
uwsgi_log("unable to allocate mutexattr structure\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
|
||||
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||||
uwsgi_log("unable to share mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
|
||||
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
uli->can_deadlock = 1;
|
||||
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_rlock(void *lock) {
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock(lock);
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
#else
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
|
||||
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_wlock(void *lock) {
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock(lock);
|
||||
uwsgi_lock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock(void *lock) {
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_unlock(lock);
|
||||
uwsgi_lock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_unlock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_init(lock);
|
||||
return uwsgi_lock_fast_init(uli);
|
||||
#else
|
||||
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
|
||||
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
|
||||
if (pthread_rwlockattr_init(&attr)) {
|
||||
uwsgi_log("unable to allocate rwlock structure\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
|
||||
|
||||
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||||
uwsgi_log("unable to share rwlock\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
|
||||
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize rwlock\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_rwlockattr_destroy(&attr);
|
||||
|
||||
uli->can_deadlock = 1;
|
||||
|
||||
return uli;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#elif defined(UWSGI_LOCK_USE_UMTX)
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_UMTX
|
||||
/* Warning: FreeBSD is still not ready for process-shared UMTX */
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/umtx.h>
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
umtx_init((struct umtx*) lock);
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
umtx_init((struct umtx*) uli->lock_ptr);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
umtx_lock(lock, 1);
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
umtx_unlock(lock, 1);
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
|
||||
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
|
||||
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
|
||||
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
|
||||
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
memset(lock, 0, sizeof(OSSpinLock));
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
OSSpinLockLock((OSSpinLock *) lock);
|
||||
OSSpinLockLock((OSSpinLock *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
OSSpinLockUnlock((OSSpinLock *) lock);
|
||||
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (OSSpinLockTry((OSSpinLock *) uli->lock_ptr)) {
|
||||
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
#define uwsgi_lock_fast_check uwsgi_lock_ipcsem_check
|
||||
#define uwsgi_lock_fast uwsgi_lock_ipcsem
|
||||
#define uwsgi_unlock_fast uwsgi_unlock_ipcsem
|
||||
|
||||
#define uwsgi_rwlock_fast_init uwsgi_rwlock_ipcsem_init
|
||||
#define uwsgi_rwlock_fast_check uwsgi_rwlock_ipcsem_check
|
||||
|
||||
#define uwsgi_rlock_fast uwsgi_rlock_ipcsem
|
||||
#define uwsgi_wlock_fast uwsgi_wlock_ipcsem
|
||||
#define uwsgi_rwunlock_fast uwsgi_rwunlock_ipcsem
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(int)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(int)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_FLOCK
|
||||
// used by ftok
|
||||
static int counter = 1;
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
ushort *array;
|
||||
} semu ;
|
||||
int semid;
|
||||
key_t myKey;
|
||||
|
||||
#define UWSGI_LOCK_SIZE 8
|
||||
#define UWSGI_RWLOCK_SIZE 8
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
semid = semget(myKey, 1, IPC_CREAT|0666);
|
||||
}
|
||||
else {
|
||||
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
|
||||
}
|
||||
|
||||
FILE *tf = tmpfile();
|
||||
int fd;
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
memcpy(uli->lock_ptr, &semid, sizeof(int));
|
||||
|
||||
if (!tf) {
|
||||
uwsgi_error_open("temp lock file");
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = fileno(tf);
|
||||
|
||||
memcpy(lock, &fd, sizeof(int));
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
int fd;
|
||||
memcpy(&fd, lock, sizeof(int));
|
||||
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
|
||||
int semid;
|
||||
struct sembuf sb;
|
||||
sb.sem_num = 0;
|
||||
sb.sem_op = -1;
|
||||
sb.sem_flg = SEM_UNDO;
|
||||
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
|
||||
if (semop(semid, &sb, 1)) {
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
int fd;
|
||||
memcpy(&fd, lock, sizeof(int));
|
||||
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
|
||||
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
int semid;
|
||||
struct sembuf sb;
|
||||
sb.sem_num = 0;
|
||||
sb.sem_op = 1;
|
||||
sb.sem_flg = SEM_UNDO;
|
||||
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
|
||||
if (semop(semid, &sb, 1)) {
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
|
||||
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
|
||||
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
|
||||
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
|
||||
|
||||
// ipc cannot deadlock
|
||||
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers) goto clear;
|
||||
|
||||
if (uwsgi.mywid == 0) goto clear;
|
||||
|
||||
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
|
||||
|
||||
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
|
||||
|
||||
return;
|
||||
|
||||
clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
|
||||
|
||||
void *uwsgi_mmap_shared_lock() {
|
||||
void *addr = NULL;
|
||||
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
|
||||
if (addr == NULL) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
while(uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void *uwsgi_mmap_shared_rwlock() {
|
||||
void *addr = NULL;
|
||||
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
|
||||
if (addr == NULL) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
|
||||
|
||||
|
||||
void uwsgi_setup_locking() {
|
||||
|
||||
// use the fastest avaikable locking
|
||||
if (uwsgi.lock_engine) {
|
||||
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_log("lock engine: ipcsem\n");
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
|
||||
uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
|
||||
uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
|
||||
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
|
||||
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
|
||||
uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
|
||||
uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
|
||||
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
|
||||
uwsgi.lock_size = 8;
|
||||
uwsgi.rwlock_size = 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
#ifdef UWSGI_IPCSEM_ATEXIT
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
#endif
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
|
||||
uwsgi.lock_ops.lock = uwsgi_lock_fast;
|
||||
uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
|
||||
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
|
||||
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
|
||||
uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
|
||||
uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
|
||||
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
|
||||
uwsgi.lock_size = UWSGI_LOCK_SIZE;
|
||||
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fcntl_lock(int fd) {
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
int ret = fcntl(fd, F_SETLKW, &fl);
|
||||
if (ret < 0)
|
||||
uwsgi_error("fcntl()");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_fcntl_is_locked(int fd) {
|
||||
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
if (fcntl(fd, F_SETLK, &fl)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,97 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_check_logrotate(void) {
|
||||
|
||||
char message[1024];
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
|
||||
need_reopen = 1;
|
||||
}
|
||||
|
||||
if (need_rotation) {
|
||||
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) time(NULL));
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
else if (need_reopen) {
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) time(NULL), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// optimize this (please)
|
||||
@@ -48,7 +139,8 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
if (wsgi_req->do_not_log) return ;
|
||||
if (wsgi_req->do_not_log)
|
||||
return;
|
||||
|
||||
if (wsgi_req->app_id >= 0) {
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
@@ -58,7 +150,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
via = msg1;
|
||||
}
|
||||
#endif
|
||||
@@ -93,12 +185,9 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
#else
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
@@ -107,35 +196,16 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
|
||||
(int) uwsgi.mypid,
|
||||
wsgi_req->app_id,
|
||||
app_req,
|
||||
(unsigned long long ) uwsgi.workers[0].requests,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
|
||||
wsgi_req->remote_user_len, wsgi_req->remote_user,
|
||||
wsgi_req->var_cnt,
|
||||
wsgi_req->uh.pktsize,
|
||||
24, time_request,
|
||||
wsgi_req->method_len, wsgi_req->method,
|
||||
wsgi_req->uri_len, wsgi_req->uri,
|
||||
(unsigned long long) wsgi_req->response_size,
|
||||
rt, tsize,
|
||||
via,
|
||||
wsgi_req->protocol_len, wsgi_req->protocol,
|
||||
wsgi_req->status,
|
||||
wsgi_req->header_cnt,
|
||||
(unsigned long long) wsgi_req->headers_size,
|
||||
wsgi_req->switches, wsgi_req->async_id);
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
|
||||
logvec[logvecpos].iov_base = logpkt;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
|
||||
// do not check for errors
|
||||
rlen = writev(2, logvec, logvecpos+1);
|
||||
rlen = writev(2, logvec, logvecpos + 1);
|
||||
}
|
||||
|
||||
void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
*vsz = syscall(356);
|
||||
@@ -146,7 +216,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
|
||||
uwsgi_log("warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
@@ -157,7 +227,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
procfd = open("/proc/self/psinfo", O_RDONLY);
|
||||
if (procfd >= 0) {
|
||||
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
*rss = (uint64_t) info.pr_rssize * 1024;
|
||||
*vsz = (uint64_t) info.pr_size * 1024;
|
||||
}
|
||||
@@ -215,9 +285,9 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
*vsz = 0;
|
||||
*rss = 0;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
*vsz += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
if ((ai.protection & B_WRITE_AREA) != 0) {
|
||||
*rss += ai.ram_size;
|
||||
}
|
||||
}
|
||||
@@ -225,27 +295,27 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, char *, size_t)) {
|
||||
void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
|
||||
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
|
||||
|
||||
if (!ul) {
|
||||
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
ul = uwsgi.loggers;
|
||||
}
|
||||
else {
|
||||
while(ul) {
|
||||
old_ul = ul;
|
||||
ul = ul->next;
|
||||
}
|
||||
if (!ul) {
|
||||
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
ul = uwsgi.loggers;
|
||||
}
|
||||
else {
|
||||
while (ul) {
|
||||
old_ul = ul;
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
old_ul->next = ul;
|
||||
}
|
||||
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
old_ul->next = ul;
|
||||
}
|
||||
|
||||
ul->name = name;
|
||||
ul->func = func;
|
||||
ul->next = NULL;
|
||||
ul->name = name;
|
||||
ul->func = func;
|
||||
ul->next = NULL;
|
||||
ul->configured = 0;
|
||||
ul->fd = -1;
|
||||
ul->data = NULL;
|
||||
@@ -259,11 +329,11 @@ void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, ch
|
||||
struct uwsgi_logger *uwsgi_get_logger(char *name) {
|
||||
struct uwsgi_logger *ul = uwsgi.loggers;
|
||||
|
||||
while(ul) {
|
||||
while (ul) {
|
||||
if (!strcmp(ul->name, name)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
[uwsgi]
|
||||
|
||||
for = 4031 14032 4033 14034 24035
|
||||
socket = /tmp/%(_)/uwsgi.sock
|
||||
socket = 192.*:%(_)
|
||||
print = ciao %(_) hello %(_) bye %(_)
|
||||
endfor =
|
||||
|
||||
|
||||
socket = :4045
|
||||
socket = :4046
|
||||
socket = :4047
|
||||
socket = :4048
|
||||
|
||||
|
||||
socket = :4049
|
||||
socket = :4050
|
||||
socket = :4051
|
||||
|
||||
show-config =
|
||||
|
||||
if-env = PIPPO
|
||||
print =
|
||||
print = PIPPO e' definita e il suo valore e' %(_) boh
|
||||
endif =
|
||||
|
||||
socket = :5051
|
||||
socket = :5052
|
||||
socket = :5053
|
||||
socket = :5054
|
||||
|
||||
if-exists = /etc/services
|
||||
print = il file %(_) esiste $(PATH)
|
||||
endif =
|
||||
|
||||
if-exists = /etc/foobar
|
||||
print = il file %(_) esiste $(PATH)
|
||||
endif =
|
||||
|
||||
socket = :6060
|
||||
if-file = /etc/fstab
|
||||
socket = :7171
|
||||
endif =
|
||||
|
||||
ifdir = /tmp
|
||||
print = %(_) is a directory
|
||||
endif=
|
||||
@@ -40,9 +40,9 @@ void *simple_loop(void *arg1) {
|
||||
long core_id = (long) arg1;
|
||||
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
|
||||
int i;
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
int i;
|
||||
//PyThreadState *pts;
|
||||
sigset_t smask;
|
||||
|
||||
@@ -55,8 +55,11 @@ void *simple_loop(void *arg1) {
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
@@ -128,8 +131,11 @@ void *zeromq_loop(void *arg1) {
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void expire_rb_timeouts(struct rb_root *root) {
|
||||
}
|
||||
}
|
||||
|
||||
void master_log(void) {
|
||||
int uwsgi_master_log(void) {
|
||||
|
||||
char log_buf[4096];
|
||||
|
||||
@@ -81,21 +81,33 @@ void master_log(void) {
|
||||
rlen = write(uwsgi.original_log_fd, log_buf, rlen);
|
||||
}
|
||||
// TODO allow uwsgi.logger = func
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *logger_thread_loop(void *noarg) {
|
||||
struct pollfd logpoll;
|
||||
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
logpoll.events = POLLIN;
|
||||
logpoll.fd = uwsgi.shared->worker_log_pipe[0];
|
||||
|
||||
for(;;) {
|
||||
int ret = poll(&logpoll, 1, -1);
|
||||
if (ret > 0 && logpoll.revents & POLLIN) {
|
||||
master_log();
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
uwsgi_master_log();
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
@@ -270,8 +282,6 @@ int master_loop(char **argv, char **environ) {
|
||||
int rlen;
|
||||
|
||||
int check_interval = 1;
|
||||
uint64_t overload_count = 0;
|
||||
uint64_t idle_count = 0;
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct rb_root *rb_timers = uwsgi_init_rb_timer();
|
||||
@@ -315,14 +325,15 @@ int master_loop(char **argv, char **environ) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding %d to signal poll (spooler)\n", uwsgi.shared->spooler_signal_pipe[0]);
|
||||
#endif
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.mules_cnt > 0) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->mule_signal_pipe[0]);
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (!uwsgi.threaded_logger) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -492,9 +503,9 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_mule(i + 1);
|
||||
}
|
||||
|
||||
// spawn fat gateways
|
||||
for (i = 0; i < uwsgi.gateways_cnt; i++) {
|
||||
if (uwsgi.gateways[i].pid == 0) {
|
||||
// spawn gateways
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid == 0) {
|
||||
gateway_respawn(i);
|
||||
}
|
||||
}
|
||||
@@ -530,20 +541,36 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
|
||||
while (touch_reload) {
|
||||
struct stat tr_st;
|
||||
if (stat(touch_reload->value, &tr_st)) {
|
||||
uwsgi_log("unable to stat() %s, reload will be triggered as soon as the file is created\n", touch_reload->value);
|
||||
touch_reload->custom = 0;
|
||||
// update touches timestamps
|
||||
uwsgi_check_touches(uwsgi.touch_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_logrotate);
|
||||
uwsgi_check_touches(uwsgi.touch_logreopen);
|
||||
|
||||
// setup cheaper algos
|
||||
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
|
||||
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
|
||||
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
if (uwsgi.requested_cheaper_algo) {
|
||||
uwsgi.cheaper_algo = NULL;
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
while(uca) {
|
||||
if (!strcmp(uca->name, uwsgi.requested_cheaper_algo)) {
|
||||
uwsgi.cheaper_algo = uca->func;
|
||||
break;
|
||||
}
|
||||
uca = uca->next;
|
||||
}
|
||||
else {
|
||||
touch_reload->custom = (uint64_t) tr_st.st_mtime;
|
||||
|
||||
if (!uwsgi.cheaper_algo) {
|
||||
uwsgi_log("unable to find requested cheaper algorithm, falling back to spare\n");
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
}
|
||||
touch_reload = touch_reload->next;
|
||||
|
||||
}
|
||||
|
||||
// here really starts the master loop
|
||||
|
||||
for (;;) {
|
||||
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
|
||||
|
||||
@@ -552,7 +579,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.gp[i]->master_cycle();
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_cycle) {
|
||||
uwsgi.p[i]->master_cycle();
|
||||
}
|
||||
@@ -634,76 +661,13 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
// cheaper management
|
||||
if (uwsgi.cheaper && !uwsgi.cheap && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].busy == 0) {
|
||||
if (overload_count > 0)
|
||||
overload_count--;
|
||||
goto healthy;
|
||||
}
|
||||
}
|
||||
}
|
||||
overload_count++;
|
||||
idle_count = 0;
|
||||
}
|
||||
|
||||
healthy:
|
||||
if (uwsgi.cheaper && !uwsgi.cheap && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
if (overload_count > 3) {
|
||||
// activate the first available worker
|
||||
int decheaped = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
overload_count = 0;
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (overload_count == 0) {
|
||||
// how many active workers ?
|
||||
idle_count++;
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
// find the oldest worker and cheap it
|
||||
if (active_workers > uwsgi.cheaper_count + 1 || (idle_count > 60 && active_workers > uwsgi.cheaper_count)) {
|
||||
time_t oldest_worker_spawn = INT_MAX;
|
||||
int oldest_worker = 0;
|
||||
idle_count = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
|
||||
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
|
||||
oldest_worker = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldest_worker > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
// wakeup task in case of wait
|
||||
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
|
||||
overload_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!uwsgi_calc_cheaper()) return 0;
|
||||
}
|
||||
|
||||
|
||||
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 + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
@@ -711,80 +675,18 @@ int master_loop(char **argv, char **environ) {
|
||||
exit(0);
|
||||
}
|
||||
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 + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf(_SC_OPEN_MAX));
|
||||
for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (i == uwsgi_sock->fd) {
|
||||
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (uwsgi.has_emperor) {
|
||||
if (i == uwsgi.emperor_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
dup2(uwsgi.original_log_fd, 1);
|
||||
dup2(1, 2);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
#ifdef __APPLE__
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
#else
|
||||
close(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
#else
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
argv[0] = uwsgi.binary_path;
|
||||
//strcpy (argv[0], uwsgi.binary_path);
|
||||
execvp(uwsgi.binary_path, argv);
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!uwsgi.cheap) {
|
||||
|
||||
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
|
||||
if (uwsgi.numproc > 0 || ushared->gateways_cnt > 0 || uwsgi.daemons_cnt > 0) {
|
||||
master_has_children = 1;
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.spoolers) {
|
||||
master_has_children = 1;
|
||||
}
|
||||
#endif
|
||||
@@ -903,7 +805,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (uwsgi.log_master && !uwsgi.threaded_logger) {
|
||||
if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) {
|
||||
master_log();
|
||||
uwsgi_master_log();
|
||||
goto health_cycle;
|
||||
}
|
||||
}
|
||||
@@ -917,51 +819,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
if (interesting_fd == uwsgi.zerg_server_fd) {
|
||||
struct sockaddr_un zsun;
|
||||
socklen_t zsun_len = sizeof(struct sockaddr_un);
|
||||
int zerg_client = accept(uwsgi.zerg_server_fd, (struct sockaddr *) &zsun, &zsun_len);
|
||||
if (zerg_client < 0) {
|
||||
uwsgi_error("zerg: accept()");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct msghdr zerg_msg;
|
||||
void *zerg_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets)));
|
||||
struct iovec zerg_iov;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
zerg_iov.iov_base = "uwsgi-zerg";
|
||||
zerg_iov.iov_len = 10;
|
||||
|
||||
zerg_msg.msg_name = NULL;
|
||||
zerg_msg.msg_namelen = 0;
|
||||
zerg_msg.msg_iov = &zerg_iov;
|
||||
zerg_msg.msg_iovlen = 1;
|
||||
zerg_msg.msg_flags = 0;
|
||||
zerg_msg.msg_control = zerg_msg_control;
|
||||
zerg_msg.msg_controllen = CMSG_SPACE(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&zerg_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * uwsgi_count_sockets(uwsgi.sockets));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
unsigned char *zerg_fd_ptr = CMSG_DATA(cmsg);
|
||||
while (uwsgi_sock) {
|
||||
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
|
||||
zerg_fd_ptr += sizeof(int);
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (sendmsg(zerg_client, &zerg_msg, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
|
||||
close(zerg_client);
|
||||
|
||||
free(zerg_msg_control);
|
||||
uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL);
|
||||
goto health_cycle;
|
||||
}
|
||||
}
|
||||
@@ -980,6 +838,8 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
grace_them_all(0);
|
||||
}
|
||||
}
|
||||
@@ -1058,7 +918,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
// loop the various udp manager until one returns true
|
||||
udp_managed = 0;
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->manage_udp) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
udp_managed = 1;
|
||||
@@ -1186,14 +1046,13 @@ int master_loop(char **argv, char **environ) {
|
||||
else {
|
||||
uwsgi_log_verbose("lost connection with worker %d\n", i);
|
||||
close(interesting_fd);
|
||||
//uwsgi.workers[i].pipe[0] = -1;
|
||||
}
|
||||
goto health_cycle;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
// check for spooler signal
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.spoolers) {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
|
||||
rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
@@ -1201,7 +1060,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("received uwsgi signal %d from the spooler\n", uwsgi_signal);
|
||||
uwsgi_log_verbose("received uwsgi signal %d from a spooler\n", uwsgi_signal);
|
||||
#endif
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
@@ -1211,9 +1070,32 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
goto health_cycle;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for mules signal
|
||||
if (uwsgi.mules_cnt > 0) {
|
||||
if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) {
|
||||
rlen = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("received uwsgi signal %d from a mule\n", uwsgi_signal);
|
||||
#endif
|
||||
uwsgi_route_signal(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("lost connection with a mule\n");
|
||||
close(interesting_fd);
|
||||
}
|
||||
goto health_cycle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1223,51 +1105,12 @@ int master_loop(char **argv, char **environ) {
|
||||
continue;
|
||||
}
|
||||
uwsgi.current_time = now;
|
||||
|
||||
// checking logsize
|
||||
if (uwsgi.logfile) {
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) time(NULL));
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
char message[1024];
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
rlen = write(uwsgi.original_log_fd, message, ret);
|
||||
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// close 2, reopen logfile dup'it and gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
uwsgi_check_logrotate();
|
||||
}
|
||||
|
||||
|
||||
// this will be incremented at (more or less) regular intervals
|
||||
uwsgi.master_cycles++;
|
||||
|
||||
@@ -1342,6 +1185,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
// get listen_queue status
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
@@ -1393,10 +1237,13 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
#endif
|
||||
}
|
||||
kill(uwsgi.workers[i].pid, SIGUSR2);
|
||||
// allow SIGUSR2 to be delivered
|
||||
sleep(1);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
kill(uwsgi.workers[i].pid, SIGUSR2);
|
||||
// allow SIGUSR2 to be delivered
|
||||
sleep(1);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
}
|
||||
// to avoid races
|
||||
uwsgi.workers[i].harakiri = 0;
|
||||
}
|
||||
@@ -1420,6 +1267,18 @@ int master_loop(char **argv, char **environ) {
|
||||
// need to find a better way
|
||||
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
|
||||
}
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways_harakiri[i] > 0) {
|
||||
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
kill(ushared->gateways[i].pid, SIGKILL);
|
||||
}
|
||||
ushared->gateways_harakiri[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].harakiri > 0) {
|
||||
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
|
||||
@@ -1430,12 +1289,14 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid > 0 && uwsgi.shared->spooler_harakiri > 0) {
|
||||
if (uwsgi.shared->spooler_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uwsgi.shared->spooler_pid);
|
||||
kill(uwsgi.shared->spooler_pid, SIGKILL);
|
||||
uwsgi.shared->spooler_harakiri = 0;
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while(uspool) {
|
||||
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1457,7 +1318,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// resubscribe every 10 cycles by default
|
||||
if (uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) {
|
||||
if ((uwsgi.subscriptions && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
uwsgi_subscribe(subscriptions->value, 0);
|
||||
@@ -1480,43 +1341,63 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// check touch_reload
|
||||
struct uwsgi_string_list *touch_reload = uwsgi.touch_reload;
|
||||
while (touch_reload && !uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
struct stat tr_st;
|
||||
if (stat(touch_reload->value, &tr_st)) {
|
||||
touch_reload->custom = 0;
|
||||
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
char *touched = uwsgi_check_touches(uwsgi.touch_reload);
|
||||
if (touched) {
|
||||
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touched);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if ((uint64_t) tr_st.st_mtime > touch_reload->custom) {
|
||||
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", touch_reload->value);
|
||||
grace_them_all(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
touch_reload = touch_reload->next;
|
||||
}
|
||||
|
||||
|
||||
// now check for lb pool
|
||||
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (diedpid > 0) {
|
||||
// check for deadlocks first
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
while(uli) {
|
||||
if (!uli->can_deadlock) goto nextlock;
|
||||
pid_t locked_pid = 0;
|
||||
if (uli->rw) {
|
||||
locked_pid = uwsgi_rwlock_check(uli);
|
||||
}
|
||||
else {
|
||||
locked_pid = uwsgi_lock_check(uli);
|
||||
}
|
||||
if (locked_pid == diedpid) {
|
||||
uwsgi_log("[deadlock-detector] pid %d was holding lock %s (%p)\n", (int) diedpid, uli->id, uli->lock_ptr);
|
||||
if (uli->rw) {
|
||||
uwsgi_rwunlock(uli);
|
||||
}
|
||||
else {
|
||||
uwsgi_unlock(uli);
|
||||
}
|
||||
}
|
||||
nextlock:
|
||||
uli = uli->next;
|
||||
}
|
||||
}
|
||||
// reload gateways and daemons only on normal workflow
|
||||
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
/* reload the spooler */
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (diedpid == uwsgi.shared->spooler_pid) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
pid_found = 0;
|
||||
while(uspool) {
|
||||
if (uspool->pid > 0 && diedpid == uspool->pid) {
|
||||
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
|
||||
uwsgi.spooler_respawned++;
|
||||
uwsgi.shared->spooler_pid = spooler_start();
|
||||
//event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
continue;
|
||||
uspool->respawned++;
|
||||
uspool->pid = spooler_start(uspool);
|
||||
pid_found = 1;
|
||||
break;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
|
||||
if (pid_found)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
pid_found = 0;
|
||||
@@ -1534,10 +1415,9 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
|
||||
/* reload the gateways */
|
||||
// TODO reload_gateway(diedpid);
|
||||
pid_found = 0;
|
||||
for (i = 0; i < uwsgi.gateways_cnt; i++) {
|
||||
if (uwsgi.gateways[i].pid == diedpid) {
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid == diedpid) {
|
||||
gateway_respawn(i);
|
||||
pid_found = 1;
|
||||
break;
|
||||
@@ -1548,7 +1428,7 @@ int master_loop(char **argv, char **environ) {
|
||||
continue;
|
||||
|
||||
/* reload the daemons */
|
||||
// TODO reload_gateway(diedpid);
|
||||
// TODO reload_daemons(diedpid);
|
||||
pid_found = 0;
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
@@ -1579,11 +1459,13 @@ int master_loop(char **argv, char **environ) {
|
||||
if (uwsgi.mywid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (diedpid == uwsgi.shared->spooler_pid) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while(uspool) {
|
||||
if (uspool->pid > 0 && diedpid == uspool->pid) {
|
||||
uwsgi_log("spooler (pid: %d) annihilated\n", (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1594,9 +1476,9 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gateways_cnt; i++) {
|
||||
if (uwsgi.gateways[i].pid == diedpid) {
|
||||
uwsgi_log("gateway %d (pid: %d) annihilated\n", i + 1, (int) diedpid);
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid == diedpid) {
|
||||
uwsgi_log("gateway %d (%s, pid: %d) annihilated\n", i + 1, ushared->gateways[i].fullname, (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
@@ -1647,23 +1529,34 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
continue;
|
||||
}
|
||||
gettimeofday(&last_respawn, NULL);
|
||||
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
|
||||
if (last_respawn.tv_sec <= uwsgi.respawn_delta + check_interval) {
|
||||
last_respawn_rate++;
|
||||
if (last_respawn_rate > uwsgi.numproc) {
|
||||
uwsgi_log("worker respawning too fast !!! i have to sleep a bit...\n");
|
||||
/* TODO, user configurable fork throttler */
|
||||
sleep(2);
|
||||
if (uwsgi.forkbomb_delay > 0) {
|
||||
uwsgi_log("worker respawning too fast !!! i have to sleep a bit (%d seconds)...\n", uwsgi.forkbomb_delay);
|
||||
/* use --forkbomb-delay 0 to disable sleeping */
|
||||
sleep(uwsgi.forkbomb_delay);
|
||||
}
|
||||
last_respawn_rate = 0;
|
||||
}
|
||||
}
|
||||
@@ -1679,4 +1572,5 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
+515
-114
@@ -2,7 +2,320 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void worker_wakeup() {}
|
||||
void worker_wakeup() {
|
||||
}
|
||||
|
||||
int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
needed_workers--;
|
||||
}
|
||||
if (needed_workers == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (needed_workers < 0) {
|
||||
int oldest_worker = 0;
|
||||
time_t oldest_worker_spawn = INT_MAX;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
|
||||
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
|
||||
oldest_worker = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldest_worker > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
// wakeup task in case of wait
|
||||
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
|
||||
|
||||
when all of the workers are busy, the overload_count is incremented.
|
||||
as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
|
||||
at most cheaper_step (default to 1) new workers are spawned.
|
||||
|
||||
when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
|
||||
If overload_count reaches 0, the system will count active workers (the ones uncheaped) and busy workers (the ones running a request)
|
||||
if there is exacly 1 free worker we are in "stable state" (1 spare worker available). no worker will be touched.
|
||||
if the number of active workers is higher than uwsgi.cheaper_count and at least uwsgi.cheaper_overload cycles are passed from the last
|
||||
"cheap it" procedure, then cheap a worker.
|
||||
|
||||
Example:
|
||||
10 processes
|
||||
2 cheaper
|
||||
2 cheaper step
|
||||
3 cheaper_overload
|
||||
1 second master cycle
|
||||
|
||||
there are 7 workers running (triggered by some kind of spike activity).
|
||||
Of this, 6 are busy, 1 is free. We are in stable state.
|
||||
After a bit the spike disappear and idle_count start to increase.
|
||||
|
||||
After 3 seconds (uwsgi.cheaper_overload cycles) the oldest worker will be cheaped. This will happens
|
||||
every seconds (uwsgi.cheaper_overload cycles) til the number of workers is == uwsgi.cheaper_count.
|
||||
|
||||
If during the "cheap them all" procedure, an overload condition come again (another spike) the "cheap them all"
|
||||
will be interrupted.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int uwsgi_cheaper_algo_spare(void) {
|
||||
|
||||
int i;
|
||||
static uint64_t overload_count = 0;
|
||||
static uint64_t idle_count = 0;
|
||||
|
||||
// step 1 -> count the number of busy workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
|
||||
if (uwsgi.workers[i].busy == 0) {
|
||||
if (overload_count > 0)
|
||||
overload_count--;
|
||||
goto healthy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overload_count++;
|
||||
idle_count = 0;
|
||||
|
||||
healthy:
|
||||
|
||||
// are we overloaded ?
|
||||
if (overload_count > uwsgi.cheaper_overload) {
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("overloaded !!!\n");
|
||||
#endif
|
||||
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// reset overload
|
||||
overload_count = 0;
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
}
|
||||
// we are no more overloaded
|
||||
else if (overload_count == 0) {
|
||||
// how many active workers ?
|
||||
int active_workers = 0;
|
||||
int busy_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
if (uwsgi.workers[i].busy == 1)
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("active workers %d busy_workers %d\n", active_workers, busy_workers);
|
||||
#endif
|
||||
|
||||
// special condition: uwsgi.cheaper running workers and 1 free
|
||||
if (active_workers > busy_workers && active_workers - busy_workers == 1) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("stable status: 1 spare worker\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
idle_count++;
|
||||
|
||||
if (active_workers > uwsgi.cheaper_count && idle_count % uwsgi.cheaper_overload == 0) {
|
||||
// we are in "cheap them all"
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, backlog algorithm (supported only on Linux) --
|
||||
|
||||
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
|
||||
Decrese when lower.
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_cheaper_algo_backlog(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->ti.tcpi_unacked;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int)uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
|
||||
}
|
||||
else if (backlog < (int) uwsgi.cheaper_overload) {
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_workers > uwsgi.cheaper_count) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// reload uWSGI, close unneded file descriptor, restore the original environment and re-exec the binary
|
||||
|
||||
void uwsgi_reload(char **argv) {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int)uwsgi.max_fd);
|
||||
for (i = 3; i < (int)uwsgi.max_fd; i++) {
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (i == uwsgi_sock->fd) {
|
||||
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (uwsgi.has_emperor) {
|
||||
if (i == uwsgi.emperor_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[0]) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[1] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[1]) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
#ifdef __APPLE__
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
#else
|
||||
close(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
//strcpy (argv[0], uwsgi.binary_path);
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
dup2(uwsgi.original_log_fd, 1);
|
||||
dup2(1, 2);
|
||||
}
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
close(uwsgi.shared->worker_log_pipe[0]);
|
||||
}
|
||||
if (uwsgi.shared->worker_log_pipe[1] > -1) {
|
||||
close(uwsgi.shared->worker_log_pipe[1]);
|
||||
}
|
||||
}
|
||||
execvp(uwsgi.binary_path, argv);
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void master_check_cluster_nodes() {
|
||||
|
||||
@@ -33,7 +346,7 @@ void master_check_cluster_nodes() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
|
||||
int i;
|
||||
|
||||
@@ -43,48 +356,82 @@ void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
}
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
|
||||
if (i != wid) {
|
||||
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
|
||||
if (uwsgi.master_queue > -1)
|
||||
close(uwsgi.master_queue);
|
||||
// close gateways
|
||||
if (!ug) {
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
close(ushared->gateways[i].internal_subscription_pipe[0]);
|
||||
close(ushared->gateways[i].internal_subscription_pipe[1]);
|
||||
}
|
||||
}
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (ug && !strcmp(ug->name, ugs->owner)) {
|
||||
ugs = ugs->next;
|
||||
continue;
|
||||
}
|
||||
// do not close shared sockets !!!
|
||||
if (!ugs->shared) {
|
||||
close(ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.workers[i].signal_pipe[0]);
|
||||
if (i != wid) {
|
||||
if (uwsgi.workers[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.workers[i].signal_pipe[1]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.shared->mule_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->mule_signal_pipe[1]);
|
||||
if (uwsgi.shared->mule_queue_pipe[1] != -1)
|
||||
close(uwsgi.shared->mule_queue_pipe[1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.mules[i].signal_pipe[0]);
|
||||
if (muleid != i + 1) {
|
||||
if (uwsgi.mules[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.mules[i].signal_pipe[1]);
|
||||
if (uwsgi.mules[i].queue_pipe[1] != -1)
|
||||
close(uwsgi.mules[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.farms_cnt; i++) {
|
||||
if (uwsgi.farms[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.farms[i].signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
|
||||
if (uwsgi.shared->mule_queue_pipe[1] != -1) close(uwsgi.shared->mule_queue_pipe[1]);
|
||||
if (uwsgi.farms[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.farms[i].signal_pipe[1]);
|
||||
if (uwsgi.farms[i].queue_pipe[1] != -1)
|
||||
close(uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].signal_pipe[0] != -1) close(uwsgi.mules[i].signal_pipe[0]);
|
||||
if (muleid != i+1) {
|
||||
if (uwsgi.mules[i].signal_pipe[1] != -1) close(uwsgi.mules[i].signal_pipe[1]);
|
||||
if (uwsgi.mules[i].queue_pipe[1] != -1) close(uwsgi.mules[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
|
||||
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
@@ -92,6 +439,10 @@ int uwsgi_respawn_worker(int wid) {
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
int i;
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
|
||||
|
||||
if (pid == 0) {
|
||||
@@ -108,7 +459,7 @@ int uwsgi_respawn_worker(int wid) {
|
||||
// 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].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;
|
||||
@@ -121,18 +472,18 @@ int uwsgi_respawn_worker(int wid) {
|
||||
// reset the apps count with a copy from the master
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
|
||||
uwsgi_fixup_fds(wid, 0);
|
||||
uwsgi_fixup_fds(wid, 0, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -149,6 +500,11 @@ int uwsgi_respawn_worker(int wid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,8 +514,7 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi.current_time = now;
|
||||
uwsgi_cron_delta = localtime(&uwsgi.current_time);
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
@@ -205,9 +560,9 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (uwsgi.current_time - ucron->last_job > 60) {
|
||||
if (now - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = uwsgi.current_time;
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,8 +582,7 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uwsgi.current_time = now;
|
||||
uwsgi_cron_delta = localtime(&uwsgi.current_time);
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
@@ -257,30 +611,30 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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 (run_task == 1) {
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (uwsgi.current_time - current_cron->last_job > 60) {
|
||||
if (now - current_cron->last_job > 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (uwsgi_run_command(current_cron->command) >=0) {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
}
|
||||
current_cron->last_job = uwsgi.current_time;
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +651,7 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
void uwsgi_send_stats(int fd) {
|
||||
|
||||
int i,j;
|
||||
int i, j;
|
||||
struct sockaddr_un client_src;
|
||||
struct uwsgi_app *ua;
|
||||
socklen_t client_src_len = 0;
|
||||
@@ -322,9 +676,9 @@ void uwsgi_send_stats(int fd) {
|
||||
|
||||
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
|
||||
|
||||
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
fprintf(output, "\"pid\": %d,\n", (int) (getpid()));
|
||||
fprintf(output, "\"uid\": %d,\n", (int) (getuid()));
|
||||
fprintf(output, "\"gid\": %d,\n", (int) (getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
@@ -333,9 +687,8 @@ void uwsgi_send_stats(int fd) {
|
||||
if (uwsgi.daemons) {
|
||||
fprintf(output, "\"daemons\": [\n");
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while(ud) {
|
||||
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }",
|
||||
ud->command, (int) ud->pid, (unsigned long long) ud->respawns-1);
|
||||
while (ud) {
|
||||
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }", ud->command, (int) ud->pid, (unsigned long long) ud->respawns - 1);
|
||||
if (ud->next)
|
||||
fprintf(output, ",\n");
|
||||
else {
|
||||
@@ -346,57 +699,75 @@ void uwsgi_send_stats(int fd) {
|
||||
fprintf(output, "],\n");
|
||||
}
|
||||
|
||||
fprintf(output, "\"locks\": [\n");
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
while (uli) {
|
||||
if (uli->next) {
|
||||
fprintf(output, "\t{ \"%s\": %d },\n", uli->id, (int) uli->pid);
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\t{ \"%s\": %d }\n", uli->id, (int) uli->pid);
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
fprintf(output, "],\n");
|
||||
|
||||
fprintf(output, "\"workers\": [\n");
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
fprintf(output,"\t{");
|
||||
fprintf(output, "\t{");
|
||||
|
||||
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);
|
||||
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\", ");
|
||||
fprintf(output, "\"status\": \"cheap\", ");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output, "\"status\": \"pause\", ");
|
||||
}
|
||||
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);
|
||||
fprintf(output, "\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output,"\"status\": \"busy\", ");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"\"status\": \"idle\", ");
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output, "\"status\": \"busy\", ");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\"status\": \"idle\", ");
|
||||
}
|
||||
}
|
||||
|
||||
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i+1].rss_size);
|
||||
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i+1].vsz_size);
|
||||
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i + 1].rss_size);
|
||||
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i + 1].vsz_size);
|
||||
|
||||
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i+1].running_time);
|
||||
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i+1].last_spawn);
|
||||
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i+1].respawn_count);
|
||||
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i+1].tx);
|
||||
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i+1].avg_response_time);
|
||||
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i + 1].running_time);
|
||||
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i + 1].last_spawn);
|
||||
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i + 1].respawn_count);
|
||||
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i + 1].tx);
|
||||
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i + 1].avg_response_time);
|
||||
|
||||
fprintf(output,"\"apps\": [\n");
|
||||
fprintf(output, "\"apps\": [\n");
|
||||
|
||||
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
|
||||
ua = &uwsgi.workers[i+1].apps[j];
|
||||
fprintf(output,"\t\t{ ");
|
||||
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
|
||||
ua = &uwsgi.workers[i + 1].apps[j];
|
||||
fprintf(output, "\t\t{ ");
|
||||
|
||||
fprintf(output, "\"id\": %d, ", j);
|
||||
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
|
||||
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
|
||||
|
||||
stats_send_llu( "\"requests\": %llu, ", ua->requests);
|
||||
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
|
||||
|
||||
stats_send_llu("\"startup_time\": %llu, ", ua->startup_time);
|
||||
|
||||
stats_send_llu("\"requests\": %llu, ", ua->requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", ua->exceptions);
|
||||
|
||||
if (ua->chdir) {
|
||||
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
|
||||
@@ -404,25 +775,55 @@ void uwsgi_send_stats(int fd) {
|
||||
else {
|
||||
fprintf(output, "\"chdir\": \"\" ");
|
||||
}
|
||||
|
||||
if (j == uwsgi.workers[i+1].apps_cnt-1) {
|
||||
fprintf(output,"}\n");
|
||||
|
||||
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output,"\t\t]");
|
||||
fprintf(output, "\t\t]");
|
||||
|
||||
if (i == uwsgi.numproc-1) {
|
||||
fprintf(output,"}\n");
|
||||
if (i == uwsgi.numproc - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output,"]}\n");
|
||||
fprintf(output, "]}\n");
|
||||
fclose(output);
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int(*func) (void)) {
|
||||
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
|
||||
if (!uca) {
|
||||
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
|
||||
uca = uwsgi.cheaper_algos;
|
||||
}
|
||||
else {
|
||||
while (uca) {
|
||||
if (!uca->next) {
|
||||
uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
|
||||
uca = uca->next;
|
||||
break;
|
||||
}
|
||||
uca = uca->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uca->name = name;
|
||||
uca->func = func;
|
||||
uca->next = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -19,4 +19,8 @@
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
</uwsgi>
|
||||
|
||||
<uwsgi>
|
||||
<socket>:3031</socket>
|
||||
</uwsgi>
|
||||
|
||||
</unbit>
|
||||
|
||||
@@ -41,20 +41,20 @@ void uwsgi_mule(int id) {
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = getpid();
|
||||
|
||||
uwsgi_fixup_fds(0, id);
|
||||
uwsgi_fixup_fds(0, id, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
|
||||
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
|
||||
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
@@ -62,7 +62,7 @@ void uwsgi_mule(int id) {
|
||||
|
||||
|
||||
if (uwsgi.mules[id-1].patch) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
|
||||
// never here
|
||||
@@ -184,7 +184,7 @@ void uwsgi_mule_handler() {
|
||||
}
|
||||
else {
|
||||
int i,found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->mule_msg) {
|
||||
if (uwsgi.p[i]->mule_msg(message, len)) {
|
||||
found = 1;
|
||||
@@ -356,3 +356,24 @@ clear:
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.mules_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.mules_patches, value);
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
|
||||
int i;
|
||||
|
||||
for(i=0;i<atoi(value);i++) {
|
||||
uwsgi.mules_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
|
||||
uwsgi.farms_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.farms_list, value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<uwsgi>
|
||||
|
||||
<!--
|
||||
|
||||
DO NOT USE <app> TAG !!!
|
||||
|
||||
It is deprecated and will be removed from 1.2
|
||||
|
||||
-->
|
||||
|
||||
<plugins>psgi</plugins>
|
||||
<plugins>rack</plugins>
|
||||
|
||||
<http>:9090</http>
|
||||
@@ -24,6 +33,8 @@
|
||||
<module>werkzeug.testapp:test_app</module>
|
||||
</app>
|
||||
|
||||
<app mountpoint="/foobar">werkzeug.testapp:test_app</app>
|
||||
|
||||
<app mountpoint="/trac">
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
</app>
|
||||
@@ -32,11 +43,12 @@
|
||||
<module>werkzeug.testapp:test_app</module>
|
||||
</app>
|
||||
|
||||
<!-- eval is broken -->
|
||||
<app mountpoint="/bzr">
|
||||
<eval>
|
||||
<eval>
|
||||
from bzrlib.transport.http import wsgi
|
||||
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
|
||||
</eval>
|
||||
</eval>
|
||||
</app>
|
||||
|
||||
<app domain="sirius002:9090">
|
||||
@@ -47,4 +59,8 @@ application = wsgi.make_app("mybzr", "/bzr", readonly=False)
|
||||
<rack>config2.ru</rack>
|
||||
</app>
|
||||
|
||||
<app mountpoint="precise64.local">
|
||||
<psgi>test.psgi</psgi>
|
||||
</app>
|
||||
|
||||
</uwsgi>
|
||||
|
||||
@@ -2,30 +2,16 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) {
|
||||
|
||||
void *plugin_handle;
|
||||
|
||||
char *plugin_name;
|
||||
char *plugin_entry_symbol;
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
static int plugin_already_loaded(const char *plugin) {
|
||||
int i;
|
||||
|
||||
char *colon = strchr(plugin, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
check:
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
@@ -33,7 +19,7 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +31,7 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
@@ -53,37 +39,78 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
|
||||
int need_free = 0;
|
||||
char *plugin_name = plugin;
|
||||
char *plugin_symbol_name_start = plugin;
|
||||
|
||||
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
|
||||
char *colon = strchr(plugin_name, ':');
|
||||
if (colon) {
|
||||
plugin = colon+1;
|
||||
colon[0] = 0;
|
||||
modifier = atoi(plugin_name);
|
||||
plugin_name = colon+1;
|
||||
colon[0] = ':';
|
||||
colon = NULL;
|
||||
goto check;
|
||||
}
|
||||
|
||||
if (absolute == 1) {
|
||||
plugin_name = uwsgi_concat2(plugin, "");
|
||||
// need to fix this... postpone until needed
|
||||
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
|
||||
}
|
||||
else if (absolute == 2) {
|
||||
plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin);
|
||||
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
|
||||
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
|
||||
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
|
||||
need_free = 1;
|
||||
}
|
||||
else {
|
||||
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
|
||||
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
|
||||
|
||||
plugin_symbol_name_start = plugin_name;
|
||||
|
||||
// step 1: check for absolute plugin (stop if it fails)
|
||||
if (strchr(plugin_name, '/')) {
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
goto end;
|
||||
}
|
||||
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
|
||||
plugin_symbol_name_start++;
|
||||
}
|
||||
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
char *plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (plugin_handle) {
|
||||
free(plugin_filename);
|
||||
break;
|
||||
}
|
||||
free(plugin_filename);
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
if (!plugin_handle) {
|
||||
char *plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
free(plugin_filename);
|
||||
}
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
if (!up) {
|
||||
// is it a link ?
|
||||
@@ -92,7 +119,7 @@ check:
|
||||
if ((linkpath_size = readlink(plugin_name, linkpath_buf, 1023)) > 0) {
|
||||
do {
|
||||
linkpath_buf[linkpath_size] = '\0';
|
||||
strcpy(linkpath, linkpath_buf);
|
||||
strncpy(linkpath, linkpath_buf, linkpath_size+1);
|
||||
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", linkpath);
|
||||
@@ -111,23 +138,41 @@ check:
|
||||
}
|
||||
}
|
||||
if (up) {
|
||||
if (!up->name) {
|
||||
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (plugin_already_loaded(up->name)) {
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (has_option) {
|
||||
struct option *lopt = up->options, *aopt;
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
int found = 0;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp(has_option, aopt->name)) {
|
||||
while (op && op->name) {
|
||||
if (!strcmp(has_option, op->name)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
lopt++;
|
||||
op++;
|
||||
}
|
||||
if (!found) {
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
free(plugin_name);
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
@@ -139,7 +184,8 @@ check:
|
||||
else {
|
||||
fill_plugin_table(up->modifier1, up);
|
||||
}
|
||||
free(plugin_name);
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
|
||||
if (up->on_load)
|
||||
@@ -149,7 +195,9 @@ check:
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
|
||||
free(plugin_name);
|
||||
end:
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+62
-41
@@ -2,12 +2,6 @@
|
||||
|
||||
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;
|
||||
@@ -15,41 +9,16 @@ struct uwsgi_carbon {
|
||||
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},
|
||||
struct uwsgi_option carbon_options[] = {
|
||||
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
|
||||
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
|
||||
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
|
||||
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
|
||||
{0, 0, 0, 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;
|
||||
@@ -94,6 +63,13 @@ void carbon_master_cycle() {
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
unsigned long long total_rss = 0;
|
||||
unsigned long long total_vsz = 0;
|
||||
unsigned long long total_tx = 0;
|
||||
unsigned long long total_avg_rt = 0; // total avg_rt
|
||||
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
|
||||
unsigned long long avg_rt_workers = 0; // number of workers used to calculate total avg_rt
|
||||
|
||||
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;}
|
||||
@@ -102,22 +78,67 @@ void carbon_master_cycle() {
|
||||
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;}
|
||||
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
total_vsz += uwsgi.workers[i].vsz_size;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
if (uwsgi.workers[i].cheaped) {
|
||||
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
|
||||
avg_rt = 0;
|
||||
}
|
||||
else {
|
||||
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
|
||||
avg_rt = uwsgi.workers[i].avg_response_time;
|
||||
avg_rt_workers++;
|
||||
total_avg_rt += uwsgi.workers[i].avg_response_time;
|
||||
}
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
total_tx += uwsgi.workers[i].tx;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (avg_rt_workers ? total_avg_rt / avg_rt_workers : 0), (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (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;
|
||||
}
|
||||
last_update = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin carbon_plugin = {
|
||||
|
||||
.name = "carbon",
|
||||
|
||||
.options = carbon_options,
|
||||
.manage_opt = carbon_opt,
|
||||
|
||||
.master_cycle = carbon_master_cycle,
|
||||
|
||||
.post_init = carbon_post_init,
|
||||
.init = carbon_init,
|
||||
};
|
||||
|
||||
+174
-92
@@ -5,56 +5,77 @@ extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_cgi {
|
||||
struct uwsgi_dyn_dict *mountpoint;
|
||||
struct uwsgi_dyn_dict *helpers;
|
||||
int buffer_size;
|
||||
size_t buffer_size;
|
||||
int timeout;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *unset;
|
||||
struct uwsgi_string_list *loadlib;
|
||||
int optimize;
|
||||
int from_docroot;
|
||||
int has_mountpoints;
|
||||
struct uwsgi_dyn_dict *default_cgi;
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
|
||||
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
|
||||
#define LONG_ARGS_CGI_MAP_HELPER LONG_ARGS_CGI_BASE + 2
|
||||
#define LONG_ARGS_CGI_BUFFER_SIZE LONG_ARGS_CGI_BASE + 3
|
||||
#define LONG_ARGS_CGI_TIMEOUT LONG_ARGS_CGI_BASE + 4
|
||||
#define LONG_ARGS_CGI_INDEX LONG_ARGS_CGI_BASE + 5
|
||||
#define LONG_ARGS_CGI_ALLOWED_EXT LONG_ARGS_CGI_BASE + 6
|
||||
#define LONG_ARGS_CGI_UNSET LONG_ARGS_CGI_BASE + 7
|
||||
#define LONG_ARGS_CGI_LOADLIB LONG_ARGS_CGI_BASE + 8
|
||||
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
struct option uwsgi_cgi_options[] = {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, value, strlen(value), NULL, 0);
|
||||
}
|
||||
else {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, value, val-value, val+1, strlen(val+1));
|
||||
}
|
||||
|
||||
{"cgi", required_argument, 0, LONG_ARGS_CGI},
|
||||
{"cgi-map-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
|
||||
{"cgi-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
|
||||
{"cgi-buffer-size", required_argument, 0, LONG_ARGS_CGI_BUFFER_SIZE},
|
||||
{"cgi-timeout", required_argument, 0, LONG_ARGS_CGI_TIMEOUT},
|
||||
{"cgi-index", required_argument, 0, LONG_ARGS_CGI_INDEX},
|
||||
{"cgi-allowed-ext", required_argument, 0, LONG_ARGS_CGI_ALLOWED_EXT},
|
||||
{"cgi-unset", required_argument, 0, LONG_ARGS_CGI_UNSET},
|
||||
{"cgi-loadlib", required_argument, 0, LONG_ARGS_CGI_LOADLIB},
|
||||
{"cgi-optimize", no_argument, &uc.optimize, 1},
|
||||
{"cgi-optimized", no_argument, &uc.optimize, 1},
|
||||
{"cgi-path-info", no_argument, &uc.path_info, 1},
|
||||
{0, 0, 0, 0},
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_dyn_dict_new(&uc.helpers, value, val-value, val+1, strlen(val+1));
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
{"cgi", required_argument, 0, "add a cgi mountpoint/directory/script", uwsgi_opt_add_cgi, NULL, 0},
|
||||
|
||||
{"cgi-map-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
|
||||
{"cgi-helper", required_argument, 0, "add a cgi map-helper", uwsgi_opt_add_cgi_maphelper, NULL, 0},
|
||||
|
||||
{"cgi-from-docroot", no_argument, 0, "blindly enable cgi in DOCUMENT_ROOT", uwsgi_opt_true, &uc.from_docroot, 0},
|
||||
|
||||
{"cgi-buffer-size", required_argument, 0, "set cgi buffer size", uwsgi_opt_set_64bit, &uc.buffer_size, 0},
|
||||
{"cgi-timeout", required_argument, 0, "set cgi script timeout", uwsgi_opt_set_int, &uc.timeout, 0},
|
||||
|
||||
{"cgi-index", required_argument, 0, "add a cgi index file", uwsgi_opt_add_string_list, &uc.index, 0},
|
||||
{"cgi-allowed-ext", required_argument, 0, "cgi allowed extension", uwsgi_opt_add_string_list, &uc.allowed_ext, 0},
|
||||
|
||||
{"cgi-unset", required_argument, 0, "unset specified environment variables", uwsgi_opt_add_string_list, &uc.unset, 0},
|
||||
|
||||
{"cgi-loadlib", required_argument, 0, "load a cgi shared library/optimizer", uwsgi_opt_add_string_list, &uc.loadlib, 0},
|
||||
{"cgi-optimize", no_argument, 0, "enable cgi realpath() optimizer", uwsgi_opt_true, &uc.optimize, 0},
|
||||
{"cgi-optimized", no_argument, 0, "enable cgi realpath() optimizer", uwsgi_opt_true, &uc.optimize, 0},
|
||||
|
||||
{"cgi-path-info", no_argument, 0, "disable PATH_INFO management in cgi scripts", uwsgi_opt_true, &uc.path_info, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
|
||||
}
|
||||
|
||||
void uwsgi_cgi_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
|
||||
|
||||
}
|
||||
|
||||
@@ -223,6 +244,7 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
i++;
|
||||
goto send_body;
|
||||
}
|
||||
// invalid header
|
||||
@@ -365,8 +387,9 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
|
||||
}
|
||||
|
||||
if (choosen_udd->status == 0) {
|
||||
char *tmp_udd = realpath(path, NULL);
|
||||
if (!tmp_udd) {
|
||||
char *tmp_udd = uwsgi_malloc(PATH_MAX+1);
|
||||
if (!realpath(path, tmp_udd)) {
|
||||
free(tmp_udd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -399,6 +422,8 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
int part_size = 0;
|
||||
struct stat st;
|
||||
|
||||
if (wsgi_req->path_info_len == 0) return 0;
|
||||
|
||||
if (ptr[0] == '/') part_size++;
|
||||
|
||||
for(i=0;i<wsgi_req->path_info_len-discard_base;i++) {
|
||||
@@ -449,10 +474,12 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char *argv[3];
|
||||
char **argv;
|
||||
int nargs = 0;
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
@@ -476,16 +503,23 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *docroot = NULL;
|
||||
|
||||
// check for file availability (and 'runnability')
|
||||
if (uc.from_docroot) {
|
||||
docroot = wsgi_req->document_root;
|
||||
docroot_len = wsgi_req->document_root_len;
|
||||
}
|
||||
else {
|
||||
docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
docroot_len = strlen(docroot);
|
||||
}
|
||||
|
||||
char *docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
|
||||
if (docroot == NULL) {
|
||||
if (docroot == NULL || docroot_len == 0) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
docroot_len = strlen(docroot);
|
||||
memcpy(full_path, docroot, docroot_len);
|
||||
|
||||
if (!is_a_file) {
|
||||
@@ -533,7 +567,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
if (S_ISDIR(cgi_stat.st_mode)) {
|
||||
|
||||
// add / to directories
|
||||
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
|
||||
if (wsgi_req->path_info_len == 0 || (wsgi_req->path_info_len > 0 && wsgi_req->path_info[wsgi_req->path_info_len-1] != '/')) {
|
||||
uwsgi_cgi_redirect_to_slash(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
@@ -548,6 +582,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
// add + 1 to ensure null byte
|
||||
memcpy(full_path+full_path_len, ci->value, ci->len + 1);
|
||||
if (!access(full_path, R_OK)) {
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@@ -563,9 +598,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
full_path_len = strlen(full_path);
|
||||
}
|
||||
|
||||
full_path_len = strlen(full_path);
|
||||
|
||||
int cgi_allowed = 1;
|
||||
struct uwsgi_string_list *allowed = uc.allowed_ext;
|
||||
@@ -612,13 +646,32 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int send_post_data = 0;
|
||||
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl && !wsgi_req->async_post) {
|
||||
send_post_data = 1;
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return -1;
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
if (send_post_data) {
|
||||
close(post_pipe[0]);
|
||||
close(post_pipe[1]);
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
@@ -627,6 +680,16 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
|
||||
if (send_post_data) {
|
||||
close(post_pipe[0]);
|
||||
if (write(post_pipe[1], wsgi_req->post_buffering_buf, wsgi_req->post_cl) != (ssize_t) wsgi_req->post_cl) {
|
||||
uwsgi_error("write()");
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
close(post_pipe[1]);
|
||||
}
|
||||
// wait for data
|
||||
char *headers_buf = uwsgi_malloc(uc.buffer_size);
|
||||
char *ptr = headers_buf;
|
||||
@@ -688,6 +751,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
clear:
|
||||
free(headers_buf);
|
||||
clear2:
|
||||
close(cgi_pipe[0]);
|
||||
|
||||
// now wait for process exit/death
|
||||
@@ -701,13 +765,35 @@ clear:
|
||||
// close all the fd except wsgi_req->poll.fd and 2;
|
||||
|
||||
for(i=0;i< (int)uwsgi.max_fd;i++) {
|
||||
if (send_post_data) {
|
||||
if (post_pipe[0] == i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (wsgi_req->async_post) {
|
||||
if (fileno((FILE*)wsgi_req->async_post) == i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
// now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1
|
||||
if (wsgi_req->poll.fd != 0) {
|
||||
// now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1
|
||||
if (send_post_data) {
|
||||
if (post_pipe[0] != 0) {
|
||||
dup2(post_pipe[0], 0);
|
||||
close(post_pipe[0]);
|
||||
}
|
||||
}
|
||||
else if (wsgi_req->async_post) {
|
||||
if (fileno((FILE*)wsgi_req->async_post) != 0) {
|
||||
dup2(fileno((FILE*)wsgi_req->async_post), 0);
|
||||
fclose(wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
else if (wsgi_req->poll.fd != 0) {
|
||||
dup2(wsgi_req->poll.fd, 0);
|
||||
close(wsgi_req->poll.fd);
|
||||
}
|
||||
@@ -741,14 +827,21 @@ clear:
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (path_info && wsgi_req->path_info_len-discard_base > 0) {
|
||||
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, wsgi_req->path_info_len-discard_base, "", 0), 1)) {
|
||||
|
||||
|
||||
if (path_info) {
|
||||
|
||||
size_t pi_len = wsgi_req->path_info_len - (path_info - wsgi_req->path_info);
|
||||
|
||||
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, pi_len, "", 0), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("PATH_TRANSLATED", uwsgi_concat4n(docroot, docroot_len, "/", 1, path_info, wsgi_req->path_info_len-discard_base, "", 0) , 1)) {
|
||||
|
||||
if (setenv("PATH_TRANSLATED", uwsgi_concat3n(docroot, docroot_len, path_info, pi_len, "", 0) , 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
unsetenv("PATH_INFO");
|
||||
@@ -779,7 +872,7 @@ clear:
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("SCRIPT_NAME", full_path+(docroot_len-discard_base), 1)) {
|
||||
if (setenv("SCRIPT_NAME", uwsgi_concat2n(wsgi_req->path_info, discard_base, full_path+docroot_len, strlen(full_path+docroot_len)), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
@@ -805,6 +898,41 @@ clear:
|
||||
drop_env = drop_env->next;
|
||||
}
|
||||
|
||||
argv = uwsgi_malloc(sizeof(char *) * 3);
|
||||
|
||||
// check if we need to parse indexed QUERY_STRING
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
if (!memchr(wsgi_req->query_string, '=', wsgi_req->query_string_len)) {
|
||||
nargs = 1;
|
||||
for(i=0;i<wsgi_req->query_string_len;i++) {
|
||||
if (wsgi_req->query_string[i] == '+')
|
||||
nargs++;
|
||||
}
|
||||
|
||||
|
||||
// reallocate argv and qs
|
||||
argv = uwsgi_malloc(sizeof(char *) * (3+nargs));
|
||||
char *qs = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
|
||||
// set the start position of args in argv
|
||||
i = 1;
|
||||
if (helper) i = 2;
|
||||
char *p = strtok(qs, "+");
|
||||
while(p) {
|
||||
// create a copy for the url_decoded string
|
||||
char *arg_copy = uwsgi_str(p);
|
||||
uint16_t arg_copy_len = strlen(p);
|
||||
http_url_decode(p, &arg_copy_len, arg_copy);
|
||||
// and a final copy for shell escaped arg
|
||||
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
if (helper) {
|
||||
if (!uwsgi_starts_with(helper, strlen(helper), "sym://", 6)) {
|
||||
void (*cgi_func)(char *) = dlsym(RTLD_DEFAULT, helper+6);
|
||||
@@ -818,11 +946,11 @@ clear:
|
||||
}
|
||||
argv[0] = helper;
|
||||
argv[1] = command;
|
||||
argv[2] = NULL;
|
||||
argv[nargs+2] = NULL;
|
||||
}
|
||||
else {
|
||||
argv[0] = command;
|
||||
argv[1] = NULL;
|
||||
argv[nargs+1] = NULL;
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
@@ -840,51 +968,6 @@ void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_cgi_manage_options(int i, char *optarg) {
|
||||
|
||||
char *value;
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_CGI:
|
||||
value = strchr(optarg, '=');
|
||||
if (!value) {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, strlen(optarg), NULL, 0);
|
||||
}
|
||||
else {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, value-optarg, value+1, strlen(value+1));
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_BUFFER_SIZE:
|
||||
uc.buffer_size = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_TIMEOUT:
|
||||
uc.timeout = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_INDEX:
|
||||
uwsgi_string_new_list(&uc.index, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_ALLOWED_EXT:
|
||||
uwsgi_string_new_list(&uc.allowed_ext, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_LOADLIB:
|
||||
uwsgi_string_new_list(&uc.loadlib, uwsgi_str(optarg));
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_UNSET:
|
||||
uwsgi_string_new_list(&uc.unset, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_MAP_HELPER:
|
||||
value = strchr(optarg, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_dyn_dict_new(&uc.helpers, optarg, value-optarg, value+1, strlen(value+1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin cgi_plugin = {
|
||||
|
||||
@@ -893,7 +976,6 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.init = uwsgi_cgi_init,
|
||||
.init_apps = uwsgi_cgi_apps,
|
||||
.options = uwsgi_cgi_options,
|
||||
.manage_opt = uwsgi_cgi_manage_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
.after_request = uwsgi_cgi_after_request,
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
This plugins is meant as an example for custom implementations.
|
||||
|
||||
-- Copy of Cheaper, backlog algorithm (supported only on Linux) --
|
||||
|
||||
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
|
||||
Decrese when lower.
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int cheaper_backlog2_algo(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->ti.tcpi_unacked;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int)uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
|
||||
}
|
||||
else if (backlog < (int) uwsgi.cheaper_overload) {
|
||||
// count active workers
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
// cheap a worker if too much are running
|
||||
if (active_workers > uwsgi.cheaper_count) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// registration hook
|
||||
void uwsgi_cheaper_register_backlog2(void) {
|
||||
uwsgi_register_cheaper_algo("backlog2", cheaper_backlog2_algo);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cheaper_backlog2_plugin = {
|
||||
|
||||
.name = "cheaper_backlog2",
|
||||
.on_load = uwsgi_cheaper_register_backlog2,
|
||||
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='cheaper_backlog2'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['cheaper_backlog2']
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int dummy_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin dummy_plugin = {
|
||||
.name = "dummy",
|
||||
.modifier1 = 0,
|
||||
.request = dummy_request,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='dummy'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['dummy']
|
||||
+7
-24
@@ -4,10 +4,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_erlang uerl;
|
||||
|
||||
struct option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, LONG_ARGS_ERLANG},
|
||||
{"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
|
||||
{0, 0, 0, 0},
|
||||
struct uwsgi_option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
|
||||
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
}
|
||||
|
||||
void erlang_loop() {
|
||||
void erlang_loop(int id) {
|
||||
|
||||
ErlConnect econn;
|
||||
//ErlMessage em;
|
||||
@@ -363,8 +363,7 @@ int erlang_init() {
|
||||
char *nodename;
|
||||
struct in_addr addr;
|
||||
|
||||
uerl.lock = uwsgi_mmap_shared_lock();
|
||||
uwsgi_lock_init(uerl.lock);
|
||||
uerl.lock = uwsgi_lock_init("erlang");
|
||||
|
||||
if (uerl.name) {
|
||||
|
||||
@@ -423,7 +422,7 @@ int erlang_init() {
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -433,26 +432,10 @@ int erlang_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erlang_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_ERLANG:
|
||||
uwsgi.master_process = 1;
|
||||
uerl.name = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_ERLANG_COOKIE:
|
||||
uerl.cookie = optarg;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin erlang_plugin = {
|
||||
|
||||
.name = "erlang",
|
||||
.options = erlang_options,
|
||||
.manage_opt = erlang_opt,
|
||||
.init = erlang_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#include <ei.h>
|
||||
|
||||
#define LONG_ARGS_ERLANG 17012
|
||||
#define LONG_ARGS_ERLANG_COOKIE 17013
|
||||
|
||||
|
||||
|
||||
struct uwsgi_erlang_process {
|
||||
|
||||
char name[0xff];
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import os
|
||||
|
||||
NAME='erlang'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
|
||||
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
|
||||
|
||||
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
|
||||
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
|
||||
|
||||
CFLAGS = [ '-I' + includedir ]
|
||||
LDFLAGS = [ '-L' + libpath ]
|
||||
|
||||
LIBS = ['-lei']
|
||||
|
||||
GCC_LIST = ['erlang']
|
||||
|
||||
+570
-737
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
#define FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
#define FASTROUTER_STATUS_RECV_HDR 2
|
||||
#define FASTROUTER_STATUS_RECV_VARS 3
|
||||
#define FASTROUTER_STATUS_RESPONSE 4
|
||||
#define FASTROUTER_STATUS_BUFFERING 5
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
#define FASTROUTER_STATUS_SCTP_NODE_FREE 6
|
||||
#define FASTROUTER_STATUS_SCTP_RESPONSE 7
|
||||
#endif
|
||||
|
||||
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
|
||||
#define add_fake_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+1, x)
|
||||
#define add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
|
||||
#define del_check_timeout(x) rb_erase(&x->rbt, timeouts);
|
||||
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
|
||||
|
||||
struct fastrouter_session;
|
||||
|
||||
struct uwsgi_fastrouter {
|
||||
|
||||
int (*mapper)(struct fastrouter_session *, char **);
|
||||
|
||||
int has_sockets;
|
||||
int has_subscription_sockets;
|
||||
#ifdef UWSGI_SCTP
|
||||
int has_sctp_sockets;
|
||||
#endif
|
||||
|
||||
int processes;
|
||||
int quiet;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
|
||||
int use_cache;
|
||||
int nevents;
|
||||
|
||||
char *magic_table[0xff];
|
||||
|
||||
int queue;
|
||||
|
||||
char *pattern;
|
||||
int pattern_len;
|
||||
|
||||
char *base;
|
||||
int base_len;
|
||||
|
||||
size_t post_buffering;
|
||||
char *pb_base_dir;
|
||||
|
||||
struct uwsgi_string_list *static_nodes;
|
||||
struct uwsgi_string_list *current_static_node;
|
||||
int static_node_gracetime;
|
||||
|
||||
char *stats_server;
|
||||
int fr_stats_server;
|
||||
|
||||
int use_socket;
|
||||
int socket_num;
|
||||
struct uwsgi_socket *to_socket;
|
||||
|
||||
struct uwsgi_subscribe_slot *subscriptions;
|
||||
int subscription_regexp;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
uint8_t code_string_modifier1;
|
||||
char *code_string_code;
|
||||
char *code_string_function;
|
||||
|
||||
|
||||
struct uwsgi_rb_timer *subscriptions_check;
|
||||
|
||||
int cheap;
|
||||
int i_am_cheap;
|
||||
|
||||
int tolerance;
|
||||
int harakiri;
|
||||
|
||||
struct fastrouter_session **fr_table;
|
||||
|
||||
};
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
struct uwsgi_fr_sctp_node {
|
||||
|
||||
int fd;
|
||||
char name[64];
|
||||
uint64_t requests;
|
||||
struct uwsgi_fr_sctp_node *prev;
|
||||
struct uwsgi_fr_sctp_node *next;
|
||||
};
|
||||
|
||||
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int);
|
||||
void uwsgi_fr_sctp_del_node(int);
|
||||
void uwsgi_opt_fastrouter_sctp(char *, char *, void *);
|
||||
|
||||
#endif
|
||||
|
||||
struct fastrouter_session {
|
||||
|
||||
int fd;
|
||||
int instance_fd;
|
||||
int status;
|
||||
struct uwsgi_header uh;
|
||||
uint8_t h_pos;
|
||||
uint16_t pos;
|
||||
|
||||
char *hostname;
|
||||
uint16_t hostname_len;
|
||||
|
||||
int has_key;
|
||||
int retry;
|
||||
#ifdef UWSGI_SCTP
|
||||
int persistent;
|
||||
#endif
|
||||
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
struct uwsgi_subscribe_node *un;
|
||||
struct uwsgi_string_list *static_node;
|
||||
int pass_fd;
|
||||
int soopt;
|
||||
int timed_out;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
|
||||
size_t post_cl;
|
||||
size_t post_remains;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
char *buf_file_name;
|
||||
FILE *buf_file;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
char *tmp_socket_name;
|
||||
|
||||
char buffer[0xffff];
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct fastrouter_session *, int intersting_fd, char **);
|
||||
void close_session(struct fastrouter_session *);
|
||||
void fr_get_hostname(char *, uint16_t, char *, uint16_t, void *);
|
||||
|
||||
int uwsgi_fr_map_use_void(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_cache(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_pattern(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_subscription(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_base(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_cs(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_to(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *, char **);
|
||||
#ifdef UWSGI_SCTP
|
||||
int uwsgi_fr_map_use_sctp(struct fastrouter_session *, char **);
|
||||
#endif
|
||||
@@ -0,0 +1,428 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct fastrouter_session *fr_session, int interesting_fd, char **magic_table) {
|
||||
|
||||
socklen_t solen = sizeof(int);
|
||||
struct iovec iov[2];
|
||||
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} msg_control;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ssize_t len;
|
||||
char *post_tmp_buf[0xffff];
|
||||
|
||||
switch (fr_session->status) {
|
||||
|
||||
case FASTROUTER_STATUS_RECV_HDR:
|
||||
len = recv(fr_session->fd, (char *) (&fr_session->uh) + fr_session->h_pos, 4 - fr_session->h_pos, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->h_pos += len;
|
||||
if (fr_session->h_pos == 4) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
|
||||
#endif
|
||||
fr_session->status = FASTROUTER_STATUS_RECV_VARS;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FASTROUTER_STATUS_RECV_VARS:
|
||||
|
||||
if (interesting_fd == -1) {
|
||||
goto choose_node;
|
||||
}
|
||||
|
||||
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->pos += len;
|
||||
if (fr_session->pos == fr_session->uh.pktsize) {
|
||||
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->hostname_len == 0) {
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
|
||||
#endif
|
||||
|
||||
// the mapper hook
|
||||
choose_node:
|
||||
if (ufr.mapper(fr_session, magic_table))
|
||||
break;
|
||||
|
||||
// no address found
|
||||
if (!fr_session->instance_address_len) {
|
||||
// if fallback nodes are configured, trigger them
|
||||
if (ufr.fallback) {
|
||||
fr_session->instance_failed = 1;
|
||||
}
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ufr.post_buffering > 0 && fr_session->post_cl > ufr.post_buffering) {
|
||||
fr_session->status = FASTROUTER_STATUS_BUFFERING;
|
||||
fr_session->buf_file_name = uwsgi_tmpname(ufr.pb_base_dir, "uwsgiXXXXX");
|
||||
if (!fr_session->buf_file_name) {
|
||||
uwsgi_error("tempnam()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->post_remains = fr_session->post_cl;
|
||||
|
||||
// 2 + UWSGI_POSTFILE + 2 + fr_session->buf_file_name
|
||||
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(fr_session->buf_file_name)) > 0xffff) {
|
||||
uwsgi_log("unable to buffer request body to file %s: not enough space\n", fr_session->buf_file_name);
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
|
||||
uint16_t bfn_len = strlen(fr_session->buf_file_name);
|
||||
*ptr++ = 14;
|
||||
*ptr++ = 0;
|
||||
memcpy(ptr, "UWSGI_POSTFILE", 14);
|
||||
ptr += 14;
|
||||
*ptr++ = (char) (bfn_len & 0xff);
|
||||
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
|
||||
memcpy(ptr, fr_session->buf_file_name, bfn_len);
|
||||
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
|
||||
|
||||
|
||||
fr_session->buf_file = fopen(fr_session->buf_file_name, "w");
|
||||
if (!fr_session->buf_file) {
|
||||
uwsgi_error_open(fr_session->buf_file_name);
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
|
||||
|
||||
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
fr_session->instance_failed = 1;
|
||||
fr_session->soopt = errno;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
fr_session->status = FASTROUTER_STATUS_CONNECTING;
|
||||
ufr.fr_table[fr_session->instance_fd] = fr_session;
|
||||
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case FASTROUTER_STATUS_CONNECTING:
|
||||
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
|
||||
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&fr_session->soopt), &solen) < 0) {
|
||||
uwsgi_error("getsockopt()");
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->soopt) {
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->uh.modifier1 = fr_session->modifier1;
|
||||
|
||||
iov[0].iov_base = &fr_session->uh;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = fr_session->buffer;
|
||||
iov[1].iov_len = fr_session->uh.pktsize;
|
||||
|
||||
// increment node requests counter
|
||||
if (fr_session->un)
|
||||
fr_session->un->requests++;
|
||||
|
||||
// fd passing: PERFORMANCE EXTREME BOOST !!!
|
||||
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));
|
||||
|
||||
if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (writev(fr_session->instance_fd, iov, 2) < 0) {
|
||||
uwsgi_error("writev()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
|
||||
fr_session->status = FASTROUTER_STATUS_RESPONSE;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifdef UWSGI_SCTP
|
||||
case FASTROUTER_STATUS_SCTP_NODE_FREE:
|
||||
|
||||
{
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
int msg_flags = 0;
|
||||
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
len = sctp_recvmsg(interesting_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
|
||||
// remove the SCTP node
|
||||
uwsgi_log("[0] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
|
||||
uwsgi_fr_sctp_del_node(interesting_fd);
|
||||
if (ufr.fr_table[interesting_fd]->timeout) {
|
||||
del_timeout(ufr.fr_table[interesting_fd]);
|
||||
}
|
||||
free(ufr.fr_table[interesting_fd]);
|
||||
ufr.fr_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
}
|
||||
|
||||
break;
|
||||
case FASTROUTER_STATUS_SCTP_RESPONSE:
|
||||
|
||||
// data from instance
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
struct uwsgi_header *uh;
|
||||
int msg_flags = 0;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
len = sctp_recvmsg(fr_session->instance_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
// REMOVE THE NODE
|
||||
uwsgi_log("[1] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
|
||||
uwsgi_fr_sctp_del_node(interesting_fd);
|
||||
if (ufr.fr_table[interesting_fd]->timeout) {
|
||||
del_timeout(ufr.fr_table[interesting_fd]);
|
||||
}
|
||||
free(ufr.fr_table[interesting_fd]);
|
||||
ufr.fr_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (fr_session->fd != -1 && sinfo.sinfo_stream != fr_session->fd) {
|
||||
if (fr_session->fd != -1) {
|
||||
uwsgi_log("INVALID SCTP STREAM !!!\n");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uh = (struct uwsgi_header *) &sinfo.sinfo_ppid;
|
||||
|
||||
// check for close packet
|
||||
if (uh->modifier1 == 200) {
|
||||
fr_session->status = FASTROUTER_STATUS_SCTP_NODE_FREE;
|
||||
if (fr_session->fd != -1) {
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->fd == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(fr_session->fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
break;
|
||||
}
|
||||
|
||||
// update transfer statistics
|
||||
if (fr_session->un)
|
||||
fr_session->un->transferred += len;
|
||||
|
||||
}
|
||||
// body from client
|
||||
else if (interesting_fd == fr_session->fd) {
|
||||
|
||||
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
// mark session as broken
|
||||
ufr.fr_table[fr_session->instance_fd]->fd = -1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
// map the stream id to the file descriptor
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 199;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
memcpy(&sinfo.sinfo_ppid, &uh, sizeof(uint32_t));
|
||||
sinfo.sinfo_stream = fr_session->fd;
|
||||
|
||||
len = sctp_send(fr_session->instance_fd, fr_session->buffer, len, &sinfo, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
case FASTROUTER_STATUS_RESPONSE:
|
||||
|
||||
// data from instance
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(fr_session->fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
// update transfer statistics
|
||||
if (fr_session->un)
|
||||
fr_session->un->transferred += len;
|
||||
}
|
||||
// body from client
|
||||
else if (interesting_fd == fr_session->fd) {
|
||||
|
||||
//uwsgi_log("receiving body...\n");
|
||||
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FASTROUTER_STATUS_BUFFERING:
|
||||
len = recv(fr_session->fd, post_tmp_buf, UMIN(0xffff, fr_session->post_remains), 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fwrite(post_tmp_buf, len, 1, fr_session->buf_file) != 1) {
|
||||
uwsgi_error("fwrite()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->post_remains -= len;
|
||||
|
||||
if (fr_session->post_remains == 0) {
|
||||
// close the buf_file ASAP
|
||||
fclose(fr_session->buf_file);
|
||||
fr_session->buf_file = NULL;
|
||||
|
||||
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
|
||||
|
||||
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->status = FASTROUTER_STATUS_CONNECTING;
|
||||
ufr.fr_table[fr_session->instance_fd] = fr_session;
|
||||
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
// fallback to destroy !!!
|
||||
default:
|
||||
uwsgi_log("unknown event: closing session\n");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
|
||||
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
|
||||
#endif
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_void(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_cache(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_pattern(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
int tmp_socket_name_len = 0;
|
||||
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
|
||||
fr_session->tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
|
||||
free(magic_table['s']);
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = fr_session->tmp_socket_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_subscription(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
|
||||
if (fr_session->un && fr_session->un->len) {
|
||||
fr_session->instance_address = fr_session->un->name;
|
||||
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) {
|
||||
uwsgi_gateway_go_cheap("uWSGI fastrouter", ufr.queue, &ufr.i_am_cheap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_base(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
int tmp_socket_name_len = 0;
|
||||
|
||||
fr_session->tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = fr_session->tmp_socket_name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_cs(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
|
||||
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
|
||||
if (fr_session->instance_address) {
|
||||
fr_session->instance_address_len = strlen(fr_session->instance_address);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_to(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
fr_session->instance_address = ufr.to_socket->name;
|
||||
fr_session->instance_address_len = ufr.to_socket->name_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
if (!ufr.current_static_node) {
|
||||
ufr.current_static_node = ufr.static_nodes;
|
||||
}
|
||||
|
||||
fr_session->static_node = ufr.current_static_node;
|
||||
|
||||
// is it a dead node ?
|
||||
if (fr_session->static_node->custom > 0) {
|
||||
|
||||
// gracetime passed ?
|
||||
if (fr_session->static_node->custom + ufr.static_node_gracetime <= (uint64_t) uwsgi_now()) {
|
||||
fr_session->static_node->custom = 0;
|
||||
}
|
||||
else {
|
||||
struct uwsgi_string_list *tmp_node = fr_session->static_node;
|
||||
struct uwsgi_string_list *next_node = fr_session->static_node->next;
|
||||
fr_session->static_node = NULL;
|
||||
// needed for 1-node only setups
|
||||
if (!next_node)
|
||||
next_node = ufr.static_nodes;
|
||||
|
||||
while (tmp_node != next_node) {
|
||||
if (!next_node) {
|
||||
next_node = ufr.static_nodes;
|
||||
}
|
||||
|
||||
if (tmp_node == next_node)
|
||||
break;
|
||||
|
||||
if (next_node->custom == 0) {
|
||||
fr_session->static_node = next_node;
|
||||
break;
|
||||
}
|
||||
next_node = next_node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fr_session->static_node) {
|
||||
|
||||
fr_session->instance_address = fr_session->static_node->value;
|
||||
fr_session->instance_address_len = fr_session->static_node->len;
|
||||
// set the next one
|
||||
ufr.current_static_node = fr_session->static_node->next;
|
||||
}
|
||||
else {
|
||||
// set the next one
|
||||
ufr.current_static_node = ufr.current_static_node->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
|
||||
int uwsgi_fr_map_use_sctp(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
if (!*uwsgi_fastrouter_sctp_nodes_current)
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes_current;
|
||||
int choosen_fd = -1;
|
||||
// find the first available server
|
||||
while (ufsn) {
|
||||
if (ufr.fr_table[ufsn->fd]->status == FASTROUTER_STATUS_SCTP_NODE_FREE) {
|
||||
ufsn->requests++;
|
||||
choosen_fd = ufsn->fd;
|
||||
break;
|
||||
}
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes_current) {
|
||||
break;
|
||||
}
|
||||
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
// no nodes available
|
||||
if (choosen_fd == -1) {
|
||||
fr_session->retry = 1;
|
||||
del_timeout(fr_session);
|
||||
fr_session->timeout = add_fake_timeout(fr_session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
memcpy(&sinfo.sinfo_ppid, &fr_session->uh, sizeof(uint32_t));
|
||||
sinfo.sinfo_stream = fr_session->fd;
|
||||
ssize_t len = sctp_send(choosen_fd, fr_session->buffer, fr_session->uh.pktsize, &sinfo, 0);
|
||||
if (len < 0)
|
||||
uwsgi_error("sctp_send()");
|
||||
|
||||
fr_session->instance_fd = choosen_fd;
|
||||
fr_session->status = FASTROUTER_STATUS_SCTP_RESPONSE;
|
||||
ufr.fr_table[fr_session->instance_fd]->status = FASTROUTER_STATUS_SCTP_RESPONSE;
|
||||
ufr.fr_table[fr_session->instance_fd]->fd = fr_session->fd;
|
||||
|
||||
// round robin
|
||||
*uwsgi_fastrouter_sctp_nodes_current = (*uwsgi_fastrouter_sctp_nodes_current)->next;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifdef UWSGI_SCTP
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
|
||||
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
|
||||
|
||||
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
if (!ufsn) {
|
||||
*uwsgi_fastrouter_sctp_nodes = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
|
||||
(*uwsgi_fastrouter_sctp_nodes)->next = *uwsgi_fastrouter_sctp_nodes;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->prev = *uwsgi_fastrouter_sctp_nodes;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->requests = 0;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->fd = fd;
|
||||
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
}
|
||||
else {
|
||||
while(ufsn) {
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
|
||||
break;
|
||||
}
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
ufsn->next = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
|
||||
ufsn->next->next = *uwsgi_fastrouter_sctp_nodes;
|
||||
ufsn->next->prev = ufsn;
|
||||
ufsn->next->requests = 0;
|
||||
ufsn->next->fd = fd;
|
||||
|
||||
(*uwsgi_fastrouter_sctp_nodes)->prev = ufsn->next;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = ufsn->next;
|
||||
|
||||
}
|
||||
|
||||
return *uwsgi_fastrouter_sctp_nodes_current;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_fr_sctp_del_node(int fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
|
||||
while(ufsn) {
|
||||
|
||||
if (ufsn->fd == fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *prev = ufsn->prev;
|
||||
struct uwsgi_fr_sctp_node *next = ufsn->next;
|
||||
|
||||
// am i the only node ?
|
||||
if (prev == ufsn) {
|
||||
free(ufsn);
|
||||
*uwsgi_fastrouter_sctp_nodes = NULL;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
|
||||
// am i the first node ?
|
||||
if (ufsn == *uwsgi_fastrouter_sctp_nodes) {
|
||||
*uwsgi_fastrouter_sctp_nodes = next;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = next;
|
||||
free(ufsn);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*uwsgi_fastrouter_sctp_nodes_current == ufsn) {
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
}
|
||||
|
||||
free(ufsn);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
|
||||
break;
|
||||
}
|
||||
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_fastrouter_sctp(char *opt, char *value, void *foobar) {
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, "uWSGI fastrouter");
|
||||
ugs->sctp = 1;
|
||||
ufr.has_sctp_sockets++;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4,4 +4,4 @@ CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['fastrouter']
|
||||
GCC_LIST = ['fr_sctp', 'fr_map', 'fastrouter', 'fr_events']
|
||||
|
||||
@@ -7,10 +7,6 @@ struct ufib {
|
||||
VALUE *fib;
|
||||
} ufiber;
|
||||
|
||||
struct option fiber_options[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
VALUE uwsgi_fiber_request() {
|
||||
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
|
||||
@@ -80,5 +76,4 @@ struct uwsgi_plugin fiber_plugin = {
|
||||
|
||||
.name = "fiber",
|
||||
.init = fiber_init,
|
||||
.options = fiber_options,
|
||||
};
|
||||
|
||||
@@ -3,17 +3,13 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
struct option gevent_options[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
|
||||
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
|
||||
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
|
||||
if (ret) Py_DECREF(ret);\
|
||||
if (ret) { Py_DECREF(ret); }\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
if (ret) Py_DECREF(ret);
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
|
||||
struct uwsgi_gevent {
|
||||
PyObject *greenlet_switch;
|
||||
@@ -352,5 +348,4 @@ struct uwsgi_plugin gevent_plugin = {
|
||||
|
||||
.name = "gevent",
|
||||
.init = gevent_init,
|
||||
.options = gevent_options,
|
||||
};
|
||||
|
||||
@@ -10,9 +10,9 @@ struct ugreenlet {
|
||||
PyGreenlet **gl;
|
||||
} ugl;
|
||||
|
||||
struct option greenlet_options[] = {
|
||||
{"greenlet", no_argument, &ugl.enabled, 1},
|
||||
{ 0, 0, 0, 0 }
|
||||
struct uwsgi_option greenlet_options[] = {
|
||||
{"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
|
||||
|
||||
+600
-547
File diff suppressed because it is too large
Load Diff
+1
-8
@@ -1,16 +1,9 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <jni.h>
|
||||
|
||||
#define MAX_CLASSPATH 64
|
||||
|
||||
#define LONG_ARGS_JVM_BASE 17000 + (300 * 100)
|
||||
#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1
|
||||
#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2
|
||||
|
||||
struct uwsgi_jvm {
|
||||
|
||||
char *classpath[MAX_CLASSPATH];
|
||||
int classpath_cnt;
|
||||
struct uwsgi_string_list *classpath;
|
||||
|
||||
JNIEnv *env;
|
||||
char *class;
|
||||
|
||||
+10
-30
@@ -5,13 +5,15 @@
|
||||
with javap -s -p <class>
|
||||
you can get method signatures
|
||||
|
||||
This plugin is the core for all of the JVM-based ones
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_jvm ujvm;
|
||||
|
||||
struct option uwsgi_jvm_options[] = {
|
||||
{"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS},
|
||||
{"jvm-classpath", required_argument, 0, LONG_ARGS_JVM_CLASSPATH},
|
||||
struct uwsgi_option uwsgi_jvm_options[] = {
|
||||
{"jvm-main-class", required_argument, 0, "load the specified class", uwsgi_opt_set_str, &ujvm.class, 0},
|
||||
{"jvm-classpath", required_argument, 0, "add the specified directory to the classpath", uwsgi_opt_add_string_list, &ujvm.classpath, 0},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -87,7 +89,6 @@ int jvm_init(void) {
|
||||
JavaVMOption options[1];
|
||||
jmethodID mmid;
|
||||
|
||||
int i;
|
||||
char *old_cp = NULL ;
|
||||
|
||||
|
||||
@@ -97,17 +98,17 @@ int jvm_init(void) {
|
||||
|
||||
options[0].optionString = "-Djava.class.path=.";
|
||||
|
||||
if (ujvm.classpath_cnt > 0) {
|
||||
for(i=0;i<ujvm.classpath_cnt;i++) {
|
||||
struct uwsgi_string_list *cp = ujvm.classpath;
|
||||
while(cp) {
|
||||
if (old_cp) {
|
||||
options[0].optionString = uwsgi_concat3(old_cp, ":", ujvm.classpath[i]);
|
||||
options[0].optionString = uwsgi_concat3(old_cp, ":", cp->value);
|
||||
free(old_cp);
|
||||
}
|
||||
else {
|
||||
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", ujvm.classpath[i]);
|
||||
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", cp->value);
|
||||
}
|
||||
old_cp = options[0].optionString ;
|
||||
}
|
||||
cp = cp->next;
|
||||
}
|
||||
|
||||
vm_args.options = options;
|
||||
@@ -199,32 +200,11 @@ int uwsgi_jvm_strlen2c(jobject obj) {
|
||||
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_manage_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_JVM_CLASS:
|
||||
ujvm.class = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_JVM_CLASSPATH:
|
||||
if (ujvm.classpath_cnt < MAX_CLASSPATH) {
|
||||
ujvm.classpath[ujvm.classpath_cnt] = optarg;
|
||||
ujvm.classpath_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "you can specify at most %d --jvm-classpath options\n", MAX_CLASSPATH);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin jvm_plugin = {
|
||||
|
||||
.name = "jvm",
|
||||
.init = jvm_init,
|
||||
.options = uwsgi_jvm_options,
|
||||
.manage_opt = uwsgi_jvm_manage_opt,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ NAME='jvm'
|
||||
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
|
||||
|
||||
# Ubuntu
|
||||
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
|
||||
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
|
||||
JVM_INCPATH = "/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux"
|
||||
JVM_LIBPATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/"
|
||||
|
||||
try:
|
||||
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
|
||||
|
||||
@@ -64,15 +64,10 @@ void uwsgi_logsocket_register() {
|
||||
uwsgi_register_logger("socket", uwsgi_socket_logger);
|
||||
}
|
||||
|
||||
int uwsgi_logsocket_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logsocket_plugin = {
|
||||
|
||||
.name = "logsocket",
|
||||
.on_load = uwsgi_logsocket_register,
|
||||
.init = uwsgi_logsocket_init
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -12,14 +12,11 @@ struct uwsgi_lua {
|
||||
char *filename;
|
||||
} ulua;
|
||||
|
||||
#define LONG_ARGS_LUA_BASE 17000 + (6 * 100)
|
||||
#define LONG_ARGS_LUA LONG_ARGS_LUA_BASE + 1
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
|
||||
struct option uwsgi_lua_options[] = {
|
||||
struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, LONG_ARGS_LUA},
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -583,16 +580,6 @@ void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_lua_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_LUA:
|
||||
ulua.filename = optarg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_lua_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
@@ -726,7 +713,6 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.modifier1 = 6,
|
||||
.init = uwsgi_lua_init,
|
||||
.options = uwsgi_lua_options,
|
||||
.manage_opt = uwsgi_lua_manage_options,
|
||||
.request = uwsgi_lua_request,
|
||||
.after_request = uwsgi_lua_after_request,
|
||||
.init_apps = uwsgi_lua_app,
|
||||
|
||||
+3
-18
@@ -3,12 +3,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int use_nagios = 0;
|
||||
|
||||
#define LONG_ARGS_NAGIOS 40000
|
||||
struct uwsgi_option nagios_options[] = {
|
||||
|
||||
struct option nagios_options[] = {
|
||||
|
||||
{"nagios", no_argument, 0, LONG_ARGS_NAGIOS},
|
||||
{0, 0, 0, 0},
|
||||
{"nagios", no_argument, 0, "nagios check", uwsgi_opt_true, &use_nagios, UWSGI_OPT_NO_INITIAL},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
@@ -70,21 +68,8 @@ int nagios() {
|
||||
exit(3);
|
||||
}
|
||||
|
||||
int nagios_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_NAGIOS:
|
||||
uwsgi.no_initial_output = 1;
|
||||
use_nagios = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin nagios_plugin = {
|
||||
|
||||
.options = nagios_options,
|
||||
.manage_opt = nagios_opt,
|
||||
.init = nagios,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int uwsgi_request_notfound(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[3];
|
||||
|
||||
if (wsgi_req->protocol_len > 0) {
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = "HTTP/1.0";
|
||||
iov[0].iov_len = 8;
|
||||
}
|
||||
|
||||
iov[1].iov_base = " 404 Not Found\r\n";
|
||||
iov[1].iov_len = 16;
|
||||
|
||||
iov[2].iov_base = "Content-Type: text/plain\r\n\r\n";
|
||||
iov[2].iov_len = 28;
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 3);
|
||||
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Not Found", 9);
|
||||
wsgi_req->status = 404;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin notfound_plugin = {
|
||||
|
||||
.name = "notfound",
|
||||
.request = uwsgi_request_notfound,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='notfound'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['notfound']
|
||||
@@ -1,16 +0,0 @@
|
||||
PHP_ARG_WITH(uwsgi,,
|
||||
[ --with-uwsgi=UWSGISRCDIR Build PHP as a uWSGI plugin (UNIX/POSIX only)], no, no)
|
||||
|
||||
AC_MSG_CHECKING([for UWSGI])
|
||||
if test "$PHP_UWSGI" != "no"; then
|
||||
|
||||
INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_UWSGI/php_plugin.so"
|
||||
|
||||
UWSGI_CFLAGS=`cd $PHP_UWSGI ; python uwsgiconfig.py --cflags`
|
||||
UWSGI_CFLAGS="$UWSGI_CFLAGS -I$PHP_UWSGI"
|
||||
|
||||
PHP_SELECT_SAPI(uwsgi, shared, php_plugin.c, $UWSGI_CFLAGS)
|
||||
AC_MSG_RESULT([$PHP_UWSGI])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
+474
-75
@@ -4,41 +4,94 @@
|
||||
#include "php_variables.h"
|
||||
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
#include <uwsgi.h>
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// http status codes list
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
struct uwsgi_php {
|
||||
struct uwsgi_string_list *allowed_docroot;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *set;
|
||||
char *docroot;
|
||||
char *app;
|
||||
size_t ini_size;
|
||||
char *server_software;
|
||||
size_t server_software_len;
|
||||
} uphp;
|
||||
|
||||
#define LONG_ARGS_PHP_BASE 17000 + ((14 + 1) * 1000)
|
||||
#define LONG_ARGS_PHP_INI LONG_ARGS_PHP_BASE + 1
|
||||
#define LONG_ARGS_PHP_ALLOWED_DOCROOT LONG_ARGS_PHP_BASE + 2
|
||||
#define LONG_ARGS_PHP_ALLOWED_EXT LONG_ARGS_PHP_BASE + 3
|
||||
void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
|
||||
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(value);
|
||||
uwsgi_sapi_module.php_ini_ignore = 1;
|
||||
}
|
||||
|
||||
struct option uwsgi_php_options[] = {
|
||||
|
||||
{"php-ini", required_argument, 0, LONG_ARGS_PHP_INI},
|
||||
{"php-config", required_argument, 0, LONG_ARGS_PHP_INI},
|
||||
{"php-allowed-docroot", required_argument, 0, LONG_ARGS_PHP_ALLOWED_DOCROOT},
|
||||
{"php-allowed-ext", required_argument, 0, LONG_ARGS_PHP_ALLOWED_EXT},
|
||||
{0, 0, 0, 0},
|
||||
struct uwsgi_option uwsgi_php_options[] = {
|
||||
|
||||
{"php-ini", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-config", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-set", required_argument, 0, "set a php config directive", uwsgi_opt_add_string_list, &uphp.set, 0},
|
||||
{"php-index", required_argument, 0, "list the php index files", uwsgi_opt_add_string_list, &uphp.index, 0},
|
||||
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
|
||||
{"php-allowed-docroot", required_argument, 0, "list the allowed document roots", uwsgi_opt_add_string_list, &uphp.allowed_docroot, 0},
|
||||
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
|
||||
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
|
||||
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_php_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[6];
|
||||
|
||||
wsgi_req->status = 301;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 301 Moved Permanently\r\n";
|
||||
iov[1].iov_len = 24;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
|
||||
iov[0].iov_base = "Location: ";
|
||||
iov[0].iov_len = 10;
|
||||
iov[1].iov_base = wsgi_req->path_info;
|
||||
iov[1].iov_len = wsgi_req->path_info_len;
|
||||
iov[2].iov_base = "/";
|
||||
iov[2].iov_len = 1;
|
||||
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
iov[3].iov_base = "?";
|
||||
iov[3].iov_len = 1;
|
||||
iov[4].iov_base = wsgi_req->query_string;
|
||||
iov[4].iov_len = wsgi_req->query_string_len;
|
||||
iov[5].iov_base = "\r\n\r\n";
|
||||
iov[5].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
else {
|
||||
iov[3].iov_base = "\r\n\r\n";
|
||||
iov[3].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
{
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
|
||||
if (len != str_length) {
|
||||
if (len != (ssize_t) str_length) {
|
||||
php_handle_aborted_connection();
|
||||
return -1;
|
||||
}
|
||||
@@ -49,13 +102,13 @@ static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
void uwsgi_php_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
|
||||
}
|
||||
|
||||
void uwsgi_php_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
|
||||
|
||||
}
|
||||
|
||||
@@ -68,43 +121,57 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
char status[4];
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
if (SG(request_info).no_headers == 1) {
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
wsgi_req->status = SG(sapi_headers).http_response_code;
|
||||
if (!wsgi_req->status) wsgi_req->status = 200;
|
||||
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
if (!SG(sapi_headers).http_status_line) {
|
||||
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
|
||||
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
|
||||
uwsgi_num2str2n(wsgi_req->status, status, 4);
|
||||
uwsgi_num2str2n(wsgi_req->status, status, 4);
|
||||
|
||||
iov[2].iov_base = status;
|
||||
iov[2].iov_len = 3;
|
||||
iov[2].iov_base = status;
|
||||
iov[2].iov_len = 3;
|
||||
|
||||
iov[3].iov_base = " ";
|
||||
iov[3].iov_len = 1;
|
||||
iov[3].iov_base = " ";
|
||||
iov[3].iov_len = 1;
|
||||
|
||||
// get the status code
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, status, 3)) {
|
||||
iov[4].iov_base = (char *) http_sc->message;
|
||||
iov[4].iov_len = http_sc->message_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// get the status code
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, status, 3)) {
|
||||
iov[4].iov_base = (char *) http_sc->message;
|
||||
iov[4].iov_len = http_sc->message_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iov[4].iov_len == 0) {
|
||||
iov[4].iov_base = "Unknown";
|
||||
iov[4].iov_len = 7;
|
||||
}
|
||||
if (iov[4].iov_len == 0) {
|
||||
iov[4].iov_base = "Unknown";
|
||||
iov[4].iov_len = 7;
|
||||
}
|
||||
|
||||
iov[5].iov_base = "\r\n";
|
||||
iov[5].iov_len = 2;
|
||||
iov[5].iov_base = "\r\n";
|
||||
iov[5].iov_len = 2;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = SG(sapi_headers).http_status_line;
|
||||
iov[0].iov_len = strlen(iov[0].iov_base);
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
while (h) {
|
||||
@@ -112,6 +179,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
iov[0].iov_len = h->header_len;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
|
||||
@@ -185,6 +253,14 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
||||
|
||||
if (uphp.server_software) {
|
||||
if (!uphp.server_software_len) uphp.server_software_len = strlen(uphp.server_software);
|
||||
php_register_variable_safe("SERVER_SOFTWARE", uphp.server_software, uphp.server_software_len, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
else {
|
||||
php_register_variable_safe("SERVER_SOFTWARE", "uWSGI", 5, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
|
||||
wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len,
|
||||
@@ -196,6 +272,7 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
php_register_variable_safe("SCRIPT_NAME", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
php_register_variable_safe("SCRIPT_FILENAME", wsgi_req->file, wsgi_req->file_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable_safe("DOCUMENT_ROOT", wsgi_req->document_root, wsgi_req->document_root_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
if (wsgi_req->path_info_len) {
|
||||
char *path_translated = ecalloc(1, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len + 1);
|
||||
@@ -204,6 +281,9 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
memcpy(path_translated + (wsgi_req->file_len - wsgi_req->script_name_len), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
php_register_variable_safe("PATH_TRANSLATED", path_translated, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
|
||||
}
|
||||
else {
|
||||
php_register_variable_safe("PATH_TRANSLATED", "", 0, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
php_register_variable_safe("PHP_SELF", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
@@ -212,9 +292,278 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_php_set(char *opt) {
|
||||
|
||||
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + strlen(opt)+2);
|
||||
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, opt, strlen(opt));
|
||||
|
||||
uphp.ini_size += strlen(opt)+1;
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = '\n';
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
|
||||
}
|
||||
|
||||
// future implementation...
|
||||
PHP_MINIT_FUNCTION(uwsgi_php_minit) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_version) {
|
||||
RETURN_STRING(UWSGI_VERSION, 1);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_worker_id) {
|
||||
RETURN_LONG(uwsgi.mywid);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_masterpid) {
|
||||
if (uwsgi.master_process) {
|
||||
RETURN_LONG(uwsgi.workers[0].pid);
|
||||
}
|
||||
RETURN_LONG(0);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_del) {
|
||||
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_get) {
|
||||
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
uint64_t valsize;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
char *value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (value) {
|
||||
char *ret = estrndup(value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_STRING(ret, 0);
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_set) {
|
||||
char *key = NULL;
|
||||
int keylen;
|
||||
char *value = NULL;
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_update) {
|
||||
char *key = NULL;
|
||||
int keylen;
|
||||
char *value = NULL;
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
|
||||
PHP_FUNCTION(uwsgi_rpc) {
|
||||
|
||||
|
||||
int num_args = 0;
|
||||
int i;
|
||||
char *node = NULL;
|
||||
char *func = NULL;
|
||||
zval ***varargs = NULL;
|
||||
zval *z_current_obj;
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
uint16_t size = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if (num_args < 2)
|
||||
goto clear;
|
||||
|
||||
if (num_args > 256 + 2)
|
||||
goto clear;
|
||||
|
||||
z_current_obj = *varargs[0];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
node = Z_STRVAL_P(z_current_obj);
|
||||
|
||||
z_current_obj = *varargs[1];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
func = Z_STRVAL_P(z_current_obj);
|
||||
|
||||
for(i=0;i<(num_args-2);i++) {
|
||||
z_current_obj = *varargs[i+2];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
argv[i] = Z_STRVAL_P(z_current_obj);
|
||||
argvs[i] = Z_STRLEN_P(z_current_obj);
|
||||
}
|
||||
|
||||
char *response = uwsgi_do_rpc(node, func, num_args - 2, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
// here we do not free varargs for performance reasons
|
||||
char *ret = estrndup(response, size);
|
||||
free(response);
|
||||
RETURN_STRING(ret, 0);
|
||||
}
|
||||
|
||||
clear:
|
||||
efree(varargs);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
|
||||
PHP_FUNCTION(uwsgi_setprocname) {
|
||||
|
||||
char *name;
|
||||
int name_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_set_processname(estrndup(name, name_len));
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_signal) {
|
||||
|
||||
long long_signum;
|
||||
uint8_t signum = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long_signum) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
signum = (uint8_t) long_signum;
|
||||
uwsgi_signal_send(uwsgi.signal_socket, signum);
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
zend_function_entry uwsgi_php_functions[] = {
|
||||
PHP_FE(uwsgi_version, NULL)
|
||||
PHP_FE(uwsgi_setprocname, NULL)
|
||||
PHP_FE(uwsgi_worker_id, NULL)
|
||||
PHP_FE(uwsgi_masterpid, NULL)
|
||||
PHP_FE(uwsgi_signal, NULL)
|
||||
PHP_FE(uwsgi_rpc, NULL)
|
||||
PHP_FE(uwsgi_cache_get, NULL)
|
||||
PHP_FE(uwsgi_cache_set, NULL)
|
||||
PHP_FE(uwsgi_cache_update, NULL)
|
||||
PHP_FE(uwsgi_cache_del, NULL)
|
||||
{ NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
PHP_MINFO_FUNCTION(uwsgi_php_minfo) {
|
||||
php_info_print_table_start( );
|
||||
php_info_print_table_row(2, "uwsgi api", "enabled");
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
php_info_print_table_row(2, "uwsgi cache", "enabled");
|
||||
}
|
||||
else {
|
||||
php_info_print_table_row(2, "uwsgi cache", "disabled");
|
||||
}
|
||||
php_info_print_table_end( );
|
||||
}
|
||||
|
||||
static zend_module_entry uwsgi_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"uwsgi",
|
||||
uwsgi_php_functions,
|
||||
PHP_MINIT(uwsgi_php_minit),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(uwsgi_php_minfo),
|
||||
UWSGI_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
|
||||
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
if (php_module_startup(&uwsgi_sapi_module, NULL, 0)==FAILURE) {
|
||||
|
||||
if (php_module_startup(&uwsgi_sapi_module, &uwsgi_module_entry, 1)==FAILURE) {
|
||||
return FAILURE;
|
||||
} else {
|
||||
return SUCCESS;
|
||||
@@ -223,7 +572,7 @@ static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
|
||||
static void sapi_uwsgi_log_message(char *message) {
|
||||
|
||||
uwsgi_log(message);
|
||||
uwsgi_log("%s\n", message);
|
||||
}
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module = {
|
||||
@@ -261,7 +610,16 @@ int uwsgi_php_init(void) {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
struct uwsgi_string_list *pset = uphp.set;
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
|
||||
// applying custom options
|
||||
while(pset) {
|
||||
uwsgi_php_set(pset->value);
|
||||
pset = pset->next;
|
||||
}
|
||||
|
||||
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
|
||||
|
||||
// filling http status codes
|
||||
@@ -269,7 +627,6 @@ int uwsgi_php_init(void) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
|
||||
|
||||
return 0;
|
||||
@@ -285,6 +642,8 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
int part_size = 0;
|
||||
struct stat st;
|
||||
|
||||
if (wsgi_req->path_info_len == 0) return 0;
|
||||
|
||||
if (ptr[0] == '/') part_size++;
|
||||
|
||||
for(i=0;i<wsgi_req->path_info_len;i++) {
|
||||
@@ -334,9 +693,9 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char real_filename[PATH_MAX+1];
|
||||
uint16_t docroot_len = 0;
|
||||
char *path_info = NULL;
|
||||
size_t real_filename_len = 0;
|
||||
struct stat php_stat;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
|
||||
@@ -346,23 +705,36 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *docroot = uwsgi_get_var(wsgi_req, (char *) "DOCUMENT_ROOT", 13, &docroot_len);
|
||||
|
||||
if (!docroot) {
|
||||
docroot = uwsgi.cwd;
|
||||
docroot_len = strlen(uwsgi.cwd);
|
||||
if (uphp.docroot) {
|
||||
wsgi_req->document_root = uphp.docroot;
|
||||
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
|
||||
}
|
||||
// fallback to cwd
|
||||
else if (!wsgi_req->document_root_len) {
|
||||
wsgi_req->document_root = uwsgi.cwd;
|
||||
wsgi_req->document_root_len = strlen(uwsgi.cwd);
|
||||
}
|
||||
|
||||
char *filename = uwsgi_concat4n(docroot, docroot_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
|
||||
if (uphp.app) {
|
||||
strcpy(real_filename, uphp.app);
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
goto secure2;
|
||||
}
|
||||
|
||||
if (uwsgi_php_walk(wsgi_req, filename, docroot, docroot_len, &path_info)) {
|
||||
char *filename = uwsgi_concat4n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
|
||||
|
||||
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
uint16_t orig_path_info_len = wsgi_req->path_info_len;
|
||||
|
||||
if (path_info) {
|
||||
wsgi_req->path_info = path_info;
|
||||
wsgi_req->path_info_len = strlen(wsgi_req->path_info);
|
||||
wsgi_req->path_info_len = orig_path_info_len - (path_info - orig_path_info);
|
||||
}
|
||||
else {
|
||||
wsgi_req->path_info = "";
|
||||
@@ -394,6 +766,47 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
secure:
|
||||
|
||||
if (stat(real_filename, &php_stat)) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (S_ISDIR(php_stat.st_mode)) {
|
||||
|
||||
// add / to directories
|
||||
if (orig_path_info_len == 0 || (orig_path_info_len > 0 && orig_path_info[orig_path_info_len-1] != '/')) {
|
||||
wsgi_req->path_info = orig_path_info;
|
||||
wsgi_req->path_info_len = orig_path_info_len;
|
||||
uwsgi_php_redirect_to_slash(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
struct uwsgi_string_list *upi = uphp.index;
|
||||
real_filename[real_filename_len] = '/';
|
||||
real_filename_len++;
|
||||
int found = 0;
|
||||
while(upi) {
|
||||
if (real_filename_len + upi->len + 1 < PATH_MAX) {
|
||||
// add + 1 to ensure null byte
|
||||
memcpy(real_filename+real_filename_len, upi->value, upi->len + 1);
|
||||
if (!access(real_filename, R_OK)) {
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
upi = upi->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (uphp.allowed_ext) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_ext;
|
||||
while(usl) {
|
||||
@@ -414,19 +827,22 @@ secure2:
|
||||
wsgi_req->file = real_filename;
|
||||
wsgi_req->file_len = strlen(wsgi_req->file);
|
||||
|
||||
if (docroot[docroot_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (docroot_len-1);
|
||||
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name = real_filename + docroot_len;
|
||||
wsgi_req->script_name = real_filename + wsgi_req->document_root_len;
|
||||
}
|
||||
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("php filename = %s\n", real_filename);
|
||||
uwsgi_log("php filename = %s %.*s\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// now check for allowed paths and extensions
|
||||
|
||||
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
|
||||
@@ -437,6 +853,9 @@ secure2:
|
||||
SG(request_info).content_length = wsgi_req->post_cl;
|
||||
SG(request_info).content_type = estrndup(wsgi_req->content_type, wsgi_req->content_type_len);
|
||||
|
||||
// reinitialize it at every request !!!
|
||||
SG(sapi_headers).http_response_code = 200;
|
||||
|
||||
SG(request_info).path_translated = wsgi_req->file;
|
||||
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
@@ -444,7 +863,6 @@ secure2:
|
||||
file_handle.free_filename = 0;
|
||||
file_handle.opened_path = NULL;
|
||||
|
||||
|
||||
if (php_request_startup(TSRMLS_C) == FAILURE) {
|
||||
internal_server_error(wsgi_req, "unable to start php request");
|
||||
return -1;
|
||||
@@ -463,32 +881,13 @@ void uwsgi_php_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_php_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PHP_INI:
|
||||
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(optarg);
|
||||
uwsgi_sapi_module.php_ini_ignore = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_PHP_ALLOWED_DOCROOT:
|
||||
uwsgi_string_new_list(&uphp.allowed_docroot, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_PHP_ALLOWED_EXT:
|
||||
uwsgi_string_new_list(&uphp.allowed_ext, optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SAPI_API struct uwsgi_plugin php_plugin = {
|
||||
.name = "php",
|
||||
.modifier1 = 14,
|
||||
.init = uwsgi_php_init,
|
||||
.request = uwsgi_php_request,
|
||||
.after_request = uwsgi_php_after_request,
|
||||
.options = uwsgi_php_options,
|
||||
.manage_opt = uwsgi_php_manage_options,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import os
|
||||
|
||||
NAME='php'
|
||||
|
||||
ld_run_path = None
|
||||
PHPPATH = 'php-config'
|
||||
|
||||
try:
|
||||
phpdir = os.environ['UWSGICONFIG_PHPDIR']
|
||||
ld_run_path = "%s/lib" % phpdir
|
||||
PHPPATH = "%s/bin/php-config" % phpdir
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
|
||||
except:
|
||||
pass
|
||||
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip()]
|
||||
|
||||
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
|
||||
if ld_run_path:
|
||||
LDFLAGS.append('-L%s' % ld_run_path)
|
||||
os.environ['LD_RUN_PATH'] = ld_run_path
|
||||
|
||||
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
|
||||
|
||||
GCC_LIST = ['php_plugin']
|
||||
@@ -7,10 +7,10 @@ struct uwsgi_ping {
|
||||
int ping_timeout;
|
||||
} uping;
|
||||
|
||||
struct option uwsgi_ping_options[] = {
|
||||
{"ping", required_argument, 0, LONG_ARGS_PING},
|
||||
{"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
|
||||
{ 0, 0, 0, 0 }
|
||||
struct uwsgi_option uwsgi_ping_options[] = {
|
||||
{"ping", required_argument, 0, "ping specified uwsgi host", uwsgi_opt_set_str, &uping.ping, UWSGI_OPT_NO_INITIAL | UWSGI_OPT_NO_SERVER},
|
||||
{"ping-timeout", required_argument, 0, "set ping timeout", uwsgi_opt_set_int, &uping.ping_timeout, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void ping() {
|
||||
@@ -91,28 +91,11 @@ int uwsgi_request_ping(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
case LONG_ARGS_PING_TIMEOUT:
|
||||
uping.ping_timeout = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin ping_plugin = {
|
||||
|
||||
.name = "ping",
|
||||
.modifier1 = 100,
|
||||
.options = uwsgi_ping_options,
|
||||
.manage_opt = uwsgi_ping_manage_options,
|
||||
.request = uwsgi_request_ping,
|
||||
.init = ping_init,
|
||||
};
|
||||
|
||||
+22
-15
@@ -11,27 +11,32 @@
|
||||
|
||||
struct uwsgi_perl {
|
||||
|
||||
int fd;
|
||||
char *psgibuffer;
|
||||
// path of the statically loaded main app
|
||||
char *psgi;
|
||||
// locallib path
|
||||
char *locallib;
|
||||
|
||||
// perl argv for initialization
|
||||
char *embedding[3];
|
||||
PerlInterpreter *main;
|
||||
pthread_key_t u_interpreter;
|
||||
PerlInterpreter **interp;
|
||||
SV *psgi_main;
|
||||
SV **psgi_func;
|
||||
CV *stream_responder;
|
||||
HV *streaming_stash;
|
||||
HV *input_stash;
|
||||
HV *error_stash;
|
||||
|
||||
// check for Devel::StackTrace
|
||||
int stacktrace_available;
|
||||
|
||||
// this is a pointer to the main list of interpreters (required for signals, rpc....);
|
||||
PerlInterpreter **main;
|
||||
|
||||
// a lock for dynamic apps
|
||||
pthread_mutex_t lock_loader;
|
||||
|
||||
// this fields must be heavy protected in threaded modes
|
||||
int tmp_current_i;
|
||||
HV **tmp_streaming_stash;
|
||||
HV **tmp_input_stash;
|
||||
HV **tmp_error_stash;
|
||||
|
||||
CV **tmp_stream_responder;
|
||||
};
|
||||
|
||||
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 1000)
|
||||
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
|
||||
#define LONG_ARGS_PERL_LOCAL_LIB LONG_ARGS_PERL_BASE + 2
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
void uwsgi_psgi_app(void);
|
||||
int psgi_response(struct wsgi_request *, AV*);
|
||||
@@ -41,3 +46,5 @@ int psgi_response(struct wsgi_request *, AV*);
|
||||
|
||||
SV *uwsgi_perl_obj_call(SV *, char *);
|
||||
int uwsgi_perl_obj_can(SV *, char *, size_t);
|
||||
int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
|
||||
PerlInterpreter *uwsgi_perl_new_interpreter(void);
|
||||
|
||||
+246
-83
@@ -15,19 +15,23 @@ XS(XS_input_seek) {
|
||||
|
||||
XS(XS_error) {
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.error_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_input) {
|
||||
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
psgi_check_args(0);
|
||||
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.input_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -35,6 +39,7 @@ XS(XS_stream)
|
||||
{
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
@@ -47,7 +52,7 @@ XS(XS_stream)
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
else {
|
||||
@@ -184,6 +189,21 @@ XS(XS_error_print) {
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
XS(XS_uwsgi_stacktrace) {
|
||||
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
uwsgi_log("*** uWSGI perl stacktrace ***\n");
|
||||
SV *ret = perl_eval_pv("Devel::StackTrace->new->as_string;", 0);
|
||||
uwsgi_log("%s", SvPV_nolen(ret));
|
||||
uwsgi_log("*** end of perl stacktrace ***\n\n");
|
||||
XSRETURN(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* automatically generated */
|
||||
|
||||
EXTERN_C void xs_init (pTHX);
|
||||
@@ -203,18 +223,21 @@ xs_init(pTHX)
|
||||
newXS("uwsgi::input::read", XS_input_read, "uwsgi::input");
|
||||
newXS("uwsgi::input::seek", XS_input_seek, "uwsgi::input");
|
||||
|
||||
uperl.input_stash = gv_stashpv("uwsgi::input", 0);
|
||||
uperl.tmp_input_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::input", 0);
|
||||
|
||||
newXS("uwsgi::error::new", XS_error, "uwsgi::error");
|
||||
newXS("uwsgi::error::print", XS_error_print, "uwsgi::print");
|
||||
uperl.error_stash = gv_stashpv("uwsgi::error", 0);
|
||||
uperl.tmp_error_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::error", 0);
|
||||
|
||||
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
|
||||
uperl.tmp_stream_responder[uperl.tmp_current_i] = newXS("uwsgi::stream", XS_stream, "uwsgi");
|
||||
|
||||
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
|
||||
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
|
||||
|
||||
uperl.streaming_stash = gv_stashpv("uwsgi::streaming", 0);
|
||||
newXS("uwsgi::stacktrace", XS_uwsgi_stacktrace, "uwsgi");
|
||||
|
||||
|
||||
uperl.tmp_streaming_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::streaming", 0);
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
init_perl_embedded_module();
|
||||
@@ -224,87 +247,227 @@ xs_init(pTHX)
|
||||
|
||||
/* end of automagically generated part */
|
||||
|
||||
PerlInterpreter *uwsgi_perl_new_interpreter(void) {
|
||||
|
||||
PerlInterpreter *pi = perl_alloc();
|
||||
if (!pi) {
|
||||
uwsgi_log("unable to allocate perl interpreter\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(pi);
|
||||
|
||||
PL_perl_destruct_level = 2;
|
||||
PL_origalen = 1;
|
||||
perl_construct(pi);
|
||||
// over-engeneering
|
||||
PL_origalen = 1;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
static void uwsgi_perl_free_stashes(void) {
|
||||
free(uperl.tmp_streaming_stash);
|
||||
free(uperl.tmp_input_stash);
|
||||
free(uperl.tmp_error_stash);
|
||||
free(uperl.tmp_stream_responder);
|
||||
}
|
||||
|
||||
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
|
||||
|
||||
struct stat st;
|
||||
int i;
|
||||
SV **callables;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
|
||||
|
||||
// prepare for $0
|
||||
uperl.embedding[1] = app_name;
|
||||
|
||||
int fd = open(app_name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(app_name);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
close(fd);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
char *buf = uwsgi_calloc(st.st_size+1);
|
||||
if (read(fd, buf, st.st_size) != st.st_size) {
|
||||
uwsgi_error("read()");
|
||||
close(fd);
|
||||
free(buf);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
// the first (default) app, should always be loaded in the main interpreter
|
||||
if (interpreters == NULL) {
|
||||
if (uwsgi_apps_cnt) {
|
||||
interpreters = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
|
||||
interpreters[0] = uwsgi_perl_new_interpreter();
|
||||
if (!interpreters[0]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
free(interpreters);
|
||||
goto clear2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
interpreters = uperl.main;
|
||||
}
|
||||
}
|
||||
|
||||
if (!interpreters) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
|
||||
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
|
||||
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_input_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_error_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_stream_responder = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);
|
||||
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
|
||||
if (i > 0 && interpreters != uperl.main) {
|
||||
|
||||
interpreters[i] = uwsgi_perl_new_interpreter();
|
||||
if (!interpreters[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps...but clear the whole stuff...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
while(i>=0) {
|
||||
perl_destruct(interpreters[i]);
|
||||
perl_free(interpreters[i]);
|
||||
goto clear2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(interpreters[i]);
|
||||
|
||||
uperl.tmp_current_i = i;
|
||||
|
||||
|
||||
if (uperl.locallib) {
|
||||
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
|
||||
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
|
||||
uperl.embedding[2] = app_name;
|
||||
if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
|
||||
free(uperl.embedding[1]);
|
||||
uperl.embedding[1] = app_name;
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
free(uperl.embedding[1]);
|
||||
uperl.embedding[1] = app_name;
|
||||
}
|
||||
else {
|
||||
if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
if (!SvTRUE(ERRSV)) {
|
||||
uperl.stacktrace_available = 1;
|
||||
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
|
||||
}
|
||||
|
||||
SV *dollar_zero = get_sv("0", GV_ADD);
|
||||
sv_setsv(dollar_zero, newSVpv(app, app_len));
|
||||
|
||||
callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
|
||||
if (!callables[i]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(interpreters[0]);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *wi = NULL;
|
||||
|
||||
if (wsgi_req) {
|
||||
// we need a copy of app_id
|
||||
wi = uwsgi_add_app(id, 5, uwsgi_concat2n(wsgi_req->appid, wsgi_req->appid_len, "", 0), wsgi_req->appid_len, interpreters, callables);
|
||||
}
|
||||
else {
|
||||
wi = uwsgi_add_app(id, 5, "", 0, interpreters, callables);
|
||||
}
|
||||
|
||||
wi->started_at = now;
|
||||
wi->startup_time = uwsgi_now() - now;
|
||||
|
||||
uwsgi_log("PSGI app %d (%s) loaded in %d seconds at %p (interpreter %p)\n", id, app_name, (int) wi->startup_time, callables[0], interpreters[0]);
|
||||
free(app_name);
|
||||
|
||||
// copy global data to app-specific areas
|
||||
wi->stream = uperl.tmp_streaming_stash;
|
||||
wi->input = uperl.tmp_input_stash;
|
||||
wi->error = uperl.tmp_error_stash;
|
||||
wi->responder0 = uperl.tmp_stream_responder;
|
||||
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
|
||||
|
||||
// restore context if required
|
||||
if (interpreters != uperl.main) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
clear:
|
||||
if (interpreters != uperl.main) {
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
perl_destruct(interpreters[i]);
|
||||
perl_free(interpreters[i]);
|
||||
}
|
||||
free(interpreters);
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
clear2:
|
||||
free(app_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_psgi_app() {
|
||||
|
||||
struct stat stat_psgi;
|
||||
int id = uwsgi_apps_cnt;
|
||||
|
||||
if (uperl.psgi) {
|
||||
|
||||
// two-pass loading: parse the script -> eval the script
|
||||
|
||||
|
||||
|
||||
if (uperl.locallib) {
|
||||
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
|
||||
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
|
||||
uperl.embedding[2] = uperl.psgi;
|
||||
if (perl_parse(uperl.main, xs_init, 3, uperl.embedding, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uperl.embedding[1] = uperl.psgi;
|
||||
if (perl_parse(uperl.main, xs_init, 2, uperl.embedding, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
|
||||
SV *dollar_zero = get_sv("0", GV_ADD);
|
||||
sv_setsv(dollar_zero, newSVpv(uperl.psgi, 0));
|
||||
|
||||
SV *dollar_slash = get_sv("/", GV_ADD);
|
||||
sv_setsv(dollar_slash, newRV_inc(newSViv(uwsgi.buffer_size)));
|
||||
|
||||
uperl.fd = open(uperl.psgi, O_RDONLY);
|
||||
if (uperl.fd < 0) {
|
||||
uwsgi_error_open(uperl.psgi);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fstat(uperl.fd, &stat_psgi)) {
|
||||
uwsgi_error("fstat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
|
||||
if (!uperl.psgibuffer) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
|
||||
uwsgi_error("read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.psgibuffer[stat_psgi.st_size] = 0;
|
||||
|
||||
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
free(uperl.psgibuffer);
|
||||
close(uperl.fd);
|
||||
}
|
||||
|
||||
uwsgi_add_app(id, 5, "", 0);
|
||||
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
|
||||
|
||||
//load app in the main interpreter list
|
||||
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+138
-114
@@ -9,11 +9,11 @@ extern struct uwsgi_perl uperl;
|
||||
struct uwsgi_perl uperl;
|
||||
#endif
|
||||
|
||||
struct option uwsgi_perl_options[] = {
|
||||
struct uwsgi_option uwsgi_perl_options[] = {
|
||||
|
||||
{"psgi", required_argument, 0, LONG_ARGS_PSGI},
|
||||
{"perl-local-lib", required_argument, 0, LONG_ARGS_PERL_LOCAL_LIB},
|
||||
{0, 0, 0, 0},
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
@@ -22,8 +22,7 @@ extern struct http_status_codes hsc[];
|
||||
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SV *newobj;
|
||||
// set current context ?
|
||||
dTHX;
|
||||
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -48,21 +47,21 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
SV *uwsgi_perl_call_stream(SV *func) {
|
||||
|
||||
SV *ret = NULL;
|
||||
// set current context ?
|
||||
dTHX;
|
||||
dSP;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs( sv_2mortal(newRV((SV*) uperl.stream_responder)));
|
||||
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
|
||||
PUTBACK;
|
||||
|
||||
call_sv( func, G_SCALAR | G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = SvREFCNT_inc(POPs);
|
||||
@@ -78,8 +77,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
|
||||
int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
int ret;
|
||||
// set current context ? needed for threading
|
||||
dTHX;
|
||||
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -102,12 +100,10 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
SV *uwsgi_perl_obj_call(SV *obj, char *method) {
|
||||
|
||||
SV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -141,7 +137,6 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
AV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -156,7 +151,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
internal_server_error(wsgi_req, "exception raised");
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
|
||||
@@ -284,10 +279,19 @@ int uwsgi_perl_init(){
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
uperl.embedding[0] = "";
|
||||
uperl.embedding[1] = "-e";
|
||||
uperl.embedding[2] = "0";
|
||||
|
||||
#ifndef USE_ITHREADS
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_log("your Perl environment does not support threads\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (setenv("PLACK_ENV", "uwsgi", 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
@@ -296,92 +300,102 @@ int uwsgi_perl_init(){
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
#ifdef PERL_VERSION_STRING
|
||||
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
|
||||
#else
|
||||
uwsgi_log("initializing Perl environment\n");
|
||||
#endif
|
||||
|
||||
argc = 3;
|
||||
|
||||
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
|
||||
uperl.main = perl_alloc();
|
||||
if (!uperl.main) {
|
||||
uwsgi_log("unable to allocate perl interpreter\n");
|
||||
|
||||
uperl.main = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
|
||||
|
||||
uperl.main[0] = uwsgi_perl_new_interpreter();
|
||||
if (!uperl.main[0]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dTHXa(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main);
|
||||
for(i=1;i<uwsgi.threads;i++) {
|
||||
uperl.main[i] = uwsgi_perl_new_interpreter();
|
||||
if (!uperl.main[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter for thread %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
PL_perl_destruct_level = 2;
|
||||
PL_origalen = 1;
|
||||
perl_construct(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
PL_origalen = 1;
|
||||
#ifdef PERL_VERSION_STRING
|
||||
uwsgi_log("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
|
||||
#else
|
||||
uwsgi_log("initialized Perl main interpreter at %p\n", uperl.main[0]);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_enable_threads() {
|
||||
|
||||
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
uperl.interp[0] = uperl.main;
|
||||
|
||||
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
SV **harakiri;
|
||||
SV *psgi_func = uperl.psgi_main;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Standard PSGI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log("Invalid PSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
psgi_func = uperl.psgi_func[wsgi_req->async_id];
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 5);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (wsgi_req->dynamic) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
if (wsgi_req->script_len > 0) {
|
||||
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
|
||||
}
|
||||
else if (wsgi_req->file_len > 0) {
|
||||
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_unlock(&uperl.lock_loader);
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
internal_server_error(wsgi_req, "Perl application not found");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
wi->requests++;
|
||||
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
|
||||
}
|
||||
|
||||
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
wsgi_req->async_environ = build_psgi_env(wsgi_req);
|
||||
if (!wsgi_req->async_environ) goto clear;
|
||||
|
||||
wsgi_req->async_result = psgi_call(wsgi_req, psgi_func, wsgi_req->async_environ);
|
||||
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
|
||||
if (!wsgi_req->async_result) goto clear;
|
||||
|
||||
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
|
||||
@@ -419,6 +433,11 @@ clear:
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
// restore main interpreter if needed
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -435,56 +454,6 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
|
||||
|
||||
if (core_id > 0) {
|
||||
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[core_id]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
dTHXa(uperl.interp[core_id]);
|
||||
PERL_SET_CONTEXT(uperl.interp[core_id]);
|
||||
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
uperl.psgi_func[0] = uperl.psgi_main;
|
||||
if (core_id > 0) {
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_perl_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PSGI:
|
||||
uperl.psgi = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PERL_LOCAL_LIB:
|
||||
uperl.locallib = optarg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
if (!strcmp(lazy+strlen(lazy)-5, ".psgi")) {
|
||||
@@ -500,6 +469,61 @@ int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
}
|
||||
|
||||
// taken from Torsten Foertsch AfterFork.xs
|
||||
void uwsgi_perl_post_fork() {
|
||||
/*
|
||||
GV *tmpgv;
|
||||
|
||||
PL_ppid = (IV)getppid();
|
||||
hv_clear(PL_pidstatus);
|
||||
|
||||
tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
|
||||
if (tmpgv) {
|
||||
SvREADONLY_off(GvSV(tmpgv));
|
||||
sv_setiv(GvSV(tmpgv), (IV)getpid());
|
||||
SvREADONLY_on(GvSV(tmpgv));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
int uwsgi_perl_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
if (uwsgi_endswith(app, ".pl") || uwsgi_endswith(app, ".psgi")) {
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
|
||||
return init_psgi_app(uwsgi.wsgi_req, app, strlen(app), NULL);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
PERL_SET_CONTEXT(uperl.main[core_id]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_prepare(void) {
|
||||
pthread_mutex_lock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_parent(void) {
|
||||
pthread_mutex_unlock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_child(void) {
|
||||
pthread_mutex_init(&uperl.lock_loader, NULL);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_perl_enable_threads(void) {
|
||||
#ifdef USE_ITHREADS
|
||||
pthread_mutex_init(&uperl.lock_loader, NULL);
|
||||
pthread_atfork(uwsgi_perl_pthread_prepare, uwsgi_perl_pthread_parent, uwsgi_perl_pthread_child);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
@@ -507,16 +531,16 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.modifier1 = 5,
|
||||
.init = uwsgi_perl_init,
|
||||
.options = uwsgi_perl_options,
|
||||
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
//.magic = uwsgi_perl_magic,
|
||||
//.help = uwsgi_perl_help,
|
||||
#ifdef USE_ITHREADS
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
.mount_app = uwsgi_perl_mount_app,
|
||||
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
#endif
|
||||
.manage_opt = uwsgi_perl_manage_options,
|
||||
|
||||
.post_fork = uwsgi_perl_post_fork,
|
||||
.request = uwsgi_perl_request,
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
|
||||
.magic = uwsgi_perl_magic,
|
||||
};
|
||||
|
||||
@@ -96,6 +96,8 @@ XS(XS_cache_set) {
|
||||
char *key, *val;
|
||||
STRLEN keylen;
|
||||
STRLEN vallen;
|
||||
|
||||
if (uwsgi.cache_max_items == 0) goto clear;
|
||||
|
||||
psgi_check_args(2);
|
||||
|
||||
@@ -104,6 +106,7 @@ XS(XS_cache_set) {
|
||||
|
||||
uwsgi_cache_set(key, (uint16_t) keylen, val, (uint64_t) vallen, 0, 0);
|
||||
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
@@ -113,6 +116,8 @@ XS(XS_cache_get) {
|
||||
char *key, *val;
|
||||
STRLEN keylen;
|
||||
uint64_t vallen;
|
||||
|
||||
if (uwsgi.cache_max_items == 0) goto clear;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
@@ -121,6 +126,7 @@ XS(XS_cache_get) {
|
||||
val = uwsgi_cache_get(key, (uint16_t) keylen, &vallen);
|
||||
|
||||
if (!val)
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
|
||||
ST(0) = newSVpv(val, vallen);
|
||||
|
||||
+40
-22
@@ -86,6 +86,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
|
||||
|
||||
@@ -375,14 +376,17 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
|
||||
wi->started_at = now;
|
||||
wi->startup_time = uwsgi_now() - now;
|
||||
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
|
||||
|
||||
@@ -414,13 +418,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to emulate fork() COW
|
||||
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;
|
||||
}
|
||||
}
|
||||
// emulate COW
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
|
||||
return id;
|
||||
|
||||
@@ -539,7 +538,7 @@ PyObject *uwsgi_mount_loader(void *arg1) {
|
||||
|
||||
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
|
||||
callable = uwsgi_file_loader((void *)what);
|
||||
if (!callable) exit(1);
|
||||
if (!callable) exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
else if (!strcmp(what+strlen(what)-4, ".ini")) {
|
||||
callable = uwsgi_paste_loader((void *)what);
|
||||
@@ -655,39 +654,58 @@ PyObject *uwsgi_paste_loader(void *arg1) {
|
||||
PyObject *paste_arg, *paste_app;
|
||||
|
||||
uwsgi_log( "Loading paste environment: %s\n", paste);
|
||||
|
||||
if (up.paste_logger) {
|
||||
PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config");
|
||||
if (paste_logger_dict) {
|
||||
PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
|
||||
if (paste_logger_fileConfig) {
|
||||
PyObject *paste_logger_arg = PyTuple_New(1);
|
||||
if (!paste_logger_arg) {
|
||||
PyErr_Print();
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
PyTuple_SetItem(paste_logger_arg, 0, PyString_FromString(paste+7));
|
||||
if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
paste_module = PyImport_ImportModule("paste.deploy");
|
||||
if (!paste_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_dict = PyModule_GetDict(paste_module);
|
||||
if (!paste_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
|
||||
if (!paste_loadapp) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_arg = PyTuple_New(1);
|
||||
if (!paste_arg) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(paste))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
|
||||
if (!paste_app) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -709,7 +727,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (!wsgi_eval_node) {
|
||||
PyErr_Print();
|
||||
uwsgi_log( "failed to parse <eval> code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
|
||||
@@ -717,14 +735,14 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (!wsgi_compiled_node) {
|
||||
PyErr_Print();
|
||||
uwsgi_log( "failed to compile eval code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
|
||||
if (!wsgi_eval_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -733,7 +751,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
|
||||
if (!up.loader_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -748,7 +766,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (wsgi_eval_callable) {
|
||||
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
|
||||
uwsgi_log( "you must define a callable object in your code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+257
-261
@@ -9,80 +9,119 @@ extern struct http_status_codes hsc[];
|
||||
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
struct option uwsgi_python_options[] = {
|
||||
{"wsgi-file", required_argument, 0, LONG_ARGS_WSGI_FILE},
|
||||
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
|
||||
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
|
||||
{"module", required_argument, 0, 'w'},
|
||||
{"wsgi", required_argument, 0, 'w'},
|
||||
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
|
||||
{"test", required_argument, 0, 'J'},
|
||||
{"home", required_argument, 0, 'H'},
|
||||
{"virtualenv", required_argument, 0, 'H'},
|
||||
{"venv", required_argument, 0, 'H'},
|
||||
{"pyhome", required_argument, 0, 'H'},
|
||||
{"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
|
||||
{"python-path", required_argument, 0, LONG_ARGS_PYTHONPATH},
|
||||
{"pymodule-alias", required_argument, 0, LONG_ARGS_PYMODULE_ALIAS},
|
||||
{"post-pymodule-alias", required_argument, 0, LONG_ARGS_POST_PYMODULE_ALIAS},
|
||||
{"import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"shared-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-pyimport", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-py-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-python-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-python-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
|
||||
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
|
||||
{"optimize", required_argument, 0, 'O'},
|
||||
{"paste", required_argument, 0, LONG_ARGS_PASTE},
|
||||
{"web3", required_argument, 0, LONG_ARGS_WEB3},
|
||||
{"pump", required_argument, 0, LONG_ARGS_PUMP},
|
||||
{"wsgi-lite", required_argument, 0, LONG_ARGS_WSGI_LITE},
|
||||
void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
glob_t g;
|
||||
|
||||
if (glob(value, GLOB_MARK, NULL, &g)) {
|
||||
uwsgi_string_new_list(&up.python_path, value);
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < (int) g.gl_pathc; i++) {
|
||||
uwsgi_string_new_list(&up.python_path, g.gl_pathv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_pyshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
|
||||
if (!strcmp("pyshell-oneshot", opt)) {
|
||||
up.pyshell_oneshot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
|
||||
uwsgi.honour_stdin = 1;
|
||||
uwsgi.command_mode = 1;
|
||||
up.pyrun = value;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
|
||||
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi_opt_load_ini(opt, value, NULL);
|
||||
|
||||
if (value[0] != '/') {
|
||||
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", value);
|
||||
}
|
||||
else {
|
||||
up.paste = uwsgi_concat2("config:", value);
|
||||
}
|
||||
|
||||
if (!strcmp("ini-paste-logged", opt)) {
|
||||
up.paste_logger = 1;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
{"catch-exceptions", no_argument, &up.catch_exceptions, 1},
|
||||
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
|
||||
{"pep3333-input", no_argument, &up.pep3333_input, 1},
|
||||
{"reload-os-env", no_argument, &up.reload_os_env, 1},
|
||||
|
||||
struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
|
||||
{"file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
|
||||
{"eval", required_argument, 0, "eval python code", uwsgi_opt_set_str, &up.eval, 0},
|
||||
{"module", required_argument,'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
|
||||
{"wsgi", required_argument, 'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
|
||||
{"callable", required_argument, 0, "set default WSGI callable name", uwsgi_opt_set_str, &up.callable, 0},
|
||||
{"test", required_argument, 'J', "test a mdule import", uwsgi_opt_set_str, &up.test_module, 0},
|
||||
{"home", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"pyhome", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
|
||||
{"pythonpath", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
|
||||
{"python-path", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
|
||||
{"pp", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
|
||||
|
||||
{"pymodule-alias", required_argument, 0, "add a python alias module", uwsgi_opt_add_string_list, &up.pymodule_alias, 0},
|
||||
{"post-pymodule-alias", required_argument, 0, "add a python module alias after uwsgi module initialization", uwsgi_opt_add_string_list, &up.post_pymodule_alias, 0},
|
||||
|
||||
{"import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
|
||||
{"pyimport", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
|
||||
{"py-import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
|
||||
{"python-import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
|
||||
|
||||
{"shared-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
|
||||
{"shared-pyimport", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
|
||||
{"shared-py-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
|
||||
{"shared-python-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
|
||||
|
||||
{"spooler-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
|
||||
{"spooler-pyimport", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
|
||||
{"spooler-py-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
|
||||
{"spooler-python-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
|
||||
|
||||
{"pyargv", required_argument, 0, "manually set sys.argv", uwsgi_opt_set_str, &up.argv, 0},
|
||||
{"optimize", required_argument, 'O', "set python optimization level", uwsgi_opt_set_int, &up.optimize, 0},
|
||||
|
||||
{"paste", required_argument, 0, "load a paste.deploy config file", uwsgi_opt_set_str, &up.paste, 0},
|
||||
{"paste-logger", no_argument, 0, "enable paste fileConfig logger", uwsgi_opt_true, &up.paste_logger, 0},
|
||||
|
||||
|
||||
{"web3", required_argument, 0, "load a web3 app", uwsgi_opt_set_str, &up.web3, 0},
|
||||
{"pump", required_argument, 0, "load a pump app", uwsgi_opt_set_str, &up.pump, 0},
|
||||
{"wsgi-lite", required_argument, 0, "load a wsgi-lite app", uwsgi_opt_set_str, &up.wsgi_lite, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &up.catch_exceptions, 0},
|
||||
{"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &up.ignore_script_name, 0},
|
||||
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
|
||||
#ifndef UWSGI_PYPY
|
||||
{"no-site", no_argument, &Py_NoSiteFlag, 1},
|
||||
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
|
||||
#endif
|
||||
{"pyshell", no_argument, 0, LONG_ARGS_PYSHELL},
|
||||
{"python", required_argument, 0, LONG_ARGS_PYTHON_RUN},
|
||||
{"py", required_argument, 0, LONG_ARGS_PYTHON_RUN},
|
||||
{"pyshell", no_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", no_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
{"python", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
|
||||
|
||||
struct uwsgi_help_item uwsgi_python_help[] = {
|
||||
|
||||
{"module <module>" ,"name of python config module"},
|
||||
{"optimize <n>", "set python optimization level to <n>"},
|
||||
{"home <path>", "set python home/virtualenv"},
|
||||
{"pyhome <path>", "set python home/virtualenv"},
|
||||
{"virtualenv <path>", "set python home/virtualenv"},
|
||||
{"venv <path>", "set python home/virtualenv"},
|
||||
{"callable <callable>", "set the callable (default 'application')"},
|
||||
{"paste <config:/egg:>", "load applications using paste.deploy.loadapp()"},
|
||||
{"pythonpath <dir>", "add <dir> to PYTHONPATH"},
|
||||
{"python-path <dir>", "add <dir> to PYTHONPATH"},
|
||||
{"pp <dir>", "add <dir> to PYTHONPATH"},
|
||||
{"pyargv <args>", "assign args to python sys.argv"},
|
||||
{"wsgi-file <file>", "load the <file> wsgi file"},
|
||||
{"file <file>", "use python file instead of python module for configuration"},
|
||||
{"eval <code>", "evaluate code for app configuration"},
|
||||
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
|
||||
{"pyshell", "run a python interactive shell in the uwsgi environment (steals a worker)"},
|
||||
|
||||
|
||||
{ 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
/* this routine will be called after each fork to reinitialize the various locks */
|
||||
@@ -98,11 +137,6 @@ void uwsgi_python_pthread_child(void) {
|
||||
pthread_mutex_init(&up.lock_pyloaders, NULL);
|
||||
}
|
||||
|
||||
// fake method
|
||||
PyMethodDef null_methods[] = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
|
||||
|
||||
@@ -195,13 +229,60 @@ void uwsgi_python_reset_random_seed() {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_python_atexit() {
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
return;
|
||||
|
||||
// if busy do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].busy)
|
||||
return;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
// managing atexit in async mode is a real pain...skip it for now
|
||||
if (uwsgi.async > 1)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// this time we use this higher level function
|
||||
// as this code can be executed in a signal handler
|
||||
|
||||
if (!Py_IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi.has_threads)
|
||||
PyGILState_Ensure();
|
||||
// no need to worry about freeing memory
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
|
||||
if (ae) {
|
||||
python_call(ae, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// this part is a 1:1 copy of mod_wsgi 3.x
|
||||
// it is required to fix some atexit bug with python 3
|
||||
// and to shutdown useless threads complaints
|
||||
PyObject *module = PyImport_ImportModule("atexit");
|
||||
Py_XDECREF(module);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
if (!PyImport_AddModule("dummy_threading"))
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
void uwsgi_python_post_fork() {
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.shared->spooler_pid == getpid()) {
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -320,7 +401,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
|
||||
void init_uwsgi_vars() {
|
||||
|
||||
int i;
|
||||
PyObject *pysys, *pysys_dict, *pypath;
|
||||
|
||||
PyObject *modules = PyImport_GetModuleDict();
|
||||
@@ -364,9 +444,10 @@ void init_uwsgi_vars() {
|
||||
uppp = uppp->next;
|
||||
}
|
||||
|
||||
for (i = 0; i < up.pymodule_alias_cnt; i++) {
|
||||
struct uwsgi_string_list *uppma = up.pymodule_alias;
|
||||
while(uppma) {
|
||||
// split key=value
|
||||
char *value = strchr(up.pymodule_alias[i], '=');
|
||||
char *value = strchr(uppma->value, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("invalid pymodule-alias syntax\n");
|
||||
continue;
|
||||
@@ -380,39 +461,43 @@ void init_uwsgi_vars() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PyDict_SetItemString(modules, up.pymodule_alias[i], tmp_module);
|
||||
PyDict_SetItemString(modules, uppma->value, tmp_module);
|
||||
}
|
||||
else {
|
||||
// this is a filepath that need to be mapped
|
||||
tmp_module = uwsgi_pyimport_by_filename(up.pymodule_alias[i], value + 1);
|
||||
tmp_module = uwsgi_pyimport_by_filename(uppma->value, value + 1);
|
||||
if (!tmp_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", up.pymodule_alias[i], value + 1);
|
||||
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", uppma->value, value + 1);
|
||||
// reset original value
|
||||
value[0] = '=';
|
||||
|
||||
uppma = uppma->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyDoc_STRVAR(uwsgi_py_doc, "uWSGI api module.");
|
||||
|
||||
|
||||
#ifdef PYTHREE
|
||||
static PyModuleDef uwsgi_module3 = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"uwsgi",
|
||||
NULL,
|
||||
uwsgi_py_doc,
|
||||
-1,
|
||||
null_methods,
|
||||
NULL,
|
||||
};
|
||||
PyObject *init_uwsgi3(void) {
|
||||
return PyModule_Create(&uwsgi_module3);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
void init_uwsgi_embedded_module() {
|
||||
PyObject *new_uwsgi_module, *zero;
|
||||
@@ -429,18 +514,19 @@ void init_uwsgi_embedded_module() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyImport_AppendInittab("uwsgi", init_uwsgi3);
|
||||
new_uwsgi_module = PyImport_AddModule("uwsgi");
|
||||
#else
|
||||
new_uwsgi_module = Py_InitModule("uwsgi", null_methods);
|
||||
new_uwsgi_module = Py_InitModule3("uwsgi", NULL, uwsgi_py_doc);
|
||||
#endif
|
||||
if (new_uwsgi_module == NULL) {
|
||||
uwsgi_log("could not initialize the uwsgi python module\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Py_INCREF((PyObject *) &uwsgi_InputType);
|
||||
|
||||
up.embedded_dict = PyModule_GetDict(new_uwsgi_module);
|
||||
@@ -471,6 +557,7 @@ void init_uwsgi_embedded_module() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "hostname", PyString_FromStringAndSize(uwsgi.hostname, uwsgi.hostname_len))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
@@ -490,6 +577,31 @@ void init_uwsgi_embedded_module() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spoolers) {
|
||||
int sc = 0;
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while(uspool) { sc++; uspool = uspool->next;}
|
||||
|
||||
PyObject *py_spooler_tuple = PyTuple_New(sc);
|
||||
|
||||
uspool = uwsgi.spoolers;
|
||||
sc = 0;
|
||||
|
||||
while(uspool) {
|
||||
PyTuple_SetItem(py_spooler_tuple, sc, PyString_FromString(uspool->dir));
|
||||
sc++;
|
||||
uspool = uspool->next;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "spoolers", py_spooler_tuple)) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "SPOOL_RETRY", PyInt_FromLong(-1))) {
|
||||
PyErr_Print();
|
||||
@@ -609,11 +721,6 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "fastfuncs", PyList_New(256))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (PyDict_SetItemString(up.embedded_dict, "applications", Py_None)) {
|
||||
PyErr_Print();
|
||||
@@ -644,16 +751,10 @@ void init_uwsgi_embedded_module() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
up.fastfuncslist = PyDict_GetItemString(up.embedded_dict, "fastfuncs");
|
||||
if (!up.fastfuncslist) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_uwsgi_module_advanced(new_uwsgi_module);
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir != NULL) {
|
||||
if (uwsgi.spoolers) {
|
||||
init_uwsgi_module_spooler(new_uwsgi_module);
|
||||
}
|
||||
#endif
|
||||
@@ -714,114 +815,19 @@ int uwsgi_python_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
|
||||
glob_t g;
|
||||
int j;
|
||||
|
||||
switch (i) {
|
||||
case 'w':
|
||||
up.wsgi_config = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_WSGI_FILE:
|
||||
case LONG_ARGS_FILE_CONFIG:
|
||||
up.file_config = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_EVAL_CONFIG:
|
||||
up.eval = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PYMODULE_ALIAS:
|
||||
if (up.pymodule_alias_cnt < MAX_PYMODULE_ALIAS) {
|
||||
up.pymodule_alias[up.pymodule_alias_cnt] = optarg;
|
||||
up.pymodule_alias_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_PYSHELL:
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_SHARED_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.shared_import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_SPOOLER_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.spooler_import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_POST_PYMODULE_ALIAS:
|
||||
uwsgi_string_new_list(&up.post_pymodule_alias, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_PYTHONPATH:
|
||||
if (glob(optarg, GLOB_MARK, NULL, &g)) {
|
||||
uwsgi_string_new_list(&up.python_path, optarg);
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < (int) g.gl_pathc; j++) {
|
||||
uwsgi_string_new_list(&up.python_path, g.gl_pathv[j]);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_PYARGV:
|
||||
up.argv = optarg;
|
||||
return 1;
|
||||
case 'J':
|
||||
up.test_module = optarg;
|
||||
return 1;
|
||||
case 'H':
|
||||
up.home = optarg;
|
||||
return 1;
|
||||
case 'O':
|
||||
up.optimize = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CALLABLE:
|
||||
up.callable = optarg;
|
||||
return 1;
|
||||
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
case LONG_ARGS_INI_PASTE:
|
||||
uwsgi_string_new_list(&uwsgi.ini,optarg);
|
||||
if (optarg[0] != '/') {
|
||||
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", optarg);
|
||||
}
|
||||
else {
|
||||
up.paste = uwsgi_concat2("config:", optarg);
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
case LONG_ARGS_WEB3:
|
||||
up.web3 = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PUMP:
|
||||
up.pump = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_WSGI_LITE:
|
||||
up.wsgi_lite = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PASTE:
|
||||
up.paste = optarg;
|
||||
return 1;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
int id;
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
if (uwsgi.single_interpreter) {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
|
||||
if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) {
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
if (uwsgi.single_interpreter) {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
int i;
|
||||
@@ -837,7 +843,9 @@ int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
}
|
||||
#endif
|
||||
|
||||
return id;
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
@@ -1053,6 +1061,16 @@ void uwsgi_python_init_apps() {
|
||||
#endif
|
||||
}
|
||||
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
up.after_req_hook = PyDict_GetItemString(uwsgi_dict, "after_req_hook");
|
||||
if (up.after_req_hook) {
|
||||
Py_INCREF(up.after_req_hook);
|
||||
up.after_req_hook_args = PyTuple_New(0);
|
||||
Py_INCREF(up.after_req_hook_args);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_master_fixup(int step) {
|
||||
@@ -1149,56 +1167,6 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_python_xml(char *node, char *content) {
|
||||
|
||||
PyThreadState *interpreter = NULL;
|
||||
|
||||
if (uwsgi.single_interpreter) {
|
||||
interpreter = up.main_thread;
|
||||
}
|
||||
|
||||
if (!strcmp("script", node)) {
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("file", node)) {
|
||||
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("eval", node)) {
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("wsgi", node)) {
|
||||
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else if (!strcmp("module", node)) {
|
||||
uwsgi.wsgi_req->module = content;
|
||||
uwsgi.wsgi_req->module_len = strlen(content);
|
||||
uwsgi.wsgi_req->callable = strchr(uwsgi.wsgi_req->module, ':');
|
||||
if (uwsgi.wsgi_req->callable) {
|
||||
uwsgi.wsgi_req->callable[0] = 0;
|
||||
uwsgi.wsgi_req->callable++;
|
||||
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
|
||||
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp("pyhome", node)) {
|
||||
uwsgi.wsgi_req->pyhome = content;
|
||||
uwsgi.wsgi_req->pyhome_len = strlen(content);
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp("callable", node)) {
|
||||
uwsgi.wsgi_req->callable = content;
|
||||
uwsgi.wsgi_req->callable_len = strlen(content);
|
||||
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
|
||||
|
||||
@@ -1431,13 +1399,35 @@ void uwsgi_python_fixup() {
|
||||
uwsgi.p[30] = uwsgi_malloc( sizeof(struct uwsgi_plugin) );
|
||||
memcpy(uwsgi.p[30], uwsgi.p[0], sizeof(struct uwsgi_plugin) );
|
||||
uwsgi.p[30]->init_thread = NULL;
|
||||
uwsgi.p[30]->atexit = NULL;
|
||||
}
|
||||
|
||||
void uwsgi_python_hijack(void) {
|
||||
|
||||
// the pyshell will be execute only in the first worker
|
||||
|
||||
FILE *pyfile;
|
||||
if (up.pyrun) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
UWSGI_GET_GIL;
|
||||
pyfile = fopen(up.pyrun, "r");
|
||||
if (!pyfile) {
|
||||
uwsgi_error_open(up.pyrun);
|
||||
exit(1);
|
||||
}
|
||||
PyRun_SimpleFile(pyfile, up.pyrun);
|
||||
// could be never executed
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 0;
|
||||
return;
|
||||
}
|
||||
if (up.pyshell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
@@ -1449,7 +1439,15 @@ void uwsgi_python_hijack(void) {
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
PyImport_ImportModule("readline");
|
||||
PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
|
||||
|
||||
if (up.pyshell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
@@ -1505,8 +1503,6 @@ struct uwsgi_plugin python_plugin = {
|
||||
.init = uwsgi_python_init,
|
||||
.post_fork = uwsgi_python_post_fork,
|
||||
.options = uwsgi_python_options,
|
||||
.manage_opt = uwsgi_python_manage_options,
|
||||
.short_options = "w:O:H:J:",
|
||||
.request = uwsgi_request_wsgi,
|
||||
.after_request = uwsgi_after_request_wsgi,
|
||||
|
||||
@@ -1520,7 +1516,6 @@ struct uwsgi_plugin python_plugin = {
|
||||
|
||||
.enable_threads = uwsgi_python_enable_threads,
|
||||
.init_thread = uwsgi_python_init_thread,
|
||||
.manage_xml = uwsgi_python_xml,
|
||||
|
||||
.magic = uwsgi_python_magic,
|
||||
|
||||
@@ -1540,8 +1535,9 @@ struct uwsgi_plugin python_plugin = {
|
||||
|
||||
.spooler = uwsgi_python_spooler,
|
||||
|
||||
.atexit = uwsgi_python_atexit,
|
||||
|
||||
.code_string = uwsgi_python_code_string,
|
||||
|
||||
.help = uwsgi_python_help,
|
||||
|
||||
};
|
||||
|
||||
+43
-19
@@ -64,24 +64,51 @@ void init_pyargv() {
|
||||
|
||||
char *ap;
|
||||
|
||||
char *argv0 = "uwsgi";
|
||||
|
||||
if (up.pyrun) {
|
||||
argv0 = up.pyrun;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t pname[6];
|
||||
mbstowcs(pname, "uwsgi", 6);
|
||||
up.py_argv[0] = pname;
|
||||
wchar_t *pname = uwsgi_calloc(strlen(argv0)+1);
|
||||
mbstowcs(pname, argv0, strlen(argv0)+1);
|
||||
#else
|
||||
up.py_argv[0] = "uwsgi";
|
||||
char *pname = argv0;
|
||||
#endif
|
||||
|
||||
up.argc = 1;
|
||||
|
||||
if (up.argv != NULL) {
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
if (!wcargv) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
if (up.argv) {
|
||||
char *tmp_ptr = uwsgi_str(up.argv);
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(tmp_ptr, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
up.argc++;
|
||||
}
|
||||
}
|
||||
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
|
||||
free(tmp_ptr);
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
up.py_argv = uwsgi_calloc(sizeof(wchar_t *) * up.argc+1);
|
||||
#else
|
||||
up.py_argv = uwsgi_calloc(sizeof(char *) * up.argc+1);
|
||||
#endif
|
||||
|
||||
up.py_argv[0] = pname;
|
||||
|
||||
|
||||
if (up.argv) {
|
||||
|
||||
up.argc = 1;
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -89,7 +116,7 @@ void init_pyargv() {
|
||||
ap = strtok(up.argv, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&up.argv, " \t")) != NULL) {
|
||||
while ((ap = strsep(&up.argv, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
#ifdef PYTHREE
|
||||
@@ -100,14 +127,11 @@ void init_pyargv() {
|
||||
#endif
|
||||
up.argc++;
|
||||
}
|
||||
if (up.argc + 1 > MAX_PYARGV)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
PySys_SetArgv(up.argc, up.py_argv);
|
||||
#endif
|
||||
}
|
||||
|
||||
PySys_SetArgv(up.argc, up.py_argv);
|
||||
|
||||
PyObject *sys_dict = get_uwsgi_pydict("sys");
|
||||
if (!sys_dict) {
|
||||
|
||||
+253
-71
@@ -312,7 +312,9 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -381,7 +383,9 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -884,7 +888,7 @@ PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
@@ -894,13 +898,47 @@ PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_is_locked(PyObject * self, PyObject * args) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i:is_locked", &lock_num)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (uwsgi_lock_check(uwsgi.user_lock[lock_num]) == 0) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_False);
|
||||
return Py_False;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
@@ -913,7 +951,9 @@ PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -924,7 +964,7 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
|
||||
int lock_num = 0;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
@@ -937,7 +977,6 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -1035,7 +1074,9 @@ PyObject *py_uwsgi_farm_msg(PyObject * self, PyObject * args) {
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
|
||||
if (!strcmp(farm_name, uwsgi.farms[i].name)) {
|
||||
UWSGI_RELEASE_GIL
|
||||
len = write(uwsgi.farms[i].queue_pipe[0], message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
if (len <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
@@ -1066,7 +1107,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "no mule configured");
|
||||
|
||||
if (mule_obj == NULL) {
|
||||
UWSGI_RELEASE_GIL
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else {
|
||||
if (PyString_Check(mule_obj)) {
|
||||
@@ -1093,7 +1136,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
mule_send_msg(fd, message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,6 +1283,8 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
@@ -1245,11 +1292,10 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
|
||||
value = current_value + value;
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return ret;
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1271,16 +1317,17 @@ PyObject *py_uwsgi_sharedarea_writelong(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1303,15 +1350,19 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, value, value_len);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value_len);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value_len);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -1334,15 +1385,18 @@ PyObject *py_uwsgi_sharedarea_writebyte(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
uwsgi.sharedarea[pos] = value;
|
||||
|
||||
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1364,15 +1418,18 @@ PyObject *py_uwsgi_sharedarea_readlong(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(&value, uwsgi.sharedarea + pos, 8);
|
||||
|
||||
PyObject *ret = PyLong_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyLong_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1394,13 +1451,17 @@ PyObject *py_uwsgi_sharedarea_readbyte(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
|
||||
char value = uwsgi.sharedarea[pos];
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1422,12 +1483,23 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(NULL, len);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(ret);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(ret);
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(uwsgi.sharedarea + pos, len);
|
||||
memcpy(storage, uwsgi.sharedarea + pos, len);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1452,23 +1524,25 @@ PyObject *py_uwsgi_spooler_jobs(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *jobslist = PyList_New(0);
|
||||
|
||||
sdir = opendir(uwsgi.spool_dir);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
sdir = opendir(uspool->dir);
|
||||
|
||||
if (sdir) {
|
||||
while ((dp = readdir(sdir)) != NULL) {
|
||||
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
|
||||
abs_path = malloc(strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
abs_path = malloc(strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
|
||||
if (!abs_path) {
|
||||
uwsgi_error("malloc()");
|
||||
closedir(sdir);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
memset(abs_path, 0, strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
memset(abs_path, 0, strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
|
||||
|
||||
memcpy(abs_path, uwsgi.spool_dir, strlen(uwsgi.spool_dir));
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir), "/", 1);
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir) + 1, dp->d_name, strlen(dp->d_name));
|
||||
memcpy(abs_path, uspool->dir, strlen(uspool->dir));
|
||||
memcpy(abs_path + strlen(uspool->dir), "/", 1);
|
||||
memcpy(abs_path + strlen(uspool->dir) + 1, dp->d_name, strlen(dp->d_name));
|
||||
|
||||
|
||||
if (lstat(abs_path, &sf_lstat)) {
|
||||
@@ -1510,6 +1584,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
spool_dict = PyTuple_GetItem(args, 0);
|
||||
|
||||
if (spool_dict) {
|
||||
@@ -1529,6 +1605,17 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
|
||||
}
|
||||
|
||||
// TODO if "spooler" is a num, get the spooler by id, otherwise get it by directory
|
||||
PyObject *py_spooler = uwsgi_py_dict_get(spool_dict, "spooler");
|
||||
if (py_spooler) {
|
||||
if (PyString_Check(py_spooler)) {
|
||||
uspool = uwsgi_get_spooler_by_name(PyString_AsString(py_spooler));
|
||||
if (!uspool) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unknown spooler requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pyprio = uwsgi_py_dict_get(spool_dict, "priority");
|
||||
if (pyprio) {
|
||||
if (PyInt_Check(pyprio)) {
|
||||
@@ -1631,7 +1718,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
|
||||
if (priority) {
|
||||
free(priority);
|
||||
}
|
||||
@@ -1651,7 +1738,9 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uwsgi.shared->spooler_pid ? uwsgi.shared->spooler_pid : 0);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (!uwsgi.spoolers) return PyInt_FromLong(0);
|
||||
return PyInt_FromLong(uspool->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1847,24 +1936,6 @@ PyObject *py_uwsgi_set_option(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
|
||||
int modifier;
|
||||
char *plugin_name = NULL;
|
||||
char *pargs = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_load_plugin(modifier, plugin_name, pargs, 1)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -1879,7 +1950,9 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
|
||||
uwsgi_message = uwsgi_malloc(message_len+4);
|
||||
memcpy(uwsgi_message+4, message, message_len);
|
||||
UWSGI_RELEASE_GIL
|
||||
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, 0, host, uwsgi_message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
free(uwsgi_message);
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -2249,9 +2322,12 @@ PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to connect to host %s", addr);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
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) {
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "unable to send uwsgi request to host %s", addr);
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// request sent, return the iterator response
|
||||
uwsgi_Iter *ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
|
||||
@@ -2301,7 +2377,9 @@ PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
|
||||
uwsgi_fd = PyInt_AsLong(destination);
|
||||
}
|
||||
else if (PyString_Check(destination)) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_fd = uwsgi_connect(PyString_AsString(destination), timeout, 0);
|
||||
UWSGI_GET_GIL
|
||||
close_fd = 1;
|
||||
}
|
||||
|
||||
@@ -2438,7 +2516,7 @@ 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) {
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
zero = PyString_FromString("pause");
|
||||
}
|
||||
else {
|
||||
@@ -2514,6 +2592,8 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
PyDict_SetItemString(apps_dict, "mountpoint", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
PyDict_SetItemString(apps_dict, "startup_time", PyInt_FromLong((long) ua->startup_time));
|
||||
|
||||
PyDict_SetItemString(apps_dict, "interpreter", PyInt_FromLong((long)ua->interpreter));
|
||||
PyDict_SetItemString(apps_dict, "callable", PyInt_FromLong((long)ua->interpreter));
|
||||
|
||||
@@ -2663,30 +2743,38 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
UWSGI_GET_GIL
|
||||
goto clear;
|
||||
}
|
||||
|
||||
len = read(fd, &uh, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("read()");
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
buffer = malloc(uh.pktsize);
|
||||
if (!buffer) {
|
||||
uwsgi_error("malloc()");
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
len = read(fd, buffer, uh.pktsize);
|
||||
if (len != uh.pktsize) {
|
||||
uwsgi_error("read()");
|
||||
free(buffer);
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + uh.pktsize;
|
||||
|
||||
@@ -2775,12 +2863,15 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
uwsgi_error("fork()");
|
||||
goto clear;
|
||||
}
|
||||
// now i am a grunt, avoid it making mess
|
||||
else if (grunt_pid == 0) {
|
||||
// it will no more accepts requests
|
||||
uwsgi_close_all_sockets();
|
||||
// create a new session
|
||||
setsid();
|
||||
// exit on SIGPIPE
|
||||
signal(SIGPIPE, (void *) &end_me);
|
||||
// here we create a new worker. Each grunt will race on this datas, so do not rely on them
|
||||
uwsgi.mywid = uwsgi.numproc + 1;
|
||||
uwsgi.mypid = getpid();
|
||||
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
|
||||
@@ -2797,7 +2888,7 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
// close connection on the worker
|
||||
// close connection on the original worker
|
||||
if (PyTuple_Size(args) == 0) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
@@ -2939,8 +3030,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"log_this_request", py_uwsgi_log_this, METH_VARARGS, ""},
|
||||
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
|
||||
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
|
||||
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
|
||||
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
|
||||
{"is_locked", py_uwsgi_is_locked, METH_VARARGS, ""},
|
||||
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
|
||||
{"cl", py_uwsgi_cl, METH_VARARGS, ""},
|
||||
|
||||
@@ -3036,16 +3127,21 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string(remote, 111, 2, key, keylen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3073,16 +3169,21 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3109,16 +3210,21 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3170,16 +3276,20 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_push(message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3200,16 +3310,20 @@ PyObject *py_uwsgi_queue_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_set(pos, message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3237,16 +3351,27 @@ PyObject *py_uwsgi_queue_pull(PyObject * self, PyObject * args) {
|
||||
PyObject *res;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
message = uwsgi_queue_pull(&size);
|
||||
UWSGI_GET_GIL
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
res = PyString_FromStringAndSize(NULL, size);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(res);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(res);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
memcpy(storage, message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3262,16 +3387,27 @@ PyObject *py_uwsgi_queue_pop(PyObject * self, PyObject * args) {
|
||||
PyObject *res;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
message = uwsgi_queue_pop(&size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
UWSGI_GET_GIL
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(NULL, size);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(res);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(res);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
memcpy(storage, message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3293,16 +3429,27 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
message = uwsgi_queue_get(index, &size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(NULL, size);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(res);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(res);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
memcpy(storage, message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3315,7 +3462,7 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
long num = 0;
|
||||
uint64_t size = 0;
|
||||
char *message;
|
||||
PyObject *res = NULL, *zero;
|
||||
PyObject *res = NULL;
|
||||
uint64_t base;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|l:queue_last", &num)) {
|
||||
@@ -3328,6 +3475,7 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
res = PyList_New(0);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
|
||||
if (uwsgi.queue_header->pos > 0) {
|
||||
@@ -3339,15 +3487,24 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
if (num == 0) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
if (message && size) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
UWSGI_GET_GIL
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(NULL, size);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(res);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(res);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
memcpy(storage, message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3355,13 +3512,23 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
while(num) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
UWSGI_GET_GIL
|
||||
if (message && size) {
|
||||
zero = PyString_FromStringAndSize(message, size);
|
||||
PyObject *zero = PyString_FromStringAndSize(NULL, size);
|
||||
PyList_Append(res, zero);
|
||||
Py_DECREF(zero);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(res);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(res);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
memcpy(storage, message, size);
|
||||
}
|
||||
else {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
if (base > 0) {
|
||||
@@ -3372,7 +3539,9 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
}
|
||||
num--;
|
||||
}
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3390,7 +3559,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
char *value = NULL;
|
||||
char *remote = NULL;
|
||||
char buffer[0xffff];
|
||||
PyObject *res;
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
struct timeval tv, tv2;
|
||||
@@ -3401,7 +3570,9 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize16, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
if (valsize16 > 0) {
|
||||
value = buffer;
|
||||
valsize = valsize16;
|
||||
@@ -3411,22 +3582,33 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
gettimeofday(&tv, NULL);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
res = PyString_FromStringAndSize(value, valsize);
|
||||
UWSGI_GET_GIL
|
||||
ret = PyString_FromStringAndSize(NULL, valsize);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(ret);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(ret);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
#ifdef UWSGI_DEBUG
|
||||
gettimeofday(&tv2, NULL);
|
||||
if ((tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec) > 30000) {
|
||||
uwsgi_log("[slow] cache get done in %d microseconds (%llu bytes value)\n", (tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec), (unsigned long long) valsize);
|
||||
}
|
||||
#endif
|
||||
memcpy(storage, value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return res;
|
||||
UWSGI_GET_GIL
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
|
||||
@@ -3,26 +3,6 @@
|
||||
|
||||
#include <frameobject.h>
|
||||
|
||||
#define MAX_PYMODULE_ALIAS 64
|
||||
#define MAX_PYARGV 10
|
||||
|
||||
#define LONG_ARGS_PYTHON_BASE 17000 + ((0 + 1) * 1000)
|
||||
|
||||
#define LONG_ARGS_PYTHONPATH LONG_ARGS_PYTHON_BASE + 1
|
||||
#define LONG_ARGS_PASTE LONG_ARGS_PYTHON_BASE + 2
|
||||
#define LONG_ARGS_PYARGV LONG_ARGS_PYTHON_BASE + 3
|
||||
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
|
||||
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
|
||||
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
|
||||
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
|
||||
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
|
||||
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
|
||||
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
|
||||
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
|
||||
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
|
||||
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
|
||||
#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
|
||||
|
||||
#define PYTHON_APP_TYPE_WSGI 0
|
||||
#define PYTHON_APP_TYPE_WEB3 1
|
||||
#define PYTHON_APP_TYPE_WSGI2 2
|
||||
@@ -118,9 +98,9 @@ struct uwsgi_python {
|
||||
int argc;
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t *py_argv[MAX_PYARGV];
|
||||
wchar_t **py_argv;
|
||||
#else
|
||||
char *py_argv[MAX_PYARGV];
|
||||
char **py_argv;
|
||||
#endif
|
||||
|
||||
PyObject *wsgi_spitout;
|
||||
@@ -131,12 +111,15 @@ struct uwsgi_python {
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
int pyshell_oneshot;
|
||||
|
||||
|
||||
struct uwsgi_string_list *python_path;
|
||||
struct uwsgi_string_list *import_list;
|
||||
struct uwsgi_string_list *shared_import_list;
|
||||
struct uwsgi_string_list *spooler_import_list;
|
||||
struct uwsgi_string_list *post_pymodule_alias;
|
||||
struct uwsgi_string_list *pymodule_alias;
|
||||
|
||||
PyObject *loader_dict;
|
||||
PyObject* (*loaders[LOADER_MAX]) (void *);
|
||||
@@ -144,6 +127,7 @@ struct uwsgi_python {
|
||||
char *wsgi_config;
|
||||
char *file_config;
|
||||
char *paste;
|
||||
int paste_logger;
|
||||
char *eval;
|
||||
|
||||
char *web3;
|
||||
@@ -175,10 +159,7 @@ struct uwsgi_python {
|
||||
PyObject *workers_tuple;
|
||||
PyObject *embedded_dict;
|
||||
PyObject *embedded_args;
|
||||
PyObject *fastfuncslist;
|
||||
|
||||
char *pymodule_alias[MAX_PYMODULE_ALIAS];
|
||||
int pymodule_alias_cnt;
|
||||
|
||||
int pep3333_input;
|
||||
|
||||
@@ -186,6 +167,11 @@ struct uwsgi_python {
|
||||
|
||||
int reload_os_env;
|
||||
|
||||
PyObject *after_req_hook;
|
||||
PyObject *after_req_hook_args;
|
||||
|
||||
char *pyrun;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
|
||||
|
||||
PyTypeObject uwsgi_InputType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"uwsgi._Input", /*tp_name */
|
||||
"uwsgi._Input", /*tp_name */
|
||||
sizeof(uwsgi_Input), /*tp_basicsize */
|
||||
0, /*tp_itemsize */
|
||||
(destructor) uwsgi_Input_free, /*tp_dealloc */
|
||||
@@ -513,6 +513,24 @@ clear2:
|
||||
|
||||
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (up.after_req_hook) {
|
||||
if (uwsgi.harakiri_no_arh) {
|
||||
// leave harakiri mode
|
||||
if (uwsgi.workers[uwsgi.mywid].harakiri > 0)
|
||||
set_harakiri(0);
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
PyObject *arh = python_call(up.after_req_hook, up.after_req_hook_args, 0, NULL);
|
||||
if (!arh) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
Py_DECREF(arh);
|
||||
}
|
||||
PyErr_Clear();
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING] || wsgi_req->log_this) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
@@ -156,18 +156,8 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
|
||||
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
|
||||
if (uwsgi.routing && uwsgi.nroutes > 0) {
|
||||
check_route(uwsgi, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// call
|
||||
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
|
||||
}
|
||||
@@ -243,6 +233,20 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
PyErr_Print();
|
||||
}
|
||||
if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "close")) {
|
||||
PyObject *close_method = PyObject_GetAttrString((PyObject *)wsgi_req->async_result, "close");
|
||||
PyObject *close_method_args = PyTuple_New(0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("calling close() for %.*s %p %p\n", wsgi_req->uri_len, wsgi_req->uri, close_method, close_method_args);
|
||||
#endif
|
||||
PyObject *close_method_output = PyEval_CallObject(close_method, close_method_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(close_method_args);
|
||||
Py_XDECREF(close_method_output);
|
||||
Py_DECREF(close_method);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python24'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python24_plugin')
|
||||
LDFLAGS = os.popen('python2.4-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.4-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python25'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python25_plugin')
|
||||
LDFLAGS = os.popen('python2.5-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.5-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python26'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python26_plugin')
|
||||
LDFLAGS = os.popen('python2.6-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.6-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python27'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python27_plugin')
|
||||
LDFLAGS = os.popen('python2.7-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.7-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python30'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.0-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python30_plugin')
|
||||
LDFLAGS = os.popen('python3.0-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python3.0-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python31'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.1-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python31_plugin')
|
||||
LDFLAGS = os.popen('python3.1-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python3.1-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python32'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python3.2-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python32_plugin')
|
||||
LDFLAGS = os.popen('python3.2-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python3.2-config --libs').read().rstrip().split()
|
||||
@@ -36,7 +36,7 @@ VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
|
||||
|
||||
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return Qtrue;
|
||||
}
|
||||
#endif
|
||||
@@ -838,7 +838,7 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
|
||||
int ret = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
|
||||
int ret = spool_request(uwsgi.spoolers, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
|
||||
|
||||
if (priority) {
|
||||
free(priority);
|
||||
|
||||
+161
-84
@@ -4,20 +4,27 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_rack ur;
|
||||
|
||||
struct option uwsgi_rack_options[] = {
|
||||
struct uwsgi_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},
|
||||
{"rails", required_argument, 0, "load a rails <= 2.x app", uwsgi_opt_set_str, &ur.rails, UWSGI_OPT_POST_BUFFERING},
|
||||
{"rack", required_argument, 0, "load a rack app", uwsgi_opt_set_str, &ur.rack, UWSGI_OPT_POST_BUFFERING},
|
||||
{"ruby-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
|
||||
{"rb-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
{"rb-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
{"ruby-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
{"rbrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
{"rubyrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
{"require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
|
||||
{"gemset", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
|
||||
{"rvm", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
|
||||
|
||||
{"rvm-path", required_argument, 0, "search for rvm in the specifiied directory", uwsgi_opt_add_string_list, &ur.rvm_path, 0},
|
||||
|
||||
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_true, &ur.rb_shell, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0 ,0},
|
||||
|
||||
};
|
||||
|
||||
@@ -61,12 +68,26 @@ VALUE rb_uwsgi_io_init(int argc, VALUE *argv, VALUE self) {
|
||||
|
||||
VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
|
||||
|
||||
size_t i;
|
||||
struct wsgi_request *wsgi_req;
|
||||
VALUE line;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
// return the whole body as string
|
||||
// return a line of body
|
||||
for(i=wsgi_req->buf_pos;i<wsgi_req->post_cl;i++) {
|
||||
if (wsgi_req->post_buffering_buf[i] == '\n') {
|
||||
line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, (i+1)-wsgi_req->buf_pos);
|
||||
wsgi_req->buf_pos = i+1;
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
rb_raise(rb_eRuntimeError, "rack.input::gets is not implemented (req %p)\n", wsgi_req);
|
||||
if (wsgi_req->buf_pos < wsgi_req->post_cl) {
|
||||
line = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, wsgi_req->post_cl-wsgi_req->buf_pos);
|
||||
wsgi_req->buf_pos = wsgi_req->post_cl;
|
||||
return line;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -199,6 +220,99 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_ruby_gem_set_apply(char *gemset) {
|
||||
|
||||
int in_pipe[2];
|
||||
int out_pipe[2];
|
||||
int size;
|
||||
int waitpid_status;
|
||||
int i;
|
||||
|
||||
if (pipe(in_pipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pipe(out_pipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_run_command("bash", in_pipe, out_pipe[1] );
|
||||
|
||||
char *gemset_code = uwsgi_open_and_read(gemset, &size, 0, NULL);
|
||||
|
||||
if (write(in_pipe[1], gemset_code, size) != size ) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
free(gemset_code);
|
||||
|
||||
if (write(in_pipe[1], "printenv\n", 9) != 9 ) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
close(in_pipe[1]);
|
||||
|
||||
size = 0;
|
||||
char *buffer = uwsgi_read_fd(out_pipe[0], &size, 0);
|
||||
|
||||
close(out_pipe[0]);
|
||||
|
||||
char *ptr = buffer;
|
||||
|
||||
for(i=0;i<size;i++) {
|
||||
if (buffer[i] == '\n') {
|
||||
buffer[i] = 0;
|
||||
if (putenv(ptr)) {
|
||||
uwsgi_error("putenv()");
|
||||
}
|
||||
ptr = buffer + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if (waitpid(pid, &waitpid_status, 0) <0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_ruby_gemset(char *gemset) {
|
||||
|
||||
char *home = getenv("HOME");
|
||||
|
||||
if (home) {
|
||||
char *filename = uwsgi_concat3(home, "/.rvm/environments/", gemset);
|
||||
if (uwsgi_file_exists(filename)) {
|
||||
uwsgi_ruby_gem_set_apply(filename);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
|
||||
char *filename = uwsgi_concat2("/usr/local/rvm/environments/", gemset);
|
||||
if (uwsgi_file_exists(filename)) {
|
||||
uwsgi_ruby_gem_set_apply(filename);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
|
||||
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
|
||||
while(rvm_paths) {
|
||||
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
|
||||
if (uwsgi_file_exists(filename)) {
|
||||
uwsgi_ruby_gem_set_apply(filename);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
rvm_paths = rvm_paths->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
@@ -215,6 +329,10 @@ int uwsgi_rack_init(){
|
||||
http_sc->message_size = (int) strlen(http_sc->message);
|
||||
}
|
||||
|
||||
if (ur.gemset) {
|
||||
uwsgi_ruby_gemset(ur.gemset);
|
||||
}
|
||||
|
||||
#ifdef RUBY19
|
||||
ruby_sysinit(&argc, &argv);
|
||||
RUBY_INIT_STACK
|
||||
@@ -233,6 +351,7 @@ int uwsgi_rack_init(){
|
||||
rb_gc_register_address(&ur.signals_protector);
|
||||
rb_gc_register_address(&ur.rpc_protector);
|
||||
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
uwsgi_rack_init_api();
|
||||
#endif
|
||||
@@ -250,6 +369,8 @@ void uwsgi_rack_init_apps(void) {
|
||||
ur.app_id = uwsgi_apps_cnt;
|
||||
struct uwsgi_string_list *usl = ur.rbrequire;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
while(usl) {
|
||||
error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
@@ -364,12 +485,17 @@ 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);
|
||||
struct uwsgi_app *ua = uwsgi_add_app(ur.app_id, 7, (char*)"", 0, NULL, NULL);
|
||||
ua->started_at = now;
|
||||
ua->startup_time = uwsgi_now() - now;
|
||||
|
||||
uwsgi_emulate_cow_for_apps(ur.app_id);
|
||||
|
||||
if (ur.gc_freq <= 1) {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, ur.call);
|
||||
uwsgi_log("RACK app %d loaded in %d seconds at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, (int) ua->startup_time, ur.call);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: %d)\n", ur.app_id, ur.call, ur.gc_freq);
|
||||
uwsgi_log("RACK app %d loaded in %d seconds at %p (GC frequency: %d)\n", ur.app_id, (int) ua->startup_time, ur.call, ur.gc_freq);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -420,9 +546,7 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
size_t len;
|
||||
VALUE hkey, hval;
|
||||
|
||||
|
||||
//uwsgi_log("HEADERS %d\n", TYPE(obj));
|
||||
if (TYPE(obj) == T_ARRAY) {
|
||||
@@ -455,18 +579,16 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
size_t header_value_len = RSTRING_LEN(hval);
|
||||
size_t i,cnt=0;
|
||||
char *this_header = header_value;
|
||||
struct iovec iov[4];
|
||||
|
||||
for(i=0;i<header_value_len;i++) {
|
||||
// multiline header, send it !!!
|
||||
if (header_value[i] == '\n') {
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
iov[0].iov_base = RSTRING_PTR(hkey); iov[0].iov_len = RSTRING_LEN(hkey);
|
||||
iov[1].iov_base = (char *)": "; iov[1].iov_len = 2;
|
||||
iov[2].iov_base = this_header; iov[2].iov_len = cnt;
|
||||
iov[3].iov_base = (char *)"\r\n"; iov[3].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header( wsgi_req, iov, 4);
|
||||
|
||||
//uwsgi_log("(multi) --%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
|
||||
|
||||
@@ -480,14 +602,11 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
}
|
||||
|
||||
if (cnt > 0) {
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
iov[0].iov_base = RSTRING_PTR(hkey); iov[0].iov_len = RSTRING_LEN(hkey);
|
||||
iov[1].iov_base = (char *)": "; iov[1].iov_len = 2;
|
||||
iov[2].iov_base = this_header; iov[2].iov_len = cnt;
|
||||
iov[3].iov_base = (char *)"\r\n"; iov[3].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header( wsgi_req, iov, 4);
|
||||
wsgi_req->header_cnt++;
|
||||
//uwsgi_log("--%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
|
||||
}
|
||||
@@ -719,31 +838,6 @@ void uwsgi_rack_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_rack_manage_options(int i, char *optarg) {
|
||||
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_RAILS:
|
||||
// HACK: can be overridden with --post-buffering
|
||||
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
|
||||
ur.rails = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_RACK:
|
||||
// HACK: can be overridden with --post-buffering
|
||||
if (!uwsgi.post_buffering) uwsgi.post_buffering = 4096;
|
||||
ur.rack = optarg;
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
void uwsgi_rack_suspend(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uwsgi_log("SUSPENDING RUBY\n");
|
||||
@@ -828,22 +922,6 @@ VALUE init_rack_app( VALUE script ) {
|
||||
return RARRAY_PTR(rackup)[0] ;
|
||||
}
|
||||
|
||||
int uwsgi_rack_xml(char *node, char *content) {
|
||||
|
||||
int error;
|
||||
|
||||
if (!strcmp("rack", node)) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(content), &error);
|
||||
if (ur.dispatcher != Qnil) {
|
||||
rb_gc_register_address(&ur.dispatcher);
|
||||
uwsgi_log("Rack application ready\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_rack_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
if (!strcmp(lazy+strlen(lazy)-3, ".ru")) {
|
||||
@@ -859,17 +937,17 @@ int uwsgi_rack_magic(char *mountpoint, char *lazy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
int uwsgi_rack_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
|
||||
if ( !strcmp(what+strlen(what)-3, ".ru") || !strcmp(what+strlen(what)-3, ".rb")) {
|
||||
return = uwsgi_rack_load(mountpoint, what);
|
||||
if (uwsgi_endswith(app, ".ru") || uwsgi_endswith(app, ".rb")) {
|
||||
ur.rack = app;
|
||||
uwsgi_rack_init_apps();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
void uwsgi_rack_hijack(void) {
|
||||
}
|
||||
@@ -1022,7 +1100,7 @@ struct uwsgi_plugin rack_plugin = {
|
||||
.modifier1 = 7,
|
||||
.init = uwsgi_rack_init,
|
||||
.options = uwsgi_rack_options,
|
||||
.manage_opt = uwsgi_rack_manage_options,
|
||||
|
||||
.request = uwsgi_rack_request,
|
||||
.after_request = uwsgi_rack_after_request,
|
||||
|
||||
@@ -1034,8 +1112,7 @@ struct uwsgi_plugin rack_plugin = {
|
||||
.spooler = uwsgi_rack_spooler,
|
||||
|
||||
.init_apps = uwsgi_rack_init_apps,
|
||||
//.mount_app = uwsgi_rack_mount_app,
|
||||
.manage_xml = uwsgi_rack_xml,
|
||||
.mount_app = uwsgi_rack_mount_app,
|
||||
|
||||
.magic = uwsgi_rack_magic,
|
||||
|
||||
|
||||
@@ -2,13 +2,6 @@
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
#define LONG_ARGS_RACK_BASE 17000 + ((7 + 1) * 100)
|
||||
#define LONG_ARGS_RAILS LONG_ARGS_RACK_BASE + 1
|
||||
#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
|
||||
#include <st.h>
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
@@ -72,6 +65,9 @@ struct uwsgi_rack {
|
||||
int unprotected;
|
||||
|
||||
struct uwsgi_string_list *rbrequire;
|
||||
struct uwsgi_string_list *rvm_path;
|
||||
|
||||
char *gemset;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
#ifdef __linux__
|
||||
#include <crypt.h>
|
||||
#else
|
||||
#ifdef UWSGI_THREADING
|
||||
pthread_mutex_t ur_basicauth_crypt_mutex;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this algo is based on nginx one (the fastest i have tested)
|
||||
static char *http_basic_auth_get(char *authorization, uint16_t len) {
|
||||
|
||||
uint16_t i;
|
||||
static uint8_t table64[] = {
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
|
||||
77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
|
||||
77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
|
||||
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
|
||||
77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
|
||||
};
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (authorization[i] == '=')
|
||||
break;
|
||||
|
||||
// check for invalid content
|
||||
if (table64[ (uint8_t) authorization[i] ] == 77) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// check for invalid length
|
||||
if (i % 4 == 1)
|
||||
return NULL;
|
||||
|
||||
uint16_t dst_len = (((len+3)/4) * 3) + 1;
|
||||
char *dst = uwsgi_malloc(dst_len);
|
||||
|
||||
char *ptr = dst;
|
||||
uint8_t *src = (uint8_t *) authorization;
|
||||
while(i > 3) {
|
||||
*ptr++= (char) ( table64[src[0]] << 2 | table64[src[1]] >> 4);
|
||||
*ptr++= (char) ( table64[src[1]] << 4 | table64[src[2]] >> 2);
|
||||
*ptr++= (char) ( table64[src[2]] << 6 | table64[src[3]]);
|
||||
|
||||
src+=4;
|
||||
i-=4;
|
||||
}
|
||||
|
||||
if (i > 1) {
|
||||
*ptr++= (char) ( table64[src[0]] << 2 | table64[src[1]] >> 4);
|
||||
}
|
||||
|
||||
if (i > 2) {
|
||||
*ptr++= (char) ( table64[src[1]] << 4 | table64[src[2]] >> 2);
|
||||
}
|
||||
|
||||
*ptr++= 0;
|
||||
|
||||
return dst;
|
||||
|
||||
}
|
||||
|
||||
static uint16_t htpasswd_check(char *filename, char *auth) {
|
||||
|
||||
char line[1024];
|
||||
|
||||
char *colon = strchr(auth, ':');
|
||||
if (!colon) return 0;
|
||||
|
||||
FILE *htpasswd = fopen(filename, "r");
|
||||
if (!htpasswd) {
|
||||
return 0;
|
||||
}
|
||||
while(fgets(line, 1024, htpasswd)) {
|
||||
char *colon2 = strchr(line, ':');
|
||||
if (!colon2) break;
|
||||
|
||||
char *cpwd = colon2+1;
|
||||
size_t clen = strlen(cpwd);
|
||||
if (clen < 13) break;
|
||||
|
||||
if (clen > 13) cpwd[13] = 0;
|
||||
|
||||
#ifdef __linux__
|
||||
struct crypt_data cd;
|
||||
cd.initialized = 0;
|
||||
// we do as nginx here
|
||||
cd.current_salt[0] = ~cpwd[0];
|
||||
char *crypted = crypt_r( colon+1, cpwd, &cd);
|
||||
#else
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&ur_basicauth_crypt_mutex);
|
||||
char *crypted = crypt( colon+1, cpwd);
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&ur_basicauth_crypt_mutex);
|
||||
#endif
|
||||
if (!crypted) continue;
|
||||
|
||||
if (!strcmp( crypted, cpwd )) {
|
||||
if (!uwsgi_strncmp(auth, colon-auth, line, colon2-line)) {
|
||||
fclose(htpasswd);
|
||||
return colon-auth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(htpasswd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct iovec iov[4];
|
||||
|
||||
if (wsgi_req->protocol_len > 0) {
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = "HTTP/1.0";
|
||||
iov[0].iov_len = 8;
|
||||
}
|
||||
|
||||
// chec for "Basic =" string at least
|
||||
if (wsgi_req->authorization_len > 7 && ur->data2_len > 0) {
|
||||
if (strncmp(wsgi_req->authorization, "Basic ", 6))
|
||||
goto forbidden;
|
||||
|
||||
char *auth = http_basic_auth_get(wsgi_req->authorization+6, wsgi_req->authorization_len-6);
|
||||
if (auth) {
|
||||
if (!ur->custom) {
|
||||
// check htpasswd-like file
|
||||
uint16_t ulen = htpasswd_check(ur->data2, auth);
|
||||
if (ulen > 0) {
|
||||
wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ulen);
|
||||
if (wsgi_req->remote_user)
|
||||
wsgi_req->remote_user_len = ulen;
|
||||
free(auth);
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!strcmp(auth, ur->data2)) {
|
||||
wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ur->custom);
|
||||
if (wsgi_req->remote_user)
|
||||
wsgi_req->remote_user_len = ur->custom;
|
||||
free(auth);
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
}
|
||||
free(auth);
|
||||
if (ur->is_last)
|
||||
goto forbidden;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
}
|
||||
|
||||
forbidden:
|
||||
iov[1].iov_base = " 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"";
|
||||
iov[1].iov_len = 60 ;
|
||||
|
||||
iov[2].iov_base = ur->data;
|
||||
iov[2].iov_len = ur->data_len;
|
||||
|
||||
iov[3].iov_base = "\"\r\n\r\n";
|
||||
iov[3].iov_len = 5;
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req,"Unauthorized", 12);
|
||||
|
||||
wsgi_req->status = 401;
|
||||
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
#ifndef __linux__
|
||||
void router_basicauth_init_lock() {
|
||||
pthread_mutex_init(&ur_basicauth_crypt_mutex, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_router_basicauth(struct uwsgi_route *ur, char *args) {
|
||||
|
||||
ur->func = uwsgi_routing_func_basicauth;
|
||||
|
||||
char *comma = strchr(args, ',');
|
||||
if (!comma) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*comma = 0;
|
||||
|
||||
char *colon = strchr(comma+1, ':');
|
||||
// is an htpasswd-like file ?
|
||||
if (!colon) {
|
||||
ur->custom = 0;
|
||||
}
|
||||
else {
|
||||
ur->custom = colon-(comma+1);
|
||||
}
|
||||
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
|
||||
ur->data2 = comma+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void router_basicauth_register(void) {
|
||||
|
||||
uwsgi_register_router("basicauth", uwsgi_router_basicauth);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_basicauth_plugin = {
|
||||
|
||||
.name = "router_redirect",
|
||||
.on_load = router_basicauth_register,
|
||||
#ifndef __linux__
|
||||
.enable_threads = router_basicauth_init_lock,
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
struct uwsgi_plugin router_basicauth_plugin = {
|
||||
.name = "router_basicauth",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
NAME='router_basicauth'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
# osx and openbsd do not need libcrypt
|
||||
if os.uname()[0] not in ('Darwin', 'OpenBSD'):
|
||||
LIBS.append('-lcrypt')
|
||||
|
||||
GCC_LIST = ['router_basicauth']
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_routing_func_redirect(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct iovec iov[4];
|
||||
|
||||
if (wsgi_req->protocol_len > 0) {
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = "HTTP/1.0";
|
||||
iov[0].iov_len = 8;
|
||||
}
|
||||
|
||||
iov[1].iov_base = " 302 Found\r\nLocation: ";
|
||||
iov[1].iov_len = 22;
|
||||
|
||||
iov[2].iov_base = uwsgi_regexp_apply_ovec(wsgi_req->path_info, wsgi_req->path_info_len, ur->data, ur->data_len, ur->ovector, ur->ovn);
|
||||
iov[2].iov_len = strlen(iov[2].iov_base);
|
||||
|
||||
iov[3].iov_base = "\r\n\r\n";
|
||||
iov[3].iov_len = 4;
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Moved", 5);
|
||||
wsgi_req->status = 302;
|
||||
|
||||
free(iov[2].iov_base);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_router_redirect(struct uwsgi_route *ur, char *args) {
|
||||
|
||||
ur->func = uwsgi_routing_func_redirect;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void router_redirect_register(void) {
|
||||
|
||||
uwsgi_register_router("redirect", uwsgi_router_redirect);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_redirect_plugin = {
|
||||
|
||||
.name = "router_redirect",
|
||||
.on_load = router_redirect_register,
|
||||
};
|
||||
#else
|
||||
struct uwsgi_plugin router_redirect_plugin = {
|
||||
.name = "router_redirect",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='router_redirect'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_redirect']
|
||||
@@ -0,0 +1,163 @@
|
||||
#include "../../uwsgi.h"
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_routing_func_uwsgi_simple(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) ur->data;
|
||||
|
||||
wsgi_req->uh.modifier1 = uh->modifier1;
|
||||
wsgi_req->uh.modifier2 = uh->modifier2;
|
||||
|
||||
// set appid
|
||||
if (ur->data2_len > 0) {
|
||||
wsgi_req->appid = ur->data2;
|
||||
wsgi_req->appid_len = ur->data2_len;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ur->data2, ur->data2_len);
|
||||
if (ptr) {
|
||||
// fill iovec
|
||||
if (wsgi_req->var_cnt + 2 < uwsgi.vec_size - (4 + 1)) {
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr - (2 + 11);
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11;
|
||||
wsgi_req->var_cnt++;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = ur->data2_len;
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
char buf[8192];
|
||||
ssize_t len;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) ur->data;
|
||||
char *addr = ur->data + sizeof(struct uwsgi_header);
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->status = -17;
|
||||
|
||||
// append appid
|
||||
if (ur->data2_len > 0) {
|
||||
uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, ur->data2, ur->data2_len);
|
||||
}
|
||||
|
||||
int uwsgi_fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (uwsgi_fd < 0) {
|
||||
uwsgi_log("unable to connect to host %s\n", addr);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
if (uwsgi_send_message(uwsgi_fd, uh->modifier1, uh->modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, wsgi_req->poll.fd, wsgi_req->post_cl, 0) < 0) {
|
||||
uwsgi_log("unable to send uwsgi request to host %s", addr);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = uwsgi_waitfd(uwsgi_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret > 0) {
|
||||
len = read(uwsgi_fd, buf, 8192);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
else if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
break;
|
||||
}
|
||||
|
||||
if (write(wsgi_req->poll.fd, buf, len) != len) {
|
||||
uwsgi_error("write()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("timeout !!!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close(uwsgi_fd);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_router_uwsgi(struct uwsgi_route *ur, char *args) {
|
||||
|
||||
// check for commas
|
||||
char *comma1 = strchr(args, ',');
|
||||
if (!comma1) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *comma2 = strchr(comma1+1, ',');
|
||||
if (!comma2) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *comma3 = strchr(comma2+1, ',');
|
||||
if (comma3) {
|
||||
*comma3 = 0;
|
||||
}
|
||||
|
||||
*comma1 = 0;
|
||||
*comma2 = 0;
|
||||
|
||||
// simple modifier remapper
|
||||
if (*args == 0) {
|
||||
struct uwsgi_header *uh = uwsgi_calloc(sizeof(struct uwsgi_header));
|
||||
ur->func = uwsgi_routing_func_uwsgi_simple;
|
||||
ur->data = (void *) uh;
|
||||
|
||||
uh->modifier1 = atoi(comma1+1);
|
||||
uh->modifier2 = atoi(comma2+1);
|
||||
|
||||
if (comma3) {
|
||||
ur->data2 = comma3+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
struct uwsgi_header *uh = uwsgi_calloc(sizeof(struct uwsgi_header) + strlen(args) + 1);
|
||||
ur->func = uwsgi_routing_func_uwsgi_remote;
|
||||
ur->data = (void *) uh;
|
||||
|
||||
uh->modifier1 = atoi(comma1+1);
|
||||
uh->modifier2 = atoi(comma2+1);
|
||||
|
||||
if (comma3) {
|
||||
ur->data2 = comma3+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
}
|
||||
|
||||
void *ptr = (void *) uh;
|
||||
strcpy(ptr+sizeof(struct uwsgi_header), args);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void router_uwsgi_register(void) {
|
||||
|
||||
uwsgi_register_router("uwsgi", uwsgi_router_uwsgi);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_uwsgi_plugin = {
|
||||
.name = "router_uwsgi",
|
||||
.on_load = router_uwsgi_register,
|
||||
};
|
||||
#else
|
||||
struct uwsgi_plugin router_uwsgi_plugin = {
|
||||
.name = "router_uwsgi",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='router_uwsgi'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_uwsgi']
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
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;
|
||||
int (*create)(int, char **);
|
||||
@@ -18,11 +13,11 @@ struct uwsgi_rrdtool {
|
||||
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},
|
||||
struct uwsgi_option rrdtool_options[] = {
|
||||
{"rrdtool", required_argument, 0, "collect requests data in the specified rrd file", uwsgi_opt_add_string_list, &u_rrd.rrd, UWSGI_OPT_MASTER},
|
||||
{"rrdtool-freq", required_argument, 0, "set collect frequency", uwsgi_opt_set_int, &u_rrd.freq, 0},
|
||||
{"rrdtool-max-ds", required_argument, 0, "set maximum number of data sources", uwsgi_opt_set_int, &u_rrd.max_ds, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
@@ -51,24 +46,6 @@ int rrdtool_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rrdtool_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case RRDTOOL_OPT_RRDTOOL:
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi_string_new_list(&u_rrd.rrd, optarg);
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
void rrdtool_post_init() {
|
||||
|
||||
struct uwsgi_string_list *usl = u_rrd.rrd;
|
||||
@@ -117,11 +94,12 @@ void rrdtool_post_init() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
usl->value = realpath(usl->value, NULL);
|
||||
if (!usl->value) {
|
||||
char *new_usl_value = uwsgi_malloc(PATH_MAX+1);
|
||||
if (!realpath(usl->value, new_usl_value)) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
usl->value = new_usl_value;
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -187,7 +165,6 @@ void rrdtool_master_cycle() {
|
||||
struct uwsgi_plugin rrdtool_plugin = {
|
||||
|
||||
.options = rrdtool_options,
|
||||
.manage_opt = rrdtool_opt,
|
||||
|
||||
.master_cycle = rrdtool_master_cycle,
|
||||
|
||||
|
||||
@@ -7,14 +7,15 @@ int uwsgi_request_signal(struct wsgi_request *wsgi_req) {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t ret_status = 1;
|
||||
struct uwsgi_header uh;
|
||||
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);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = ret_status;
|
||||
len = write(wsgi_req->poll.fd, &uh, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
this plugin, allows remote spooling of jobs
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
char spool_filename[1024];
|
||||
struct uwsgi_header uh;
|
||||
|
||||
// get the spooler from the modifier2
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
if (uspool == NULL) {
|
||||
uwsgi_log("the spooler is inactive !!!...skip\n");
|
||||
uwsgi_send_empty_pkt(wsgi_req->poll.fd, NULL, 255, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize, NULL, 0, NULL, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (i > 0) {
|
||||
uh.modifier2 = 1;
|
||||
if (write(wsgi_req->poll.fd, &uh, 4) != 4) {
|
||||
uwsgi_log("disconnected client, remove spool file.\n");
|
||||
/* client disconnect, remove spool file */
|
||||
if (unlink(spool_filename)) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_log("something horrible happened !!! check your spooler ASAP !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* announce a failed spool request */
|
||||
uh.modifier2 = 0;
|
||||
i = write(wsgi_req->poll.fd, &uh, 4);
|
||||
if (i != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin spooler_plugin = {
|
||||
|
||||
.name = "spooler",
|
||||
.modifier1 = 17,
|
||||
|
||||
.request = uwsgi_request_spooler,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='spooler'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['spooler_plugin']
|
||||
@@ -9,8 +9,8 @@ struct ustackless {
|
||||
PyTaskletObject **sl;
|
||||
} usl;
|
||||
|
||||
struct option stackless_options[] = {
|
||||
{"stackless", no_argument, &usl.enabled, 1},
|
||||
struct uwsgi_option stackless_options[] = {
|
||||
{"stackless", no_argument, 0, "use stackless as suspend engine", uwsgi_opt_true, &usl.enabled, 0},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
+4
-16
@@ -21,10 +21,10 @@ struct uwsgi_ugreen {
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct option ugreen_options[] = {
|
||||
{"ugreen", no_argument, &ug.ugreen, 1},
|
||||
{"ugreen-stacksize", required_argument, 0, LONG_ARGS_UGREEN_PAGES},
|
||||
{ 0, 0, 0, 0 }
|
||||
struct uwsgi_option ugreen_options[] = {
|
||||
{"ugreen", no_argument, 0, "enable ugreen coroutine subsystem", uwsgi_opt_true, &ug.ugreen, 1},
|
||||
{"ugreen-stacksize", required_argument, 0, "set ugreen stack size in pages", uwsgi_opt_set_int, &ug.stackpages, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void u_green_request() {
|
||||
@@ -126,21 +126,9 @@ int u_green_init() {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_ugreen_manage_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_UGREEN_PAGES:
|
||||
ug.stackpages = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin ugreen_plugin = {
|
||||
|
||||
.name = "ugreen",
|
||||
.init = u_green_init,
|
||||
.options = ugreen_options,
|
||||
.manage_opt = uwsgi_ugreen_manage_opt,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user