mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f387d27582 | ||
|
|
5d8e5d943f | ||
|
|
4046f76cb2 | ||
|
|
8baeb0af2f | ||
|
|
63e0105a0f | ||
|
|
70daa57caf | ||
|
|
db0f7951a9 | ||
|
|
45a7a3066d | ||
|
|
c73a6723d7 | ||
|
|
fb55f57531 | ||
|
|
8cf4d5802a | ||
|
|
e3c042e567 | ||
|
|
5435f8927c | ||
|
|
e1e65c46ac | ||
|
|
e1f3665a8e | ||
|
|
ef09a010cf | ||
|
|
3f5d79c755 | ||
|
|
3b5468f39f | ||
|
|
5598c7cc22 | ||
|
|
d6fdb812a2 | ||
|
|
e6d5f6c612 | ||
|
|
8f10daa2bf | ||
|
|
f027153452 | ||
|
|
0ebda93a50 | ||
|
|
dc4e8950d2 | ||
|
|
0f5336028f | ||
|
|
e02341bffe | ||
|
|
ac92ff4079 | ||
|
|
a5da77bc54 | ||
|
|
0441e88b82 | ||
|
|
815f4abec0 | ||
|
|
4f9e2ff3f6 | ||
|
|
ce8dd001bf | ||
|
|
d4e90f5215 | ||
|
|
da13562890 | ||
|
|
d320075ab0 | ||
|
|
4061826da4 | ||
|
|
2854321891 | ||
|
|
c4181cdc55 | ||
|
|
327582b695 | ||
|
|
f56b9be4c5 | ||
|
|
28ccace24f | ||
|
|
13f82176e3 | ||
|
|
be4d324f6b | ||
|
|
36486caabb | ||
|
|
b3af255727 | ||
|
|
a56f726f7d | ||
|
|
24d6470f38 | ||
|
|
7e079e4c40 | ||
|
|
0d9bc03c53 | ||
|
|
7598666768 | ||
|
|
cd6f027705 | ||
|
|
0803a7f0b0 | ||
|
|
0eb956db4a | ||
|
|
76c6ae6d16 | ||
|
|
40054e3494 | ||
|
|
8927dfd538 | ||
|
|
68f734fcad | ||
|
|
af4c7f74d5 | ||
|
|
4581d1e7ce | ||
|
|
d465f61506 | ||
|
|
5cae9b9ba4 | ||
|
|
428a2d9366 | ||
|
|
1c00b54b06 | ||
|
|
6228fb91da | ||
|
|
307cf3a0ef | ||
|
|
f723a804c0 | ||
|
|
24ac19e2d6 | ||
|
|
38147d50ff | ||
|
|
9f7db10582 | ||
|
|
ed35a50e6c | ||
|
|
fae08f49cf | ||
|
|
35f5b5b2eb | ||
|
|
b785c8fccf | ||
|
|
597c3cd7f1 | ||
|
|
bbbe01ef4b | ||
|
|
ea1e1cb65f | ||
|
|
a1d31ae954 | ||
|
|
fa0ed9489a | ||
|
|
7bb7b351e0 | ||
|
|
cb45f207a6 | ||
|
|
82ffb60bdd | ||
|
|
ec38ce9a26 | ||
|
|
8279926bab | ||
|
|
ac17b0910e | ||
|
|
aae3e7ff17 | ||
|
|
4cfff98cd1 | ||
|
|
19ee50949c | ||
|
|
ec27d624c3 | ||
|
|
0dc8803ff8 | ||
|
|
e8ea1a55f9 | ||
|
|
a0cb71ca78 | ||
|
|
5c5aef3827 | ||
|
|
737a7f4d51 | ||
|
|
c3ee774d56 | ||
|
|
2d5adacc65 | ||
|
|
b7a8cc0297 | ||
|
|
317b0f79a8 | ||
|
|
4644578276 | ||
|
|
f1d450c12f | ||
|
|
6624f75ec7 | ||
|
|
8941505ea0 | ||
|
|
18b177db25 | ||
|
|
27421f3642 | ||
|
|
30f9479e85 | ||
|
|
a9f7631ab4 | ||
|
|
cb8519510f | ||
|
|
f7881bfb78 | ||
|
|
4cf4c75d5d | ||
|
|
91bcbc77b3 | ||
|
|
b1db4d35c3 | ||
|
|
060462b849 | ||
|
|
0e08c0211c | ||
|
|
e69cc2bcd5 | ||
|
|
996af7d46c | ||
|
|
e8e66f15da | ||
|
|
cd09b4a55d | ||
|
|
f4a1d76396 | ||
|
|
ab8cc168e5 | ||
|
|
5e43ef6fae | ||
|
|
caa3614f78 | ||
|
|
a81ca89ae9 | ||
|
|
5861705cd6 | ||
|
|
4e68dacad3 | ||
|
|
4f8f15a3b6 | ||
|
|
aa6b86fbdf | ||
|
|
7a18ff48ba | ||
|
|
e354de9f5e | ||
|
|
10073bc4ae | ||
|
|
6fd051b248 | ||
|
|
1cf034881e | ||
|
|
1393281c74 | ||
|
|
edf95a4b0a | ||
|
|
8887f83f7f | ||
|
|
7513d80440 | ||
|
|
67289b7cf1 | ||
|
|
a88f478fac | ||
|
|
d385661a93 | ||
|
|
e8895ba773 | ||
|
|
5a23a8d457 | ||
|
|
e01a3d8bd2 | ||
|
|
b270bd24d7 | ||
|
|
ab989ebf16 | ||
|
|
7c31b6657f | ||
|
|
ba7d322aaf | ||
|
|
537187b7f8 | ||
|
|
d22a7c7223 | ||
|
|
c9f986fa59 | ||
|
|
d7388ca5e7 | ||
|
|
df5ad62ebf | ||
|
|
41dab14020 | ||
|
|
744e166e9d | ||
|
|
5a3b93f763 | ||
|
|
656de924eb | ||
|
|
703444dd40 | ||
|
|
ff8ca18e8f | ||
|
|
1f90be1ae1 | ||
|
|
ee95c2eb0b | ||
|
|
6606f3f0dc | ||
|
|
bcd97f7247 | ||
|
|
271e7f8f4c | ||
|
|
e78d8594a8 | ||
|
|
659360b366 | ||
|
|
6c1c86ea79 | ||
|
|
5da36b7199 | ||
|
|
294452eef7 | ||
|
|
3ac0e28d9c | ||
|
|
ce22b69a2f | ||
|
|
8b31a998ed | ||
|
|
dad97bc104 | ||
|
|
e20e43eee0 | ||
|
|
aafd4e757d | ||
|
|
575fc26bd7 | ||
|
|
5743eb2575 | ||
|
|
31972ded93 | ||
|
|
28321a0f94 | ||
|
|
406dfbc770 | ||
|
|
c59595cefc | ||
|
|
7108ee1ba0 | ||
|
|
cf8e68f7a0 | ||
|
|
a9510c2209 | ||
|
|
b2be5943a8 | ||
|
|
8f19fe292e | ||
|
|
d3e7668d0a | ||
|
|
88e67a74e5 | ||
|
|
7fecda1a23 | ||
|
|
56b6fa88f9 | ||
|
|
e847cfe4bc | ||
|
|
1a854ae3ba | ||
|
|
c75180bf95 | ||
|
|
d496450b84 | ||
|
|
d2636ed133 | ||
|
|
59de0c2085 | ||
|
|
4b7df29bd1 | ||
|
|
b099ba6a29 | ||
|
|
164069e194 | ||
|
|
b3e4ff8613 | ||
|
|
3eb5ec3543 | ||
|
|
c3c698a615 | ||
|
|
ac6d2f3e83 | ||
|
|
d1f1b8a43a | ||
|
|
85586a621c | ||
|
|
1a384a334f | ||
|
|
8901afded5 | ||
|
|
ab12703a11 | ||
|
|
9992b4c964 | ||
|
|
9a2dbd08cd | ||
|
|
5f92a00b71 | ||
|
|
7bd9d51217 | ||
|
|
80c649aa40 | ||
|
|
6c8fe2cc53 | ||
|
|
dcc7167d75 | ||
|
|
e3a52e4039 | ||
|
|
498f6162f7 | ||
|
|
33d85d3670 | ||
|
|
afbf5b9633 | ||
|
|
a8505be6c0 | ||
|
|
4a07632569 | ||
|
|
d4f0589c39 | ||
|
|
a9989d46fc | ||
|
|
99cf598c0c | ||
|
|
a6af22b8f0 | ||
|
|
0961d61a88 | ||
|
|
7b76a2d749 | ||
|
|
b516f1d3ec | ||
|
|
8fdef7a1f9 | ||
|
|
10258db4ae | ||
|
|
621c9523cf | ||
|
|
c415adab28 | ||
|
|
7fef1048b3 | ||
|
|
1e7aaeeeed | ||
|
|
c5b4564001 | ||
|
|
a9127c8d79 | ||
|
|
a0f7a5c70f | ||
|
|
ecf3cae35b | ||
|
|
d553bc8014 | ||
|
|
a1553d3632 | ||
|
|
bb42ae1b4a | ||
|
|
61ac2efe0e | ||
|
|
1c0a3ec413 | ||
|
|
8b7e93385b | ||
|
|
c742624054 | ||
|
|
8011f0615d | ||
|
|
8096b2198f | ||
|
|
3556bd5283 | ||
|
|
26710694af | ||
|
|
0f397eeb55 | ||
|
|
bf929398a9 | ||
|
|
4f8a0f753e | ||
|
|
7db5da9566 | ||
|
|
4d1389805c | ||
|
|
ee87e2b946 | ||
|
|
6356d78768 | ||
|
|
afdf7e740e | ||
|
|
51ce3ddf78 | ||
|
|
192186056e | ||
|
|
336a7febd7 | ||
|
|
63e73d1b73 | ||
|
|
a02ab9a723 | ||
|
|
95f15ab9dd | ||
|
|
5d0ea0066a | ||
|
|
9ff6b2da9b | ||
|
|
6ac7e27847 | ||
|
|
4ed1c5e747 | ||
|
|
bae3bc096f | ||
|
|
9d73683de2 | ||
|
|
f5fec0ab71 | ||
|
|
9909ab10c4 | ||
|
|
65cff01fee | ||
|
|
10190a3012 | ||
|
|
79ab696f4e | ||
|
|
cb603682e4 | ||
|
|
c986a06bf7 | ||
|
|
e2843a6cee | ||
|
|
ea1f239807 | ||
|
|
8d7618146a | ||
|
|
eb9e419bb0 | ||
|
|
f98f71ac26 | ||
|
|
03baaaebcb | ||
|
|
cbca954508 | ||
|
|
22ba6cc406 | ||
|
|
6bd172acb4 | ||
|
|
818ba4416f | ||
|
|
adff12841c | ||
|
|
480c306591 | ||
|
|
cbd1481cb7 | ||
|
|
d1c1871222 | ||
|
|
15a94b8fb0 | ||
|
|
66be54e6a7 | ||
|
|
62c85cc2eb | ||
|
|
1ae05a9ebc | ||
|
|
3457c70f30 | ||
|
|
c1ec9126da | ||
|
|
398da2fac7 | ||
|
|
47f33d6346 | ||
|
|
2cad82d537 | ||
|
|
8d06d78537 | ||
|
|
b61be000de | ||
|
|
9ca6de6e7a | ||
|
|
5c03c25e96 | ||
|
|
23843163ad | ||
|
|
8b07fbbedc | ||
|
|
5bf55220d4 | ||
|
|
0e1de3d6e8 | ||
|
|
3a7ba3675b | ||
|
|
5c0deb5bdb | ||
|
|
50dcbc2b01 | ||
|
|
90d72f7843 | ||
|
|
90ee59c70d | ||
|
|
59eda11c1b | ||
|
|
78684a424f | ||
|
|
4a936dda6e | ||
|
|
094d4b99a4 | ||
|
|
382268308e | ||
|
|
97315d27b9 | ||
|
|
26ae573b72 | ||
|
|
803c44d783 | ||
|
|
90f3f1037a | ||
|
|
ce39a751d9 | ||
|
|
ceebf7d32d | ||
|
|
8da59bf0ac | ||
|
|
d25979502a | ||
|
|
549bc3bf9f | ||
|
|
22b2f325e0 | ||
|
|
6615d1b90c | ||
|
|
8f045c4254 | ||
|
|
a4434349e5 | ||
|
|
01272be25f | ||
|
|
be0beed403 | ||
|
|
453d2abed5 | ||
|
|
57e9ccbef0 | ||
|
|
989124772b | ||
|
|
72400e4b91 | ||
|
|
900cba29a7 | ||
|
|
f177a65c1e | ||
|
|
b6baf9016d | ||
|
|
86ac6e8044 | ||
|
|
66d8fb95db | ||
|
|
22da8d9ba2 | ||
|
|
819e9c1b16 | ||
|
|
dd4b2e8bc2 | ||
|
|
e2f7ac2017 | ||
|
|
31b5cf6926 | ||
|
|
25fe3035c2 | ||
|
|
0cf56823cd | ||
|
|
c2f36968c3 | ||
|
|
a508c7f53e | ||
|
|
48de68031d | ||
|
|
81ef85af82 | ||
|
|
16b65d7dbe | ||
|
|
5a98e6511b | ||
|
|
2418f08e22 | ||
|
|
80a821bc20 | ||
|
|
378f78bd87 | ||
|
|
f010591e19 | ||
|
|
5274abdcca | ||
|
|
48f9e8c5c8 | ||
|
|
5c02117fde | ||
|
|
bc56a188f8 | ||
|
|
b6df1b22ab | ||
|
|
0fbf2dd5bb | ||
|
|
38c126d11a | ||
|
|
7dff602e5e | ||
|
|
e401f32815 | ||
|
|
12e94b70a7 | ||
|
|
884de3959c | ||
|
|
fe12325e50 | ||
|
|
bea86f3f79 | ||
|
|
7a5f3667da | ||
|
|
0813788c98 | ||
|
|
b1ca73e7f0 | ||
|
|
ebf9e9b1a3 | ||
|
|
b0abab7a1d | ||
|
|
995bb493df | ||
|
|
1b2375fc84 | ||
|
|
b7315bcb5a | ||
|
|
2c9ebdaa69 | ||
|
|
fbd9e5b4d7 | ||
|
|
b9a3425b6d | ||
|
|
d4742c611b | ||
|
|
c645a590aa | ||
|
|
275a7fe63f | ||
|
|
0ff16d8312 | ||
|
|
1cb31d6c7e | ||
|
|
8a6eb553df | ||
|
|
946af8b9ee | ||
|
|
098a1f647e | ||
|
|
c9681dc430 | ||
|
|
ff0b8b2d53 | ||
|
|
75f520d43a | ||
|
|
65209748ba | ||
|
|
cd604ef07b | ||
|
|
51da8bc531 | ||
|
|
2374ba12bd | ||
|
|
0a75aaec25 | ||
|
|
a8c286ae83 | ||
|
|
7c4caef5e7 |
@@ -2,8 +2,12 @@
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
*~
|
||||
*.so
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
|
||||
/t/ring/target
|
||||
|
||||
core/dot_h.c
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
|
||||
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
|
||||
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
|
||||
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
|
||||
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
|
||||
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
|
||||
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
|
||||
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
|
||||
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
|
||||
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
|
||||
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
|
||||
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
|
||||
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
|
||||
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
|
||||
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
|
||||
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
|
||||
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
|
||||
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
|
||||
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
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
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
|
||||
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
|
||||
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
|
||||
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
|
||||
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
|
||||
@@ -22,3 +22,6 @@ Aarni Koskela
|
||||
C Anthony Risinger
|
||||
Stephen Pierce
|
||||
Mingli Yuan
|
||||
Natanael Copa
|
||||
Roberto Leandrini
|
||||
Ryan Petrello
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
matheval = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
@@ -16,7 +17,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi,coroae
|
||||
inherit = base
|
||||
@@ -1,3 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
matheval = false
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack,rbthreads,fiber
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = jvm,servlet
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = v8
|
||||
inherit = base
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Greenlets support
|
||||
|
||||
simply --pypy-exec this file to enable PyPy's greenlet mode
|
||||
|
||||
Example:
|
||||
|
||||
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
|
||||
"""
|
||||
|
||||
import greenlet
|
||||
|
||||
uwsgi_pypy_greenlets = {}
|
||||
|
||||
def uwsgi_pypy_greenlet_wrapper():
|
||||
lib.async_schedule_to_req_green()
|
||||
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_greenlet_schedule():
|
||||
id = lib.uwsgi.wsgi_req.async_id
|
||||
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
|
||||
|
||||
# generate a new greenlet
|
||||
if not lib.uwsgi.wsgi_req.suspended:
|
||||
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
|
||||
lib.uwsgi.wsgi_req.suspended = 1
|
||||
|
||||
# this is called in the main stack
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
|
||||
|
||||
# let's switch
|
||||
uwsgi_pypy_greenlets[id].switch()
|
||||
|
||||
# back to the main stack
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(ffi.NULL)
|
||||
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_greenlet_switch(wsgi_req):
|
||||
id = wsgi_req.async_id
|
||||
modifier1 = wsgi_req.uh.modifier1;
|
||||
|
||||
# this is called in the current greenlet
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(wsgi_req)
|
||||
|
||||
uwsgi_pypy_main_greenlet.switch()
|
||||
|
||||
# back to the greenlet
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(wsgi_req)
|
||||
|
||||
# update current running greenlet
|
||||
lib.uwsgi.wsgi_req = wsgi_req
|
||||
|
||||
if lib.uwsgi.async <= 1:
|
||||
raise Exception("pypy greenlets require async mode !!!")
|
||||
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
|
||||
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
|
||||
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
|
||||
@@ -0,0 +1,15 @@
|
||||
# uWSGI - Emperor
|
||||
#
|
||||
|
||||
description "uWSGI Emperor"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
env VASSALS=/etc/uwsgi
|
||||
|
||||
exec $BINPATH --emperor $VASSALS --logto $LOGTO
|
||||
@@ -11,7 +11,6 @@ respawn
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
# --die-on-term could be a good idea
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
# --die-on-term is upstart friendly
|
||||
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
|
||||
|
||||
+10
-1
@@ -206,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
|
||||
static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -222,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
|
||||
}
|
||||
@@ -265,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
static int async_wait_fd_write(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_write(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -359,7 +368,7 @@ void async_loop() {
|
||||
uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
if (!uwsgi.schedule_to_main) {
|
||||
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
|
||||
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
|
||||
#ifdef UWSGI_DEBUG_BUFFER
|
||||
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
|
||||
#endif
|
||||
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
|
||||
|
||||
if (len) {
|
||||
@@ -270,6 +273,13 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
|
||||
|
||||
|
||||
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
|
||||
#ifdef UWSGI_DEBUG_BUFFER
|
||||
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
|
||||
if (ub->freed) {
|
||||
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
|
||||
}
|
||||
ub->freed = 1;
|
||||
#endif
|
||||
if (ub->buf)
|
||||
free(ub->buf);
|
||||
free(ub);
|
||||
|
||||
+101
-1
@@ -171,6 +171,42 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
char *value = strchr(key, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("[cache] unable to store item %s\n", usl->value);
|
||||
goto next;
|
||||
}
|
||||
key_len = value - key;
|
||||
value++;
|
||||
uint64_t len = (usl->value + usl->len) - value;
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
|
||||
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
|
||||
@@ -194,9 +230,15 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
|
||||
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
free(value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key);
|
||||
}
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -335,6 +377,8 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
uwsgi_cache_add_items(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
@@ -455,6 +499,27 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get4(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *hits) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
|
||||
if (index) {
|
||||
struct uwsgi_cache_item *uci = cache_item(index);
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return NULL;
|
||||
*valsize = uci->valsize;
|
||||
if (hits)
|
||||
*hits = uci->hits;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
|
||||
|
||||
@@ -1089,7 +1154,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
// defaults
|
||||
uc->blocks = uc->max_items;
|
||||
uc->blocksize = UMAX16;
|
||||
uc->max_item_size = uc->blocksize;
|
||||
uc->keysize = 2048;
|
||||
uc->hashsize = UMAX16;
|
||||
uc->hash = uwsgi_hash_algo_get("djb33x");
|
||||
@@ -1097,6 +1161,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
// customize
|
||||
if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize);
|
||||
if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); }
|
||||
// set the true max size of an item
|
||||
uc->max_item_size = uc->blocksize;
|
||||
|
||||
if (c_blocks) uc->blocks = uwsgi_n64(c_blocks);
|
||||
if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); }
|
||||
if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash);
|
||||
@@ -1854,3 +1921,36 @@ void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *uc, uint64_t *pos, struct uwsgi_cache_item **uci) {
|
||||
|
||||
// security check
|
||||
if (*pos >= uc->hashsize) return NULL;
|
||||
// iterate hashtable
|
||||
uint64_t orig_pos = *pos;
|
||||
for(;*pos<uc->hashsize;(*pos)++) {
|
||||
// get the cache slot
|
||||
uint64_t slot = uc->hashtable[*pos];
|
||||
if (*pos == orig_pos && *uci) {
|
||||
slot = (*uci)->next;
|
||||
}
|
||||
if (slot == 0) continue;
|
||||
|
||||
*uci = cache_item(slot);
|
||||
return *uci;
|
||||
}
|
||||
|
||||
(*pos)++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_cache_rlock(struct uwsgi_cache *uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
}
|
||||
|
||||
void uwsgi_cache_rwunlock(struct uwsgi_cache *uc) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
}
|
||||
|
||||
char *uwsgi_cache_item_key(struct uwsgi_cache_item *uci) {
|
||||
return uci->key;
|
||||
}
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Chunked input implementation
|
||||
|
||||
--chunked-input-limit <bytes> (default 1MB)
|
||||
|
||||
--chunked-input-timeout <s> (default --socket-timeout)
|
||||
|
||||
chunk = uwsgi.chunked_read([timeout])
|
||||
|
||||
timeout = -1 (wait forever)
|
||||
timeout = 0 (default)
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
|
||||
|
||||
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
|
||||
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
int ret = -1;
|
||||
|
||||
for(;;) {
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (nb) return -1;
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
|
||||
size_t i;
|
||||
int found = 0;
|
||||
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
|
||||
if (found) {
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
|
||||
// strtoul will stop at \r
|
||||
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
|
||||
return num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0 -> waiting for \r\n
|
||||
1 -> waiting for whole body
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
|
||||
|
||||
if (!wsgi_req->chunked_input_buf) {
|
||||
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
|
||||
}
|
||||
|
||||
// the whole chunk stream has been consumed
|
||||
if (wsgi_req->chunked_input_complete) {
|
||||
*len = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_decapitate > 0) {
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
|
||||
wsgi_req->chunked_input_decapitate = 0;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
|
||||
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
|
||||
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
|
||||
if (rlen <= 0) return NULL;
|
||||
// update buffer position
|
||||
wsgi_req->chunked_input_buf->pos += rlen;
|
||||
if (wsgi_req->chunked_input_need > 0) {
|
||||
if ((size_t)rlen > wsgi_req->chunked_input_need) {
|
||||
wsgi_req->chunked_input_need = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->chunked_input_need -= rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) continue;
|
||||
|
||||
// ok we have a frame, let's parse it
|
||||
if (wsgi_req->chunked_input_buf->pos > 0) {
|
||||
switch(wsgi_req->chunked_input_parser_status) {
|
||||
case 0:
|
||||
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
|
||||
if (wsgi_req->chunked_input_chunk_len == -2) {
|
||||
wsgi_req->chunked_input_need++;
|
||||
break;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len == 0) {
|
||||
*len = 0;
|
||||
wsgi_req->chunked_input_complete = 1;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
// if here the buffer has been already decapitated
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
wsgi_req->chunked_input_parser_status = 1;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
case 1:
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
|
||||
wsgi_req->chunked_input_parser_status = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int main() {}
|
||||
+447
@@ -31,3 +31,450 @@ struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(
|
||||
|
||||
return uc;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_exists(char *key, char *value) {
|
||||
|
||||
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_for(char *key, char *value) {
|
||||
|
||||
char *p = strtok(uwsgi.logic_opt_data, " ");
|
||||
while (p) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
|
||||
glob_t g;
|
||||
int i;
|
||||
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("uwsgi_logic_opt_for_glob()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int) g.gl_pathc; i++) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
|
||||
}
|
||||
|
||||
globfree(&g);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_opt(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (!strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_env(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = getenv(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = getenv(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (!strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_reload(char *key, char *value) {
|
||||
if (uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
|
||||
if (!uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_file(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_dir(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
|
||||
|
||||
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
|
||||
|
||||
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_count_options(struct uwsgi_option *uopt) {
|
||||
|
||||
struct uwsgi_option *aopt;
|
||||
int count = 0;
|
||||
|
||||
while ((aopt = uopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
count++;
|
||||
uopt++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) {
|
||||
return op;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
|
||||
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
|
||||
|
||||
while (blacklist) {
|
||||
if (!strcmp(key, blacklist->value)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
blacklist = blacklist->next;
|
||||
}
|
||||
|
||||
if (whitelist) {
|
||||
int allowed = 0;
|
||||
while (whitelist) {
|
||||
if (!strcmp(key, whitelist->value)) {
|
||||
allowed = 1;
|
||||
break;
|
||||
}
|
||||
whitelist = whitelist->next;
|
||||
}
|
||||
if (!allowed) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.blacklist_context) {
|
||||
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.whitelist_context) {
|
||||
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.logic_opt_running)
|
||||
goto add;
|
||||
|
||||
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
|
||||
if (uwsgi.logic_opt_data) {
|
||||
free(uwsgi.logic_opt_data);
|
||||
}
|
||||
uwsgi.logic_opt = NULL;
|
||||
uwsgi.logic_opt_arg = NULL;
|
||||
uwsgi.logic_opt_cycles = 0;
|
||||
uwsgi.logic_opt_data = NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.logic_opt) {
|
||||
if (uwsgi.logic_opt_data) {
|
||||
free(uwsgi.logic_opt_data);
|
||||
}
|
||||
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
|
||||
uwsgi.logic_opt_cycles++;
|
||||
uwsgi.logic_opt_running = 1;
|
||||
uwsgi.logic_opt(key, value);
|
||||
uwsgi.logic_opt_running = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
add:
|
||||
|
||||
if (!uwsgi.exported_opts) {
|
||||
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
|
||||
}
|
||||
else {
|
||||
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
|
||||
if (!uwsgi.exported_opts) {
|
||||
uwsgi_error("realloc()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int id = uwsgi.exported_opts_cnt;
|
||||
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
|
||||
uwsgi.exported_opts[id]->key = key;
|
||||
uwsgi.exported_opts[id]->value = value;
|
||||
uwsgi.exported_opts[id]->configured = configured;
|
||||
uwsgi.exported_opts_cnt++;
|
||||
uwsgi.dirty_config = 1;
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
// requires master ?
|
||||
if (op->flags & UWSGI_OPT_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
}
|
||||
// requires log_master ?
|
||||
if (op->flags & UWSGI_OPT_LOG_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.log_master = 1;
|
||||
}
|
||||
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.log_master = 1;
|
||||
uwsgi.req_log_master = 1;
|
||||
}
|
||||
// requires threads ?
|
||||
if (op->flags & UWSGI_OPT_THREADS) {
|
||||
uwsgi.has_threads = 1;
|
||||
}
|
||||
// requires cheaper mode ?
|
||||
if (op->flags & UWSGI_OPT_CHEAPER) {
|
||||
uwsgi.cheaper = 1;
|
||||
}
|
||||
// requires virtualhosting ?
|
||||
if (op->flags & UWSGI_OPT_VHOST) {
|
||||
uwsgi.vhost = 1;
|
||||
}
|
||||
// requires memusage ?
|
||||
if (op->flags & UWSGI_OPT_MEMORY) {
|
||||
uwsgi.force_get_memusage = 1;
|
||||
}
|
||||
// requires auto procname ?
|
||||
if (op->flags & UWSGI_OPT_PROCNAME) {
|
||||
uwsgi.auto_procname = 1;
|
||||
}
|
||||
// requires lazy ?
|
||||
if (op->flags & UWSGI_OPT_LAZY) {
|
||||
uwsgi.lazy = 1;
|
||||
}
|
||||
// requires no_initial ?
|
||||
if (op->flags & UWSGI_OPT_NO_INITIAL) {
|
||||
uwsgi.no_initial_output = 1;
|
||||
}
|
||||
// requires no_server ?
|
||||
if (op->flags & UWSGI_OPT_NO_SERVER) {
|
||||
uwsgi.no_server = 1;
|
||||
}
|
||||
// requires post_buffering ?
|
||||
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
|
||||
if (!uwsgi.post_buffering)
|
||||
uwsgi.post_buffering = 4096;
|
||||
}
|
||||
// requires building mime dict ?
|
||||
if (op->flags & UWSGI_OPT_MIME) {
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
// immediate ?
|
||||
if (op->flags & UWSGI_OPT_IMMEDIATE) {
|
||||
op->func(key, value, op->data);
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", key);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_fallback_config() {
|
||||
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
|
||||
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
|
||||
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
|
||||
char *argv[3];
|
||||
argv[0] = uwsgi.binary_path;
|
||||
argv[1] = uwsgi.fallback_config;
|
||||
argv[2] = NULL;
|
||||
execvp(uwsgi.binary_path, argv);
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
}
|
||||
}
|
||||
|
||||
+160
-12
@@ -27,13 +27,22 @@ struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
|
||||
exit(1);
|
||||
}
|
||||
uc->command = crontab + i;
|
||||
uc->pid = -1;
|
||||
return uc;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
uwsgi_cron_add(value);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(value);
|
||||
uc->unique = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
@@ -45,9 +54,140 @@ void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
uc->unique = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *c_minute = NULL;
|
||||
char *c_hour = NULL;
|
||||
char *c_day = NULL;
|
||||
char *c_month = NULL;
|
||||
char *c_week = NULL;
|
||||
char *c_unique = NULL;
|
||||
char *c_harakiri = NULL;
|
||||
char *c_legion = NULL;
|
||||
|
||||
char *c_command = value;
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (space) {
|
||||
if (uwsgi_str_contains(value, space - value, '=')) {
|
||||
// --cron2 key=val command
|
||||
*space = 0;
|
||||
c_command = space + 1;
|
||||
}
|
||||
|
||||
// no point in parsing key=val list if there is none
|
||||
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
|
||||
"minute", &c_minute,
|
||||
"hour", &c_hour,
|
||||
"day", &c_day,
|
||||
"month", &c_month,
|
||||
"week", &c_week,
|
||||
"unique", &c_unique,
|
||||
"harakiri", &c_harakiri,
|
||||
"legion", &c_legion,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_str_contains(value, strlen(value), '=')) {
|
||||
// --cron2 key=val
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
uc->command = c_command;
|
||||
if (!uc->command) {
|
||||
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// defaults
|
||||
uc->minute = -1;
|
||||
uc->hour = -1;
|
||||
uc->day = -1;
|
||||
uc->month = -1;
|
||||
uc->week = -1;
|
||||
|
||||
uc->unique = 0;
|
||||
uc->mercy = 0;
|
||||
uc->harakiri = 0;
|
||||
uc->pid = -1;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uc->legion = c_legion;
|
||||
#endif
|
||||
|
||||
if (c_minute)
|
||||
uc->minute = atoi(c_minute);
|
||||
|
||||
if (c_hour)
|
||||
uc->hour = atoi(c_hour);
|
||||
|
||||
if (c_day)
|
||||
uc->day = atoi(c_day);
|
||||
|
||||
if (c_month)
|
||||
uc->month = atoi(c_month);
|
||||
|
||||
if (c_week)
|
||||
uc->week = atoi(c_week);
|
||||
|
||||
if (c_unique)
|
||||
uc->unique = atoi(c_unique);
|
||||
|
||||
if (c_harakiri) {
|
||||
if (atoi(c_harakiri)) {
|
||||
// harakiri > 0
|
||||
uc->mercy = atoi(c_harakiri);
|
||||
}
|
||||
else {
|
||||
// harakiri == 0
|
||||
uc->mercy = -1;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.cron_harakiri) {
|
||||
uc->harakiri = uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
@@ -134,15 +274,16 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
#ifdef UWSGI_SSL
|
||||
// check for legion cron
|
||||
if (current_cron->legion) {
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion)) {
|
||||
current_cron = current_cron->next;
|
||||
continue;
|
||||
}
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
|
||||
goto next;
|
||||
}
|
||||
#endif
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
|
||||
// skip unique crons that are still running
|
||||
if (current_cron->unique && current_cron->pid >= 0)
|
||||
goto next;
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
@@ -153,20 +294,27 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
current_cron->func(current_cron, now);
|
||||
}
|
||||
else {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
|
||||
if (pid >= 0) {
|
||||
current_cron->pid = pid;
|
||||
current_cron->started_at = now;
|
||||
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
|
||||
if (current_cron->mercy) {
|
||||
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
|
||||
if (current_cron->mercy > 0)
|
||||
current_cron->harakiri = now + current_cron->mercy;
|
||||
}
|
||||
else if (uwsgi.cron_harakiri)
|
||||
current_cron->harakiri = now + uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
next:
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -181,6 +181,7 @@ void uwsgi_daemons_spawn_all() {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ud->registered = 1;
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -194,7 +195,6 @@ void uwsgi_daemons_spawn_all() {
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -366,7 +366,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
freq = atoi(comma + 1);
|
||||
}
|
||||
command = space + 1;
|
||||
if (!strcmp(opt, "smart-attach-daemon2")) {
|
||||
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
daemonize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+189
-35
@@ -234,11 +234,18 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
if (!uwsgi_emperor_is_valid(de->d_name))
|
||||
continue;
|
||||
|
||||
if (stat(de->d_name, &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(de->d_name, &st))
|
||||
continue;
|
||||
if (!S_ISLNK(st.st_mode) && !S_ISREG(st.st_mode))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (stat(de->d_name, &st))
|
||||
continue;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
}
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
@@ -294,16 +301,30 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
else {
|
||||
char *filename = uwsgi_calloc(0xff);
|
||||
memcpy(filename, c_ui->name, colon - c_ui->name);
|
||||
if (stat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c_ui = c_ui->ui_next;
|
||||
@@ -328,11 +349,18 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
|
||||
continue;
|
||||
|
||||
if (stat(g.gl_pathv[i], &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(g.gl_pathv[i], &st))
|
||||
continue;
|
||||
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (stat(g.gl_pathv[i], &st))
|
||||
continue;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
}
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
@@ -389,16 +417,30 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
else {
|
||||
char *filename = uwsgi_calloc(0xff);
|
||||
memcpy(filename, c_ui->name, colon - c_ui->name);
|
||||
if (stat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(filename, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
if (uwsgi.emperor_nofollow) {
|
||||
if (lstat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(c_ui->name, &st)) {
|
||||
emperor_stop(c_ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c_ui = c_ui->ui_next;
|
||||
@@ -748,15 +790,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *);
|
||||
|
||||
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
int i;
|
||||
char *colon = NULL;
|
||||
int counter;
|
||||
char **uenvs;
|
||||
char *uef;
|
||||
char **vassal_argv;
|
||||
pid_t pid;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
|
||||
@@ -780,9 +817,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
// TODO pre-start hook
|
||||
|
||||
// a new uWSGI instance will start
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
if (uwsgi.emperor_clone) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
pid = fork();
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
}
|
||||
#endif
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()")
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/fork()")
|
||||
}
|
||||
else if (pid > 0) {
|
||||
n_ui->pid = pid;
|
||||
@@ -812,9 +859,72 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// once the config is sent we can run hooks (they can fail)
|
||||
// exec hooks have access to all of the currently defined vars + UWSGI_VASSAL_PID, UWSGI_VASSAL_UID, UWSGI_VASSAL_GID, UWSGI_VASSAL_CONFIG
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
|
||||
uwsgi_log("running \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
char *argv[4];
|
||||
argv[0] = uwsgi_concat2("UWSGI_VASSAL_CONFIG=", n_ui->name);
|
||||
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", n_ui->pid); argv[1] = argv_pid;
|
||||
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", n_ui->uid); argv[2] = argv_uid;
|
||||
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", n_ui->gid); argv[3] = argv_gid;
|
||||
int ret = uwsgi_run_command_putenv_and_wait(NULL, usl->value, argv, 4);
|
||||
uwsgi_log("command \"%s\" exited with code: %d\n", usl->value, ret);
|
||||
free(argv[0]);
|
||||
}
|
||||
// 4 call hooks
|
||||
// config / config + pid / config + pid + uid + gid
|
||||
// call
|
||||
uwsgi_foreach(usl, uwsgi.call_as_emperor) {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_emperor1) {
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
func(n_ui->name);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_emperor2) {
|
||||
void (*func)(char *, pid_t) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
func(n_ui->name, n_ui->pid);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_emperor4) {
|
||||
void (*func)(char *, pid_t, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
func(n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
uwsgi_emperor_spawn_vassal(n_ui);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
|
||||
@@ -837,7 +947,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
unsetenv("UWSGI_RELOADS");
|
||||
unsetenv("NOTIFY_SOCKET");
|
||||
|
||||
uef = uwsgi_num2str(n_ui->pipe[1]);
|
||||
char *uef = uwsgi_num2str(n_ui->pipe[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
exit(1);
|
||||
@@ -863,15 +973,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
free(uef);
|
||||
}
|
||||
|
||||
uenvs = environ;
|
||||
char **uenvs = environ;
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
|
||||
#ifdef UNSETENV_VOID
|
||||
unsetenv(oe);
|
||||
#else
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
free(oe);
|
||||
|
||||
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
@@ -896,17 +1010,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
counter = 4;
|
||||
int counter = 4;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
char *colon = NULL;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
@@ -991,7 +1107,9 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
int i;
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
if (n_ui->use_config) {
|
||||
if (i == n_ui->pipe_config[1])
|
||||
continue;
|
||||
@@ -1001,6 +1119,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
|
||||
// run start hook (can fail)
|
||||
if (uwsgi.vassals_start_hook) {
|
||||
uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
|
||||
if (uwsgi.emperor_absolute_dir) {
|
||||
@@ -1012,6 +1131,44 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
|
||||
}
|
||||
|
||||
// run exec hooks (cannot fail)
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_vassal) {
|
||||
uwsgi_log("running \"%s\" (as-vassal)...\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);
|
||||
}
|
||||
}
|
||||
|
||||
// run low-level hooks
|
||||
uwsgi_foreach(usl, uwsgi.call_as_vassal) {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
func();
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_vassal1) {
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
func(n_ui->name);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_vassal3) {
|
||||
void (*func)(char *, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
func(n_ui->name, n_ui->uid, n_ui->gid);
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
@@ -1019,9 +1176,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
|
||||
// never here
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
@@ -376,7 +376,11 @@ void *event_queue_alloc(int nevents) {
|
||||
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
@@ -464,7 +468,11 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
*interesting_fd = (long) pe.portev_user;
|
||||
}
|
||||
else {
|
||||
@@ -972,6 +980,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
|
||||
struct file_obj fo;
|
||||
@@ -1032,6 +1041,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
return -1;
|
||||
}
|
||||
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_fsmon_setup() {
|
||||
struct uwsgi_string_list *usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
char *copy = uwsgi_str(usl->value);
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
goto next;
|
||||
}
|
||||
*space = 0;
|
||||
usl->value = copy;
|
||||
usl->len = strlen(copy);
|
||||
usl->custom_ptr = space+1;
|
||||
if (uwsgi_register_fsmon(usl)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
|
||||
}
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
static int inotify_fd = -1;
|
||||
if (inotify_fd == -1) {
|
||||
inotify_fd = inotify_init();
|
||||
if (inotify_fd < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
|
||||
return -1;
|
||||
}
|
||||
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
|
||||
if (wd < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
|
||||
return -1;
|
||||
}
|
||||
usl->custom = inotify_fd;
|
||||
usl->custom2 = wd;
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
|
||||
struct kevent kev;
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(usl->value);
|
||||
uwsgi_error("uwsgi_register_fsmon()/open()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
|
||||
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("uwsgi_register_fsmon()/kevent()");
|
||||
return -1;
|
||||
}
|
||||
usl->custom = fd;
|
||||
usl->custom2 = fd;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
|
||||
int found_fd = -1;
|
||||
struct uwsgi_string_list *usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
if ((int)usl->custom == interesting_fd) {
|
||||
found_fd = usl->custom;
|
||||
goto found;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
found:
|
||||
if (found_fd == -1) return NULL;
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
unsigned int isize = 0;
|
||||
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
|
||||
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
|
||||
return 0;
|
||||
}
|
||||
if (isize == 0) return NULL;
|
||||
struct inotify_event *ie = uwsgi_malloc(isize);
|
||||
// read from the inotify descriptor
|
||||
ssize_t len = read(found_fd, ie, isize);
|
||||
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
|
||||
found_fd = ie->wd;
|
||||
free(ie);
|
||||
#endif
|
||||
#endif
|
||||
// search for the item id and print it
|
||||
usl = uwsgi.fs_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return uwsgi.fs_reload;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_brutal_reload;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return uwsgi.fs_brutal_reload;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
usl = uwsgi.fs_signal;
|
||||
while(usl) {
|
||||
if ((int)usl->custom2 == found_fd) {
|
||||
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
|
||||
return usl;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_fsmon_event(int interesting_fd) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
|
||||
|
||||
if (!usl) return 0;
|
||||
|
||||
if (usl == uwsgi.fs_reload) {
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (usl == uwsgi.fs_brutal_reload) {
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fallback to signal
|
||||
uwsgi_route_signal(atoi(usl->custom_ptr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
if (!uwsgi.master_process && !uwsgi.force_gateway)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
ushared->gateways_cnt++;
|
||||
|
||||
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
int got_section = 0;
|
||||
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
@@ -147,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
val = ini_get_key(key);
|
||||
|
||||
if (!strcmp(section, section_asked)) {
|
||||
got_section = 1;
|
||||
ini_rstrip(key);
|
||||
val = ini_lstrip(val);
|
||||
ini_rstrip(val);
|
||||
@@ -161,6 +163,10 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
}
|
||||
|
||||
if (!got_section) {
|
||||
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
+18
-1
@@ -161,10 +161,17 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.empty = "";
|
||||
|
||||
#ifdef __linux__
|
||||
uwsgi.cgroup_dir_mode = "0700";
|
||||
#endif
|
||||
|
||||
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -348,7 +355,9 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes();
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -378,6 +387,8 @@ pid_t uwsgi_daemonize2() {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) uwsgi_setup_log_master();
|
||||
|
||||
return uwsgi.mypid;
|
||||
}
|
||||
|
||||
@@ -440,6 +451,12 @@ void sanitize_args() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* here we try to choose if thunder lock is a good thing */
|
||||
#ifdef UNBIT
|
||||
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
|
||||
uwsgi.use_thunder_lock = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
|
||||
|
||||
@@ -1078,3 +1078,22 @@ void uwsgi_add_safe_fd(int fd) {
|
||||
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
|
||||
uwsgi.safe_fds_cnt++;
|
||||
}
|
||||
|
||||
int uwsgi_is_again() {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
|
||||
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
+25
-2
@@ -79,6 +79,9 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
|
||||
ul->scroll = value;
|
||||
ul->scroll_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "dead", 4)) {
|
||||
ul->dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a node is added or removed (heavy locking is needed)
|
||||
@@ -611,6 +614,14 @@ static void *legion_loop(void *foobar) {
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
// remove node announcing death
|
||||
else if (legion_msg.dead) {
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s announced its death to Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_wlock(ul->lock);
|
||||
uwsgi_legion_remove_node(ul, node);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
node->lord_valor = legion_msg.lord_valor;
|
||||
@@ -752,8 +763,11 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
|
||||
goto err;
|
||||
}
|
||||
#ifdef UWSGI_UUID
|
||||
#endif
|
||||
|
||||
if (ul->dead) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
|
||||
@@ -1122,6 +1136,14 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_legion_announce_death(void) {
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
while (legion) {
|
||||
legion->dead = 1;
|
||||
uwsgi_legion_announce(legion);
|
||||
legion = legion->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_legion_atexit(void) {
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
@@ -1140,6 +1162,7 @@ next:
|
||||
legion = legion->next;
|
||||
}
|
||||
|
||||
uwsgi_legion_announce_death();
|
||||
}
|
||||
|
||||
int uwsgi_legion_i_am_the_lord(char *name) {
|
||||
|
||||
+44
-2
@@ -610,6 +610,32 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_ipcsem_check(uli);
|
||||
}
|
||||
|
||||
#ifdef UNBIT
|
||||
/*
|
||||
Unbit-specific workaround for robust-mutexes
|
||||
*/
|
||||
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
|
||||
for(;;) {
|
||||
uwsgi_lock(uwsgi.the_thunder_lock);
|
||||
uwsgi_unlock(uwsgi.the_thunder_lock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void uwsgi_robust_mutexes_watchdog() {
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// 32K should be more than enough...
|
||||
pthread_attr_setstacksize(&attr, 32 * 1024);
|
||||
|
||||
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
|
||||
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void uwsgi_setup_locking() {
|
||||
|
||||
@@ -689,6 +715,14 @@ ready:
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
// process shared thunder lock
|
||||
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
|
||||
#ifdef UNBIT
|
||||
// we have a serious bug on Unbit (and very probably on older libc)
|
||||
// when all of the workers die in the same moment the pthread robust mutes is left
|
||||
// in inconsistent state and we have no way to recover
|
||||
// we span a thread in the master constantly ensuring the lock is ok
|
||||
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
|
||||
uwsgi_robust_mutexes_watchdog();
|
||||
#endif
|
||||
}
|
||||
|
||||
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
|
||||
@@ -764,10 +798,18 @@ nextlock:
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_user_lock(int lock_num) {
|
||||
int uwsgi_user_lock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_user_unlock(int lock_num) {
|
||||
int uwsgi_user_unlock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+22
-4
@@ -45,7 +45,7 @@ void uwsgi_log(const char *fmt, ...) {
|
||||
}
|
||||
else {
|
||||
gettimeofday(&tv, NULL);
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
|
||||
@@ -97,7 +97,7 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
}
|
||||
else {
|
||||
gettimeofday(&tv, NULL);
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
|
||||
@@ -616,7 +616,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request);
|
||||
@@ -1035,7 +1035,7 @@ static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
|
||||
|
||||
static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_malloc(26);
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf);
|
||||
@@ -1060,6 +1060,19 @@ static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
if (!uwsgi.log_strftime) {
|
||||
return uwsgi_lf_ltime(wsgi_req, buf);
|
||||
}
|
||||
*buf = uwsgi_malloc(64);
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
size_t ret = strftime(*buf, 64, uwsgi.log_strftime, localtime(&now));
|
||||
if (ret == 0) {
|
||||
*buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
@@ -1246,6 +1259,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->func = uwsgi_lf_ltime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ftime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ctime;
|
||||
|
||||
+34
-1
@@ -375,6 +375,8 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_start_legions();
|
||||
#endif
|
||||
|
||||
uwsgi_add_reload_fds();
|
||||
|
||||
uwsgi_cache_start_sweepers();
|
||||
uwsgi_cache_start_sync_servers();
|
||||
|
||||
@@ -391,7 +393,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
if (uwsgi.stats) {
|
||||
char *tcp_port = strchr(uwsgi.stats, ':');
|
||||
char *tcp_port = strrchr(uwsgi.stats, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
@@ -485,6 +487,21 @@ int master_loop(char **argv, char **environ) {
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
@@ -686,6 +703,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
// get listen_queue status
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
int tmp_queue = 0;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
|
||||
@@ -697,8 +715,14 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi_sock->queue > tmp_queue) {
|
||||
tmp_queue = uwsgi_sock->queue;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
// fix queue size on multiple sockets
|
||||
uwsgi.shared->load = tmp_queue;
|
||||
|
||||
// check if some worker has to die (harakiri, evil checks...)
|
||||
uwsgi_master_check_workers_deadline();
|
||||
@@ -706,6 +730,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_master_check_gateways_deadline();
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
uwsgi_master_check_crons_deadline();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
@@ -768,6 +793,12 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -789,6 +820,7 @@ int master_loop(char **argv, char **environ) {
|
||||
if (uwsgi_master_check_mules_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid)) continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -853,6 +885,7 @@ next:
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
|
||||
@@ -197,6 +197,14 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
// user harakiri
|
||||
if (uwsgi.mules[i].user_harakiri > 0) {
|
||||
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].user_harakiri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +216,11 @@ void uwsgi_master_check_spoolers_deadline() {
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
}
|
||||
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->user_harakiri = 0;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
}
|
||||
@@ -277,3 +290,29 @@ int uwsgi_worker_is_busy(int wid) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_cron_death(int diedpid) {
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid == (pid_t) diedpid) {
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
|
||||
uc->pid = -1;
|
||||
uc->started_at = 0;
|
||||
return -1;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_crons_deadline() {
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
|
||||
kill(-uc->pid, SIGKILL);
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,79 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_fsmon_event(interesting_fd)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reload on fd
|
||||
if (uwsgi.reload_on_fd) {
|
||||
// custom -> fd
|
||||
// custom2 -> len (optional, default 1)
|
||||
// custom_ptr -> log message (optional)
|
||||
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
|
||||
while(usl) {
|
||||
if (interesting_fd == (int) usl->custom) {
|
||||
char stack_tmp[8];
|
||||
char *tmp = stack_tmp;
|
||||
if (usl->custom2 > 8) {
|
||||
tmp = uwsgi_malloc(usl->custom2);
|
||||
}
|
||||
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
|
||||
uwsgi_error("[reload-on-fd] read()");
|
||||
}
|
||||
if (usl->custom_ptr) {
|
||||
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
|
||||
}
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
// brutal reload on fd
|
||||
if (uwsgi.brutal_reload_on_fd) {
|
||||
// custom -> fd
|
||||
// custom2 -> len (optional, default 1)
|
||||
// custom_ptr -> log message (optional)
|
||||
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
|
||||
while(usl) {
|
||||
if (interesting_fd == (int) usl->custom) {
|
||||
char stack_tmp[8];
|
||||
char *tmp = stack_tmp;
|
||||
if (usl->custom2 > 8) {
|
||||
tmp = uwsgi_malloc(usl->custom2);
|
||||
}
|
||||
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
|
||||
uwsgi_error("[brutal-reload-on-fd] read()");
|
||||
}
|
||||
if (usl->custom_ptr) {
|
||||
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
|
||||
}
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wakeup from cheap mode ?
|
||||
if (uwsgi.status.is_cheap) {
|
||||
|
||||
+105
-1
@@ -388,6 +388,12 @@ void uwsgi_reload(char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.alarm_thread) {
|
||||
if (i == uwsgi.alarm_thread->queue) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[0]) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[1]) continue;
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
@@ -690,8 +696,17 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
while (ud) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
|
||||
@@ -1073,6 +1088,68 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
struct uwsgi_cron *ucron = uwsgi.crons;
|
||||
if (ucron) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_key(us, "crons"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
while (ucron) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
|
||||
goto end;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
|
||||
goto end;
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
ucron = ucron->next;
|
||||
if (ucron) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
struct uwsgi_legion *legion = NULL;
|
||||
if (uwsgi.legions) {
|
||||
@@ -1381,3 +1458,30 @@ int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int
|
||||
|
||||
}
|
||||
|
||||
static void add_reload_fds(struct uwsgi_string_list *list, char *type) {
|
||||
struct uwsgi_string_list *usl = list;
|
||||
while(usl) {
|
||||
char *strc = uwsgi_str(usl->value);
|
||||
char *space = strchr(strc, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->custom_ptr = space+1;
|
||||
}
|
||||
char *colon = strchr(strc, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
usl->custom2 = strtoul(colon+1, NULL, 10);
|
||||
}
|
||||
usl->custom = strtoul(strc, NULL, 10);
|
||||
if (!usl->custom2) usl->custom2 = 1;
|
||||
event_queue_add_fd_read(uwsgi.master_queue, usl->custom);
|
||||
uwsgi_add_safe_fd(usl->custom);
|
||||
uwsgi_log("added %s reload monitor for fd %d (read size: %llu)\n", type, (int) usl->custom, usl->custom2);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_add_reload_fds() {
|
||||
add_reload_fds(uwsgi.reload_on_fd, "graceful");
|
||||
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
|
||||
}
|
||||
|
||||
+21
-15
@@ -77,19 +77,8 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_run();
|
||||
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
@@ -98,6 +87,23 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_run() {
|
||||
int id = uwsgi.muleid;
|
||||
int i;
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
@@ -410,12 +416,12 @@ void uwsgi_setup_mules_and_farms() {
|
||||
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
|
||||
|
||||
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
|
||||
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
|
||||
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.mules[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.mules[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
uwsgi.mules[i].id = i + 1;
|
||||
|
||||
@@ -445,7 +451,7 @@ void uwsgi_setup_mules_and_farms() {
|
||||
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.farms[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
|
||||
+151
-2
@@ -58,6 +58,39 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offload engine:
|
||||
fd -> the file descriptor to read from
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (uor->fd < 0 || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
memory offload engine:
|
||||
buf -> pointer to the memory to transfer (memory is freed at the end)
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->buf || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
transfer offload engine:
|
||||
@@ -66,7 +99,7 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name) {
|
||||
return -1;
|
||||
@@ -240,6 +273,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
|
||||
return uwsgi_thread_new(uwsgi_offload_loop);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
offload memory transfer
|
||||
|
||||
uor->len -> the size of the memory chunk
|
||||
uor->buf -> the memory to transfer
|
||||
uor->written -> written bytes
|
||||
|
||||
status: none
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
if (fd == -1) {
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
return 0;
|
||||
}
|
||||
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
|
||||
if (rlen > 0) {
|
||||
uor->written += rlen;
|
||||
if (uor->written >= uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_memory_do()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
the offload task starts after having acquired the file fd
|
||||
@@ -279,7 +345,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_sendfile_do()");
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
|
||||
off_t len = 0;
|
||||
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
|
||||
// transfer finished
|
||||
@@ -293,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offloading
|
||||
status:
|
||||
0 -> waiting for data on fd
|
||||
1 -> waiting for write to s
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
// setup
|
||||
if (fd == -1) {
|
||||
event_queue_add_fd_read(ut->queue, uor->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(uor->status) {
|
||||
// read event from fd
|
||||
case 0:
|
||||
if (!uor->buf) {
|
||||
uor->buf = uwsgi_malloc(4096);
|
||||
}
|
||||
rlen = read(uor->fd, uor->buf, 4096);
|
||||
if (rlen > 0) {
|
||||
uor->to_write = rlen;
|
||||
uor->pos = 0;
|
||||
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
uor->status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> read()");
|
||||
}
|
||||
return -1;
|
||||
// write event on s
|
||||
case 1:
|
||||
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
|
||||
if (rlen > 0) {
|
||||
uor->to_write -= rlen;
|
||||
uor->pos += rlen;
|
||||
if (uor->to_write == 0) {
|
||||
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
|
||||
uor->status = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> write()");
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
the offload task starts soon after the call to connect()
|
||||
|
||||
@@ -490,6 +621,8 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
|
||||
void uwsgi_offload_engines_register_all() {
|
||||
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
|
||||
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
|
||||
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
|
||||
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
@@ -507,3 +640,19 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
|
||||
uor.ubuf = ubuf;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
|
||||
uor.buf = buf;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
|
||||
uor.fd = fd;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
+24
-5
@@ -24,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int plugin_already_loaded(const char *plugin) {
|
||||
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
@@ -33,7 +33,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
@@ -41,7 +41,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
@@ -61,14 +61,21 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int plugin_already_loaded(const char *plugin) {
|
||||
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
|
||||
if (up) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
@@ -91,6 +98,12 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
char *init_func = strchr(plugin_name, '|');
|
||||
if (init_func) {
|
||||
init_func[0] = 0;
|
||||
init_func++;
|
||||
}
|
||||
|
||||
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
|
||||
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
|
||||
need_free = 1;
|
||||
@@ -150,6 +163,12 @@ success:
|
||||
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
|
||||
}
|
||||
else {
|
||||
if (init_func) {
|
||||
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
|
||||
if (plugin_init_func) {
|
||||
plugin_init_func();
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
+2
-2
@@ -478,9 +478,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
int upload_progress_fd = -1;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
wsgi_req->post_file = tmpfile();
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+278
-15
@@ -166,23 +166,34 @@ static void uwsgi_routing_reset_memory(struct wsgi_request *wsgi_req, struct uws
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
int n = -1;
|
||||
|
||||
char *orig_subject = subject;
|
||||
uint16_t orig_subject_len = subject_len;
|
||||
|
||||
uint32_t *r_goto = &wsgi_req->route_goto;
|
||||
uint32_t *r_pc = &wsgi_req->route_pc;
|
||||
|
||||
if (routes == uwsgi.error_routes) {
|
||||
r_goto = &wsgi_req->error_route_goto;
|
||||
r_pc = &wsgi_req->error_route_pc;
|
||||
}
|
||||
else if (routes == uwsgi.final_routes) {
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
}
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (routes->label) goto next;
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
if (*r_goto > 0 && *r_pc < *r_goto) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
wsgi_req->route_goto = 0;
|
||||
*r_goto = 0;
|
||||
|
||||
if (!routes->if_func) {
|
||||
// could be a "run"
|
||||
@@ -244,7 +255,7 @@ next:
|
||||
subject = orig_subject;
|
||||
subject_len = orig_subject_len;
|
||||
routes = routes->next;
|
||||
if (routes) wsgi_req->route_pc++;
|
||||
if (routes) *r_pc = *r_pc+1;
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
@@ -268,9 +279,34 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
return uwsgi_apply_routes_do(wsgi_req, NULL, 0);
|
||||
return uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
void uwsgi_apply_final_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.final_routes) return;
|
||||
|
||||
// avoid loops
|
||||
if (wsgi_req->is_routing) return;
|
||||
|
||||
wsgi_req->is_final_routing = 1;
|
||||
|
||||
uwsgi_apply_routes_do(uwsgi.final_routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.error_routes) return 0;
|
||||
|
||||
// do not forget to check it !!!
|
||||
if (wsgi_req->is_error_routing) return 0;
|
||||
|
||||
wsgi_req->is_error_routing = 1;
|
||||
|
||||
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
while(urc) {
|
||||
@@ -282,11 +318,25 @@ static void *uwsgi_route_get_condition_func(char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_status(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
if (wsgi_req->status == ur->if_status) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *space = NULL;
|
||||
char *command = NULL;
|
||||
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
|
||||
struct uwsgi_route *old_ur = NULL, *ur = uwsgi.routes;
|
||||
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
|
||||
ur = uwsgi.final_routes;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
ur = uwsgi.error_routes;
|
||||
}
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
old_ur = ur;
|
||||
@@ -298,7 +348,15 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
old_ur->next = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
if (!uwsgi_starts_with(opt, strlen(opt), "final", 5)) {
|
||||
uwsgi.final_routes = ur;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
uwsgi.error_routes = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
}
|
||||
}
|
||||
|
||||
ur->pos = pos;
|
||||
@@ -344,6 +402,11 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(foobar, "status")) {
|
||||
ur->if_status = atoi(ur->orig_route);
|
||||
foobar = ur->orig_route;
|
||||
ur->if_func = uwsgi_route_condition_status;
|
||||
}
|
||||
|
||||
else if (!strcmp(foobar, "http_host")) {
|
||||
ur->subject = offsetof(struct wsgi_request, host);
|
||||
@@ -409,8 +472,7 @@ done:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_fixup_routes() {
|
||||
struct uwsgi_route *ur = uwsgi.routes;
|
||||
void uwsgi_fixup_routes(struct uwsgi_route *ur) {
|
||||
while(ur) {
|
||||
// prepare the main pointers
|
||||
ur->ovn = uwsgi_calloc(sizeof(int) * uwsgi.cores);
|
||||
@@ -496,6 +558,21 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// harakiri router
|
||||
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
if (route->custom > 0) {
|
||||
set_user_harakiri(route->custom);
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_harakiri_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// flush response
|
||||
static int transform_flush(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
// avoid loops !!!
|
||||
@@ -609,25 +686,37 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
uint32_t *r_goto = &wsgi_req->route_goto;
|
||||
uint32_t *r_pc = &wsgi_req->route_pc;
|
||||
|
||||
// find the label
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (wsgi_req->is_error_routing) {
|
||||
routes = uwsgi.error_routes;
|
||||
r_goto = &wsgi_req->error_route_goto;
|
||||
r_pc = &wsgi_req->error_route_pc;
|
||||
}
|
||||
else if (wsgi_req->is_final_routing) {
|
||||
routes = uwsgi.final_routes;
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
}
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
|
||||
wsgi_req->route_goto = routes->pos;
|
||||
*r_goto = routes->pos;
|
||||
goto found;
|
||||
}
|
||||
next:
|
||||
routes = routes->next;
|
||||
}
|
||||
|
||||
wsgi_req->route_goto = ur->custom;
|
||||
*r_goto = ur->custom;
|
||||
|
||||
found:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
|
||||
wsgi_req->route_goto = 0;
|
||||
if (*r_goto <= *r_pc) {
|
||||
*r_goto = 0;
|
||||
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
@@ -800,6 +889,126 @@ static int uwsgi_router_setscriptname(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setmethod route
|
||||
static int uwsgi_router_setmethod_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_METHOD", 14, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->method = ptr;
|
||||
wsgi_req->method_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmethod(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmethod_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// seturi route
|
||||
static int uwsgi_router_seturi_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_URI", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->uri = ptr;
|
||||
wsgi_req->uri_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_seturi_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
// setdocroot route
|
||||
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "DOCUMENT_ROOT", 13, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->document_root = ptr;
|
||||
wsgi_req->document_root_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setdocroot(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setdocroot_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setpathinfo route
|
||||
static int uwsgi_router_setpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->path_info = ptr;
|
||||
wsgi_req->path_info_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setpathinfo_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setscheme route
|
||||
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_SCHEME", 12, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->scheme = ptr;
|
||||
wsgi_req->scheme_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setscheme_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setuser route
|
||||
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
@@ -1291,6 +1500,19 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
uwsgi_uuid(ret);
|
||||
*vallen = 36;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "status", 6)) {
|
||||
ret = uwsgi_num2str(wsgi_req->status);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "rtime", 5)) {
|
||||
ret = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
|
||||
ret = uwsgi_num2str(uwsgi.shared->load);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1417,12 +1639,19 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("sethome", uwsgi_router_sethome);
|
||||
uwsgi_register_router("setfile", uwsgi_router_setfile);
|
||||
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
|
||||
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
|
||||
uwsgi_register_router("seturi", uwsgi_router_seturi);
|
||||
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
|
||||
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
|
||||
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("flush", uwsgi_router_flush);
|
||||
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
|
||||
|
||||
uwsgi_register_router("harakiri", uwsgi_router_harakiri);
|
||||
|
||||
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
|
||||
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
|
||||
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
|
||||
@@ -1522,7 +1751,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
|
||||
|
||||
void uwsgi_routing_dump() {
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (!routes) return;
|
||||
if (!routes) goto next;
|
||||
uwsgi_log("*** dumping internal routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
@@ -1537,5 +1766,39 @@ void uwsgi_routing_dump() {
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal routing table ***\n");
|
||||
next:
|
||||
routes = uwsgi.error_routes;
|
||||
if (!routes) goto next2;
|
||||
uwsgi_log("*** dumping internal error routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal error routing table ***\n");
|
||||
next2:
|
||||
routes = uwsgi.final_routes;
|
||||
if (!routes) return;
|
||||
uwsgi_log("*** dumping internal final routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal final routing table ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
+38
-1
@@ -10,7 +10,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
|
||||
off_t sf_len = len;
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
@@ -37,3 +37,40 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
simple non blocking sendfile implementation
|
||||
(generally used as fallback)
|
||||
*/
|
||||
|
||||
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_sendfile()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+4
-1
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
if (!uwsgi.master_process) {
|
||||
uwsgi_log("you cannot register signals without a master\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
||||
uwsgi_log("only the master and the workers can register signal handlers\n");
|
||||
|
||||
+8
-1
@@ -74,7 +74,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
}
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
}
|
||||
|
||||
uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
|
||||
@@ -1552,6 +1552,9 @@ void uwsgi_setup_shared_sockets() {
|
||||
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
shared_sock->family = AF_UNIX;
|
||||
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
@@ -1711,6 +1714,10 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
struct stat st;
|
||||
if (uwsgi_sock->name[0] != '@' && !stat(uwsgi_sock->name, &st)) {
|
||||
uwsgi_sock->inode = st.st_ino;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
|
||||
+39
-19
@@ -122,21 +122,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
|
||||
@@ -145,6 +131,26 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
void uwsgi_spooler_run() {
|
||||
int i;
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
}
|
||||
|
||||
void destroy_spool(char *dir, char *file) {
|
||||
|
||||
if (chdir(dir)) {
|
||||
@@ -221,20 +227,33 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
#endif
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_log("[spooler] unable to write header for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, size) != size) {
|
||||
uwsgi_log("[spooler] unable to write args for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (body && body_len > 0) {
|
||||
if ((size_t) write(fd, body, body_len) != body_len) {
|
||||
uwsgi_log("[spooler] unable to write body for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
if (at > 0) {
|
||||
#ifdef __UCLIBC__
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = at;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = at;
|
||||
ts[1].tv_nsec = 0;
|
||||
if (futimens(fd, ts)) {
|
||||
uwsgi_error("futimens()");
|
||||
}
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = at;
|
||||
tv[0].tv_usec = 0;
|
||||
@@ -247,6 +266,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
#endif
|
||||
uwsgi_error("futimes()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// here the file will be unlocked too
|
||||
@@ -374,7 +394,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
|
||||
|
||||
struct dirent **tasklist;
|
||||
int n;
|
||||
int n, i;
|
||||
|
||||
if (!dir)
|
||||
dir = uspool->dir;
|
||||
@@ -385,9 +405,9 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (n--) {
|
||||
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
|
||||
free(tasklist[n]);
|
||||
for (i = 0; i < n; i++) {
|
||||
spooler_manage_task(uspool, dir, tasklist[i]->d_name);
|
||||
free(tasklist[i]);
|
||||
}
|
||||
|
||||
free(tasklist);
|
||||
|
||||
+12
-11
@@ -2,9 +2,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
|
||||
// check for filename size
|
||||
if (filename_len + 4 > PATH_MAX) return 0;
|
||||
if (*filename_len + 4 > PATH_MAX) return 0;
|
||||
// check for supported encodings
|
||||
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
|
||||
|
||||
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for dirs/prefix
|
||||
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
|
||||
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for ext/suffix
|
||||
usl = uwsgi.static_gzip_ext;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for regexp
|
||||
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
|
||||
goto gzip;
|
||||
}
|
||||
url = url->next;
|
||||
@@ -43,12 +43,12 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
|
||||
gzip:
|
||||
|
||||
memcpy(filename + filename_len, ".gz\0", 4);
|
||||
filename_len += 3;
|
||||
memcpy(filename + *filename_len, ".gz\0", 4);
|
||||
*filename_len += 3;
|
||||
|
||||
if (stat(filename, st)) {
|
||||
filename_len -= 3;
|
||||
filename[filename_len] = 0;
|
||||
*filename_len -= 3;
|
||||
filename[*filename_len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) use_gzip = 1;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
@@ -579,6 +579,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
if (item && item_len > 0 && item_len <= PATH_MAX) {
|
||||
memcpy(real_filename, item, item_len);
|
||||
real_filename_len = item_len;
|
||||
real_filename[real_filename_len] = 0;
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
goto found;
|
||||
}
|
||||
@@ -644,7 +645,7 @@ safe:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
char *uwsgi_str_split_nget(char *str, size_t len, char what, size_t pos, size_t *rlen) {
|
||||
size_t i;
|
||||
size_t current = 0;
|
||||
char *choosen = str;
|
||||
size_t choosen_len = 0;
|
||||
*rlen = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (!choosen) choosen = str + i;
|
||||
if (str[i] == what) {
|
||||
if (current == pos) {
|
||||
if (choosen_len == 0) return NULL;
|
||||
*rlen = choosen_len;
|
||||
return choosen;
|
||||
}
|
||||
current++;
|
||||
choosen = NULL;
|
||||
choosen_len = 0;
|
||||
}
|
||||
else {
|
||||
choosen_len ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (current == pos) {
|
||||
if (choosen_len == 0) return NULL;
|
||||
*rlen = choosen_len;
|
||||
return choosen;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t uwsgi_str_occurence(char *str, size_t len, char what) {
|
||||
size_t count = 0;
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (str[i] == what) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// check if a string_list contains an item
|
||||
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
|
||||
struct uwsgi_string_list *usl = list;
|
||||
|
||||
+10
-5
@@ -82,6 +82,8 @@ int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
|
||||
found_nostream = 1;
|
||||
}
|
||||
else {
|
||||
// stop the chain if no chunk is available
|
||||
if (!ut->chunk) return 0;
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
goto next;
|
||||
@@ -132,6 +134,12 @@ void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
|
||||
if (current_ut->chunk) {
|
||||
uwsgi_buffer_destroy(current_ut->chunk);
|
||||
}
|
||||
if (current_ut->ub) {
|
||||
uwsgi_buffer_destroy(current_ut->ub);
|
||||
}
|
||||
if (current_ut->fd > -1) {
|
||||
close(current_ut->fd);
|
||||
}
|
||||
ut = ut->next;
|
||||
free(current_ut);
|
||||
}
|
||||
@@ -144,12 +152,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
|
||||
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
|
||||
ut->func = func;
|
||||
ut->is_final = 0;
|
||||
ut->next = NULL;
|
||||
ut->chunk = NULL;
|
||||
ut->can_stream = 0;
|
||||
ut->fd = -1;
|
||||
ut->data = data;
|
||||
|
||||
if (old_ut) {
|
||||
|
||||
+422
-498
File diff suppressed because it is too large
Load Diff
+325
-32
@@ -59,7 +59,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possibie)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
|
||||
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
|
||||
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI, 0},
|
||||
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose, 0},
|
||||
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
@@ -72,6 +72,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"fallback-config", required_argument, 0, "re-exec uwsgi with the specified config when exit code is 1", uwsgi_opt_set_str, &uwsgi.fallback_config, UWSGI_OPT_IMMEDIATE},
|
||||
{"strict", no_argument, 0, "enable strict mode (placeholder cannot be used)", uwsgi_opt_true, &uwsgi.strict, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
|
||||
@@ -171,6 +173,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
@@ -191,6 +194,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -203,9 +209,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"print-sym", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"print-symbol", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER, 0},
|
||||
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS, 0},
|
||||
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MIN_WORKER_LIFETIME, 0},
|
||||
@@ -218,8 +228,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"fd-safe", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
|
||||
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
|
||||
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
|
||||
@@ -233,6 +243,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
|
||||
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
|
||||
|
||||
{"add-cache-item", required_argument, 0, "add an item in the cache", uwsgi_opt_add_string_list, &uwsgi.add_cache_item, 0},
|
||||
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
|
||||
#ifdef UWSGI_ZLIB
|
||||
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
|
||||
@@ -258,6 +269,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
|
||||
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
|
||||
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
|
||||
{"mule-msg-size", optional_argument, 0, "set mule message buffer size", uwsgi_opt_set_int, &uwsgi.mule_msg_size, UWSGI_OPT_MASTER},
|
||||
|
||||
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
|
||||
@@ -278,6 +290,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"add-gid", required_argument, 0, "add the specified group id to the process credentials", uwsgi_opt_add_string_list, &uwsgi.additional_gids, 0},
|
||||
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
|
||||
@@ -285,8 +298,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0},
|
||||
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
|
||||
#endif
|
||||
{"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
|
||||
{"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
|
||||
|
||||
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
|
||||
{"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0},
|
||||
{"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0},
|
||||
@@ -295,6 +311,42 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
|
||||
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
|
||||
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
|
||||
|
||||
{"exec-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.exec_as_vassal, 0},
|
||||
{"exec-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.exec_as_emperor, 0},
|
||||
|
||||
{"wait-for-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-for-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"wait-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"wait-for-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-for-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
|
||||
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
|
||||
{"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0},
|
||||
{"call-as-root", required_argument, 0, "call the specified function before privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_root, 0},
|
||||
{"call-as-user", required_argument, 0, "call the specified function after privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_user, 0},
|
||||
{"call-as-user-atexit", required_argument, 0, "call the specified function before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.call_as_user_atexit, 0},
|
||||
{"call-pre-app", required_argument, 0, "call the specified function before app loading", uwsgi_opt_add_string_list, &uwsgi.call_pre_app, 0},
|
||||
{"call-post-app", required_argument, 0, "call the specified function after app loading", uwsgi_opt_add_string_list, &uwsgi.call_post_app, 0},
|
||||
|
||||
{"call-as-vassal", required_argument, 0, "call the specified function() before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal, 0},
|
||||
{"call-as-vassal1", required_argument, 0, "call the specified function(char *) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal1, 0},
|
||||
{"call-as-vassal3", required_argument, 0, "call the specified function(char *, uid_t, gid_t) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal3, 0},
|
||||
|
||||
{"call-as-emperor", required_argument, 0, "call the specified function() in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor, 0},
|
||||
{"call-as-emperor1", required_argument, 0, "call the specified function(char *) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor1, 0},
|
||||
{"call-as-emperor2", required_argument, 0, "call the specified function(char *, pid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor2, 0},
|
||||
{"call-as-emperor4", required_argument, 0, "call the specified function(char *, pid_t, uid_t, gid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor4, 0},
|
||||
|
||||
|
||||
|
||||
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#ifdef UWSGI_YAML
|
||||
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -330,6 +382,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
|
||||
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
|
||||
|
||||
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
|
||||
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
{"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
|
||||
@@ -345,6 +400,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
|
||||
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
|
||||
|
||||
{"fs-reload", required_argument, 0, "graceful reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_reload, UWSGI_OPT_MASTER},
|
||||
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
|
||||
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
|
||||
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
@@ -414,7 +475,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ssl-verbose", no_argument, 0, "be verbose about SSL errors", uwsgi_opt_true, &uwsgi.ssl_verbose, 0},
|
||||
// force master, as ssl sessions caching initialize locking early
|
||||
{"ssl-sessions-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-session-use-cache", no_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_true, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-session-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-sessions-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
|
||||
{"ssl-session-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
|
||||
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
|
||||
@@ -455,6 +516,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER},
|
||||
#endif
|
||||
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
@@ -492,6 +556,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
|
||||
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
|
||||
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
|
||||
{"force-cwd", required_argument, 0, "force the initial working directory to the specified value", uwsgi_opt_set_str, &uwsgi.force_cwd, 0},
|
||||
{"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
|
||||
{"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
|
||||
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
|
||||
@@ -531,6 +596,37 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
|
||||
|
||||
{"final-route", required_argument, 0, "add a final route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"final-route-status", required_argument, 0, "add a final route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"final-route-host", required_argument, 0, "add a final route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"final-route-uri", required_argument, 0, "add a final route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"final-route-qs", required_argument, 0, "add a final route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"final-route-remote-addr", required_argument, 0, "add a final route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"final-route-user-agent", required_argument, 0, "add a final route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"final-route-remote-user", required_argument, 0, "add a final route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"final-route-referer", required_argument, 0, "add a final route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"final-route-label", required_argument, 0, "add a final routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"final-route-if", required_argument, 0, "add a final route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"final-route-if-not", required_argument, 0, "add a final route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"final-route-run", required_argument, 0, "always run the specified final route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"error-route", required_argument, 0, "add an error route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"error-route-status", required_argument, 0, "add an error route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"error-route-host", required_argument, 0, "add an error route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"error-route-uri", required_argument, 0, "add an error route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"error-route-qs", required_argument, 0, "add an error route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"error-route-remote-addr", required_argument, 0, "add an error route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"error-route-user-agent", required_argument, 0, "add an error route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"error-route-remote-user", required_argument, 0, "add an error route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"error-route-referer", required_argument, 0, "add an error route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"error-route-label", required_argument, 0, "add an error routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"error-route-if", required_argument, 0, "add an error route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -544,6 +640,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"websockets-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
{"websocket-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
|
||||
{"chunked-input-limit", required_argument, 0, "set the max size of a chunked input part (default 1MB, in bytes)", uwsgi_opt_set_64bit, &uwsgi.chunked_input_limit, 0},
|
||||
{"chunked-input-timeout", required_argument, 0, "set default timeout for chunked input", uwsgi_opt_set_int, &uwsgi.chunked_input_timeout, 0},
|
||||
|
||||
{"clock", required_argument, 0, "set a clock source", uwsgi_opt_set_str, &uwsgi.requested_clock, 0},
|
||||
|
||||
{"clock-list", no_argument, 0, "list enabled clocks", uwsgi_opt_true, &uwsgi.clock_list, 0},
|
||||
@@ -598,12 +697,15 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
|
||||
{"early-envdir", required_argument, 0, "load a daemontools compatible envdir ASAP", uwsgi_opt_envdir, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
|
||||
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
|
||||
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
|
||||
#ifdef __linux__
|
||||
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
|
||||
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
|
||||
{"cgroup-dir-mode", required_argument, 0, "set permission for cgroup directory (default is 700)", uwsgi_opt_set_str, &uwsgi.cgroup_dir_mode, 0},
|
||||
{"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
|
||||
{"namespace-keep-mount", required_argument, 0, "keep the specified mountpoint in your namespace", uwsgi_opt_add_string_list, &uwsgi.ns_keep_mount, 0},
|
||||
{"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
|
||||
@@ -620,14 +722,20 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
|
||||
|
||||
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron2", required_argument, 0, "add a cron task (key=val syntax)", uwsgi_opt_add_cron2, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-cron", required_argument, 0, "add a unique cron task", uwsgi_opt_add_unique_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-harakiri", required_argument, 0, "set the maximum time (in seconds) we wait for cron command to complete", uwsgi_opt_set_int, &uwsgi.cron_harakiri, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-legion-cron", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-cron-legion", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
|
||||
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
|
||||
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -639,6 +747,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"need-plugins", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"need-plugin", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-list", no_argument, 0, "list enabled plugins", uwsgi_opt_true, &uwsgi.plugins_list, 0},
|
||||
@@ -652,6 +762,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
|
||||
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
|
||||
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
@@ -1042,6 +1153,10 @@ void grace_them_all(int signum) {
|
||||
|
||||
uwsgi_log("...gracefully killing workers...\n");
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_legion_announce_death();
|
||||
#endif
|
||||
|
||||
if (uwsgi.unsubscribe_on_graceful_reload) {
|
||||
uwsgi_unsubscribe_all();
|
||||
}
|
||||
@@ -1111,6 +1226,10 @@ void reap_them_all(int signum) {
|
||||
|
||||
uwsgi_log("...brutally killing workers...\n");
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_legion_announce_death();
|
||||
#endif
|
||||
|
||||
// unsubscribe if needed
|
||||
uwsgi_unsubscribe_all();
|
||||
|
||||
@@ -1192,7 +1311,7 @@ void what_i_am_doing() {
|
||||
for (i = 0; i < uwsgi.cores; i++) {
|
||||
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
if (wsgi_req->uri_len > 0) {
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
|
||||
@@ -1209,7 +1328,7 @@ void what_i_am_doing() {
|
||||
else {
|
||||
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[0].req;
|
||||
if (wsgi_req->uri_len > 0) {
|
||||
#ifdef __sun__
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
|
||||
@@ -1248,15 +1367,21 @@ struct uwsgi_plugin unconfigured_plugin = {
|
||||
void uwsgi_exec_atexit(void) {
|
||||
if (getpid() == masterpid) {
|
||||
// now run exit scripts needed by the user
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_as_user_atexit;
|
||||
while (usl) {
|
||||
struct uwsgi_string_list *usl;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_user_atexit) {
|
||||
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
|
||||
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);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_user_atexit) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1298,6 +1423,13 @@ static void vacuum(void) {
|
||||
}
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_UNIX && uwsgi_sock->name[0] != '@') {
|
||||
struct stat st;
|
||||
if (!stat(uwsgi_sock->name, &st)) {
|
||||
if (st.st_ino != uwsgi_sock->inode) {
|
||||
uwsgi_log("VACUUM WARNING: unix socket %s changed inode. Skip removal\n", uwsgi_sock->name);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
if (unlink(uwsgi_sock->name)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
@@ -1305,6 +1437,7 @@ static void vacuum(void) {
|
||||
uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
|
||||
}
|
||||
}
|
||||
next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
@@ -1362,14 +1495,17 @@ void signal_pidfile(int sig, char *filename) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
|
||||
static void fixup_argv_and_environ(int argc, char **argv, char **environ, char **envp) {
|
||||
|
||||
uwsgi.orig_argv = argv;
|
||||
uwsgi.argv = argv;
|
||||
uwsgi.argc = argc;
|
||||
uwsgi.environ = environ;
|
||||
|
||||
// avoid messing with fake environ
|
||||
if (envp && *environ != *envp) return;
|
||||
|
||||
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
|
||||
int i;
|
||||
@@ -1443,7 +1579,7 @@ void uwsgi_plugins_atexit(void) {
|
||||
|
||||
void uwsgi_backtrace(int depth) {
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
|
||||
#if defined(__linux__) || (defined(__APPLE__) && !defined(NO_EXECINFO)) || defined(UWSGI_HAS_EXECINFO)
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
@@ -1486,6 +1622,8 @@ void uwsgi_segfault(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -1499,6 +1637,8 @@ void uwsgi_fpe(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -1696,6 +1836,8 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_clock(&uwsgi_unix_clock);
|
||||
uwsgi_set_clock("unix");
|
||||
|
||||
// fallback config
|
||||
atexit(uwsgi_fallback_config);
|
||||
// manage/flush logs
|
||||
atexit(uwsgi_flush_logs);
|
||||
// clear sockets, pidfiles...
|
||||
@@ -1777,7 +1919,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
|
||||
|
||||
// ok we can now safely play with argv and environ
|
||||
fixup_argv_and_environ(argc, argv, environ);
|
||||
fixup_argv_and_environ(argc, argv, environ, envp);
|
||||
|
||||
if (gethostname(uwsgi.hostname, 255)) {
|
||||
uwsgi_error("gethostname()");
|
||||
@@ -1840,6 +1982,9 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
// manage envdirs ASAP
|
||||
uwsgi_envdirs(uwsgi.envdirs);
|
||||
|
||||
// --get management
|
||||
struct uwsgi_string_list *get_list = uwsgi.get_list;
|
||||
while(get_list) {
|
||||
@@ -1874,7 +2019,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
|
||||
|
||||
// setup master logging
|
||||
if (uwsgi.log_master)
|
||||
if (uwsgi.log_master && !uwsgi.daemonize2)
|
||||
uwsgi_setup_log_master();
|
||||
|
||||
// setup offload engines
|
||||
@@ -2036,6 +2181,12 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
// we could now patch the binary
|
||||
if (uwsgi.privileged_binary_patch) {
|
||||
uwsgi.argv[0] = uwsgi.privileged_binary_patch;
|
||||
@@ -2088,6 +2239,23 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.exec_in_jail) {
|
||||
uwsgi_log("running \"%s\" (in-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);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_in_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi_file_write_do(uwsgi.file_write_list);
|
||||
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
|
||||
@@ -2397,6 +2565,11 @@ int uwsgi_start(void *v_argv) {
|
||||
else if (!uwsgi.sockets && ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.master_process) {
|
||||
// here we will have a zombie... sorry
|
||||
uwsgi_log("...you should enable the master process... really...\n");
|
||||
if (uwsgi.force_gateway) {
|
||||
struct uwsgi_gateway *ug = &ushared->gateways[0];
|
||||
ug->loop(0, ug->data);
|
||||
// when we are here the gateway is dead :(
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -2531,7 +2704,7 @@ unsafe:
|
||||
}
|
||||
}
|
||||
|
||||
// initialize locks and socket as soon as possibile, as the master could enqueue tasks
|
||||
// initialize locks and socket as soon as possible, as the master could enqueue tasks
|
||||
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
|
||||
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
@@ -2752,7 +2925,7 @@ next2:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.sockets->fd != 0) {
|
||||
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
|
||||
if (dup2(uwsgi.sockets->fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
@@ -2790,6 +2963,44 @@ next2:
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->post_fork) {
|
||||
uwsgi.gp[i]->post_fork();
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.worker_exec2) {
|
||||
char *w_argv[2];
|
||||
w_argv[0] = uwsgi.worker_exec2;
|
||||
w_argv[1] = NULL;
|
||||
|
||||
uwsgi.sockets->arg &= (~O_NONBLOCK);
|
||||
if (fcntl(uwsgi.sockets->fd, F_SETFL, uwsgi.sockets->arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
|
||||
if (dup2(uwsgi.sockets->fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
execvp(w_argv[0], w_argv);
|
||||
// never here
|
||||
uwsgi_error("execvp()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_worker_run();
|
||||
// never here
|
||||
_exit(0);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_worker_run() {
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.lazy || uwsgi.lazy_apps) {
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
@@ -3077,7 +3288,7 @@ void build_options() {
|
||||
|
||||
/*
|
||||
|
||||
this function build the help output from the uwsgi.options structure
|
||||
this function builds the help output from the uwsgi.options structure
|
||||
|
||||
*/
|
||||
void uwsgi_help(char *opt, char *val, void *none) {
|
||||
@@ -3131,6 +3342,12 @@ void uwsgi_init_all_apps() {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_app) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_apps) {
|
||||
@@ -3190,6 +3407,11 @@ void uwsgi_init_all_apps() {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_app) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3335,7 +3557,9 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
|
||||
uint16_t *ptr = (uint16_t *) key;
|
||||
|
||||
if (value) {
|
||||
*ptr = (strtoul(value, NULL, 10));
|
||||
unsigned long n = strtoul(value, NULL, 10);
|
||||
if (n > 65535) n = 65535;
|
||||
*ptr = n;
|
||||
}
|
||||
else {
|
||||
*ptr = 1;
|
||||
@@ -3584,8 +3808,8 @@ void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
|
||||
}
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
|
||||
uwsgi_build_unshare(value);
|
||||
void uwsgi_opt_set_unshare(char *opt, char *value, void *mask) {
|
||||
uwsgi_build_unshare(value, (int *) mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3596,9 +3820,13 @@ void uwsgi_opt_set_env(char *opt, char *value, void *none) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
|
||||
#ifdef UNSETENV_VOID
|
||||
unsetenv(value);
|
||||
#else
|
||||
if (unsetenv(value)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
@@ -3626,6 +3854,10 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
if (uwsgi_load_plugin(-1, p, NULL)) {
|
||||
build_options();
|
||||
}
|
||||
else if (!uwsgi_startswith(opt, "need-", 5)) {
|
||||
uwsgi_log("unable to load plugin \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(p);
|
||||
@@ -4006,20 +4238,61 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
||||
// report CFLAGS used for compiling the server
|
||||
// use that values to build external plugins
|
||||
void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
|
||||
size_t len = sizeof(UWSGI_CFLAGS);
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
fprintf(stdout, "%.*s\n", (int) len / 2, base);
|
||||
fprintf(stdout, "%s\n", uwsgi_get_cflags());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *uwsgi_get_cflags() {
|
||||
size_t len = sizeof(UWSGI_CFLAGS) -1;
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc((len / 2) + 1);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
*ptr ++= 0;
|
||||
return base;
|
||||
}
|
||||
|
||||
// report uwsgi.h used for compiling the server
|
||||
// use that values to build external plugins
|
||||
extern char *uwsgi_dot_h;
|
||||
char *uwsgi_get_dot_h() {
|
||||
char *src = uwsgi_dot_h;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
#ifdef UWSGI_ZLIB
|
||||
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
|
||||
if (!ub) {
|
||||
free(base);
|
||||
return "";
|
||||
}
|
||||
// add final null byte
|
||||
uwsgi_buffer_append(ub, "\0", 1);
|
||||
free(base);
|
||||
// base is the final blob
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
|
||||
fprintf(stdout, "%s\n", uwsgi_get_dot_h());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
|
||||
|
||||
char buf[8192];
|
||||
@@ -4054,3 +4327,23 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
|
||||
};
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
|
||||
char **sym = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (sym) {
|
||||
uwsgi_log("%s", *sym);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *symbol_start = uwsgi_concat2(symbol, "_start");
|
||||
char *symbol_end = uwsgi_concat2(symbol, "_end");
|
||||
|
||||
char *sym_s = dlsym(RTLD_DEFAULT, symbol_start);
|
||||
char *sym_e = dlsym(RTLD_DEFAULT, symbol_end);
|
||||
|
||||
if (sym_s && sym_e) {
|
||||
uwsgi_log("%.*s", sym_e - sym_s, sym_s);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+54
-3
@@ -76,7 +76,19 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
|
||||
|
||||
// reset the buffer (could be useful for rollbacks...)
|
||||
wsgi_req->headers->pos = 0;
|
||||
// reset headers count
|
||||
wsgi_req->header_cnt = 0;
|
||||
struct uwsgi_buffer *hh = NULL;
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply error routes
|
||||
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_error_routing = 0;
|
||||
#endif
|
||||
if (status_len <= 4) {
|
||||
char *new_sc = NULL;
|
||||
size_t new_sc_len = 0;
|
||||
@@ -99,7 +111,6 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
|
||||
if (!hh) {wsgi_req->write_errors++; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
@@ -208,6 +219,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
@@ -270,8 +282,10 @@ sendbody:
|
||||
}
|
||||
|
||||
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
|
||||
}
|
||||
|
||||
int can_close = 1;
|
||||
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len, int can_close) {
|
||||
|
||||
if (fd == wsgi_req->sendfile_fd) can_close = 0;
|
||||
|
||||
@@ -280,6 +294,11 @@ int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->ignore_body) {
|
||||
if (can_close) close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendfile;
|
||||
@@ -294,7 +313,7 @@ sendfile:
|
||||
if (len == 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
@@ -389,3 +408,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
simplified write to client
|
||||
(generally used as fallback)
|
||||
*/
|
||||
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+56
@@ -2,6 +2,8 @@
|
||||
|
||||
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
|
||||
uwsgi_crc32(crc32, buf, len);
|
||||
return uwsgi_deflate(z, buf, len, dlen);
|
||||
@@ -38,6 +40,45 @@ end:
|
||||
return ub;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
|
||||
z_stream z;
|
||||
|
||||
z.zalloc = Z_NULL;
|
||||
z.zfree = Z_NULL;
|
||||
z.opaque = Z_NULL;
|
||||
if (inflateInit(&z) != Z_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
unsigned char out[8192];
|
||||
|
||||
z.next_in = (unsigned char *)buf;
|
||||
z.avail_in = len;
|
||||
z.next_out = out;
|
||||
|
||||
do {
|
||||
z.avail_out = 8192;
|
||||
z.next_out = out;
|
||||
int ret = inflate(&z, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
while (z.avail_out == 0);
|
||||
end:
|
||||
inflateEnd(&z);
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
@@ -54,6 +95,21 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
z->opaque = Z_NULL;
|
||||
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
if (dict && dict_len) {
|
||||
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
|
||||
uwsgi_crc32(crc32, NULL, 0);
|
||||
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet
|
||||
version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:html="http://www.w3.org/TR/html4/"
|
||||
xmlns="http://www.w3.org/TR/html4/"
|
||||
exclude-result-prefixes="html">
|
||||
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Strict//EN"
|
||||
indent="yes" doctype-system="http://www.w3.org/TR/html4/strict.dtd"
|
||||
encoding="UTF-8" />
|
||||
|
||||
<xsl:template name="format-date">
|
||||
<xsl:param name="date" />
|
||||
|
||||
<xsl:value-of select="substring-before($date, 'T')" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="substring-after($date, 'T')" />
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="index">
|
||||
<html>
|
||||
<head>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$stylesheet">
|
||||
<link rel="stylesheet" type="text/css" media="all" href="{$stylesheet}" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<style type="text/css">
|
||||
html {
|
||||
color: #000000;
|
||||
background-color: #fefefe;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
margin: .67em 0;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
td {
|
||||
font-family: mono;
|
||||
}
|
||||
td, th {
|
||||
padding: 0 1em;
|
||||
}
|
||||
td.size {
|
||||
text-align: right;
|
||||
}
|
||||
:link, :visited {
|
||||
text-decoration: none;
|
||||
}
|
||||
:link {
|
||||
color: #000099;
|
||||
}
|
||||
:visited {
|
||||
color: #6600cc;
|
||||
}
|
||||
:link:hover,
|
||||
:visited:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
:link:focus,
|
||||
:visited:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
:link:active,
|
||||
:visited:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<title>Index of <xsl:value-of select="@path" /></title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Index of <xsl:value-of select="@path" /></h1>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="name">Name</th>
|
||||
<th class="mtime">Last Modified</th>
|
||||
<th class="size">Size</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" colspan="3"><a href=".." title="Parent">Parent directory</a></td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="directory" />
|
||||
<xsl:apply-templates select="file" />
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="directory">
|
||||
<tr class="directory">
|
||||
<td class="name">
|
||||
<xsl:element name="a">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="." />
|
||||
<xsl:text>/</xsl:text>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="title">
|
||||
<xsl:value-of select="." />
|
||||
<xsl:text>/</xsl:text>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="." />
|
||||
<xsl:text>/</xsl:text>
|
||||
</xsl:element>
|
||||
</td>
|
||||
<td class="mtime">
|
||||
<xsl:call-template name="format-date">
|
||||
<xsl:with-param name="date" select="@mtime" />
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
<td class="size">
|
||||
<xsl:value-of select="@size" />
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="file">
|
||||
<tr class="file">
|
||||
<td class="name">
|
||||
<xsl:element name="a">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="." />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="title">
|
||||
<xsl:value-of select="." />
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="." />
|
||||
</xsl:element>
|
||||
</td>
|
||||
<td class="mtime">
|
||||
<xsl:call-template name="format-date">
|
||||
<xsl:with-param name="date" select="@mtime" />
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
<td class="size">
|
||||
<xsl:value-of select="@size" />
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[uwsgi]
|
||||
plugin = 0:notfound, router_xmldir, xslt
|
||||
http-socket = :8080
|
||||
|
||||
docroot = .
|
||||
check-static = %(docroot)
|
||||
|
||||
route-if = isdir:%(docroot)/${PATH_INFO} goto:index
|
||||
route-run = last:
|
||||
|
||||
route-label = index
|
||||
; uncomment to link CSS stylesheet /css/default.css
|
||||
;route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=/css/default.css,content_type=text/html
|
||||
; use embedded CSS
|
||||
route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=,content_type=text/html
|
||||
route-run = xmldir:%(docroot)/${PATH_INFO}
|
||||
|
||||
@@ -7,7 +7,14 @@ Net::HTTP.start("uwsgi.it") do |http|
|
||||
end
|
||||
end
|
||||
|
||||
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
|
||||
major,minor = RUBY_VERSION.split('.')
|
||||
if major.to_i >= 2 or (major.to_i == 1 and minor.to_i >= 9)
|
||||
# a trick for installations with messy PATH
|
||||
ENV['UWSGICONFIG_RUBYPATH'] = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
|
||||
system("bash install.sh ruby2 #{Dir.pwd}/uwsgi.ruby")
|
||||
else
|
||||
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
|
||||
end
|
||||
|
||||
open("Makefile", "w") do |file|
|
||||
file.write("all:\n")
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import uwsgi
|
||||
if uwsgi.loop == 'gevent':
|
||||
import gevent
|
||||
|
||||
from threading import Thread
|
||||
import time
|
||||
from uwsgidecorators import postfork
|
||||
|
||||
def foobar():
|
||||
while True:
|
||||
time.sleep(3)
|
||||
print "threee second elapsed in worker %d" % uwsgi.worker_id()
|
||||
|
||||
@postfork
|
||||
def spawn_thread():
|
||||
t = Thread(target=foobar)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
@postfork
|
||||
def spawn_thread2():
|
||||
t = Thread(target=foobar)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def gl_func():
|
||||
while True:
|
||||
gevent.sleep(2)
|
||||
print "i am a greenltet running in worker %d" % uwsgi.worker_id()
|
||||
|
||||
@postfork
|
||||
def spawn_greenlet():
|
||||
gevent.spawn(gl_func)
|
||||
|
||||
print uwsgi.version
|
||||
print uwsgi.workers()
|
||||
try:
|
||||
uwsgi.cache_set('foo', "Hello World from cache")
|
||||
except:
|
||||
pass
|
||||
def application(env, start_response):
|
||||
print env['wsgi.input'].read()
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep()
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar<br/>"
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep(3)
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
try:
|
||||
yield uwsgi.cache_get('foo')
|
||||
except:
|
||||
pass
|
||||
@@ -1,31 +0,0 @@
|
||||
import uwsgi
|
||||
import time
|
||||
import rrdtool
|
||||
|
||||
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
|
||||
|
||||
s_freq = 10
|
||||
|
||||
# this task will be executed every s_freq seconds
|
||||
def rrdtool_updater(sig, sec):
|
||||
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
|
||||
|
||||
|
||||
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
|
||||
|
||||
|
||||
|
||||
def hello_world(env, start_response):
|
||||
start_response('200 Ok', [('Content-type', 'text/plain')])
|
||||
return 'Hello world !'
|
||||
|
||||
|
||||
def graph(env, start_response):
|
||||
start_response('200 Ok', [('Content-type', 'image/png')])
|
||||
now = int(time.time())
|
||||
graph_range = (3600*24)
|
||||
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
|
||||
# send file to client
|
||||
uwsgi.sendfile('uwsgi_graph.png')
|
||||
|
||||
uwsgi.applications = {'/': hello_world, '/graph':graph}
|
||||
@@ -82,6 +82,12 @@ void linux_namespace_start(void *argv) {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
|
||||
pid = waitpid(pid, &waitpid_status, 0);
|
||||
if (pid < 0) {
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#AEC84D" d="M170.667,41.334"/>
|
||||
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
|
||||
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
|
||||
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
|
||||
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
|
||||
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
|
||||
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
|
||||
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
|
||||
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
|
||||
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
|
||||
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
|
||||
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
|
||||
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
|
||||
<g>
|
||||
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
|
||||
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
|
||||
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
|
||||
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
|
||||
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
|
||||
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
|
||||
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
|
||||
"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
|
||||
L204.667,32.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
|
||||
"/>
|
||||
</g>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
|
||||
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
|
||||
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
|
||||
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
|
||||
S685.666,30.334,631,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -8,6 +8,7 @@ struct uwsgi_airbrake_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *apikey;
|
||||
char *env;
|
||||
};
|
||||
|
||||
struct uwsgi_airbrake_opt {
|
||||
@@ -28,9 +29,14 @@ static void uwsgi_airbrake_set_apikey(CURL *curl, CURLoption option, char *arg,
|
||||
uacc->apikey = arg;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_set_env(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
uacc->env = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_airbrake_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
{"apikey", 0, uwsgi_airbrake_set_apikey},
|
||||
{"env", 0, uwsgi_airbrake_set_env},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_airbrake_ssl},
|
||||
{"timeout", CURLOPT_TIMEOUT, uwsgi_airbrake_int},
|
||||
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_airbrake_int},
|
||||
@@ -65,78 +71,89 @@ end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_airbrake_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) {
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
}
|
||||
|
||||
static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apikey) {
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
|
||||
xmlChar *xmlbuff;
|
||||
int buffersize;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr notice_node = NULL, node = NULL, line_node = NULL, errnode = NULL;
|
||||
char *msg = uwsgi_str("uWSGI segfault");
|
||||
char *msg = NULL;
|
||||
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
notice_node = xmlNewNode(NULL, BAD_CAST "notice");
|
||||
xmlNewProp(notice_node, BAD_CAST "version", BAD_CAST "2.3");
|
||||
xmlDocSetRootElement(doc, notice_node);
|
||||
|
||||
xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST apikey);
|
||||
xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST uacc->apikey);
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "notifier", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST "uWSGI");
|
||||
xmlNewChild(node, NULL, BAD_CAST "version", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewChild(node, NULL, BAD_CAST "url", BAD_CAST "https://github.com/unbit/uwsgi");
|
||||
|
||||
// request env
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "request", NULL);
|
||||
node = xmlNewChild(node, NULL, BAD_CAST "cgi-data", NULL);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "uwsgi_version");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST __VERSION__);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "compiled_with_version");
|
||||
|
||||
struct utsname uuts;
|
||||
#ifdef __sun__
|
||||
if (uname(&uuts) < 0) {
|
||||
#else
|
||||
if (uname(&uuts)) {
|
||||
#endif
|
||||
uwsgi_error("uname()");
|
||||
}
|
||||
else {
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.sysname);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_sysname");
|
||||
|
||||
char *os_version = uwsgi_concat3(uuts.release, "-", uuts.version);
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST os_version);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_version");
|
||||
free(os_version);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.machine);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "machine");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.nodename);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "nodename");
|
||||
|
||||
}
|
||||
// end request env
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
|
||||
if (uacc->env) {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST uacc->env);
|
||||
}
|
||||
else {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
|
||||
}
|
||||
|
||||
errnode = xmlNewChild(notice_node, NULL, BAD_CAST "error", NULL);
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "class", BAD_CAST "RuntimeError");
|
||||
node = xmlNewChild(errnode, NULL, BAD_CAST "backtrace", NULL);
|
||||
|
||||
char *p = strtok(ut->buf, "\n");
|
||||
int i = 0;
|
||||
char *ctx = NULL;
|
||||
char *text = uwsgi_str(ut->buf);
|
||||
char *p = strtok_r(text, "\n", &ctx);
|
||||
while (p) {
|
||||
// skip log messages
|
||||
if (!uwsgi_startswith(p, "***", 3))
|
||||
goto next;
|
||||
i++;
|
||||
// skip last 2 backtrace lines, real bt starts after them
|
||||
if (i <= 2) {
|
||||
goto next;
|
||||
}
|
||||
// backtrace line looks like this: uwsgi(simple_loop_run+0xc5) [0x451555]
|
||||
// we take binary/lib as filename
|
||||
// and extract method name from remaining string
|
||||
char *n = strchr(p, '(');
|
||||
if (n) {
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
|
||||
*n = 0;
|
||||
|
||||
char *pls = strchr(n+1, '+');
|
||||
@@ -144,8 +161,15 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
*pls = 0;
|
||||
}
|
||||
|
||||
if (i == 3) {
|
||||
free(msg);
|
||||
if (!strcmp("uwsgi_backtrace", n+1) || !strcmp("what_i_am_doing", n+1)) {
|
||||
goto next;
|
||||
}
|
||||
else if (!strcmp("uwsgi_fpe", n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI FPE at ", n+1, " in ", p);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!msg) {
|
||||
if (strlen(n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI segfault at ", n+1, " in ", p);
|
||||
}
|
||||
@@ -155,6 +179,12 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
}
|
||||
}
|
||||
|
||||
// skip empty lines
|
||||
if (!p)
|
||||
goto next;
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
|
||||
|
||||
if ((n+1)[0] == ')') {
|
||||
xmlNewProp(line_node, BAD_CAST "method", BAD_CAST "()");
|
||||
}
|
||||
@@ -164,28 +194,23 @@ static void uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut, char *apike
|
||||
|
||||
xmlNewProp(line_node, BAD_CAST "file", BAD_CAST p);
|
||||
|
||||
xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
|
||||
//xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
|
||||
}
|
||||
next:
|
||||
p = strtok(NULL, "\n");
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
}
|
||||
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "message", BAD_CAST msg);
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
|
||||
|
||||
xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
|
||||
free(ut->buf);
|
||||
free(msg);
|
||||
ut->buf = (char *) xmlbuff;
|
||||
ut->len = strlen(ut->buf);
|
||||
free(text);
|
||||
|
||||
return (char *) xmlbuff;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,11 +224,12 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_airbrake_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
@@ -218,7 +244,8 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
@@ -226,19 +253,20 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
|
||||
uwsgi_format_airbrake_backtrace(ut, uacc->apikey);
|
||||
char *notice = uwsgi_format_airbrake_backtrace(ut);
|
||||
|
||||
curl_slist_append(expect, "Accept: */*");
|
||||
curl_slist_append(expect, "Content-Type: text/xml; charset=utf-8");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ut->buf);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, ut->len);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notice);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(notice));
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
free(notice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -154,6 +154,7 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
@@ -168,7 +169,8 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import os
|
||||
|
||||
NAME='alarm_speech'
|
||||
|
||||
CFLAGS = []
|
||||
uwsgi_os = os.uname()[0]
|
||||
|
||||
LDFLAGS = []
|
||||
LIBS = ['-framework appkit']
|
||||
if uwsgi_os == "Darwin":
|
||||
CFLAGS = []
|
||||
LIBS = ['-framework appkit']
|
||||
else:
|
||||
CFLAGS = ['-I /usr/include/GNUstep']
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['alarm_speech.m']
|
||||
|
||||
@@ -214,7 +214,7 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
|
||||
// "Status: NNN"
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
@@ -229,13 +229,13 @@ static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len)
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -44,10 +44,6 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
peers->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// add timeout
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
// check retry
|
||||
if (cs->retry) {
|
||||
peers->can_retry = 1;
|
||||
}
|
||||
peers->prev = old_peers;
|
||||
|
||||
if (old_peers) {
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
}\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
|
||||
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
buf##_pos += len;
|
||||
ubuf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "cr.h"
|
||||
|
||||
@@ -9,13 +9,28 @@ int uwsgi_cr_map_use_void(struct uwsgi_corerouter *ucr, struct corerouter_peer *
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
uint64_t hits = 0;
|
||||
uwsgi_rlock(ucr->cache->lock);
|
||||
peer->instance_address = uwsgi_cache_get2(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len);
|
||||
char *value = uwsgi_cache_get4(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len, &hits);
|
||||
if (!value) goto end;
|
||||
peer->tmp_socket_name = uwsgi_concat2n(value, peer->instance_address_len, "", 0);
|
||||
size_t nodes = uwsgi_str_occurence(peer->tmp_socket_name, peer->instance_address_len, '|');
|
||||
if (nodes > 0) {
|
||||
size_t choosen_node = hits % (nodes+1);
|
||||
size_t choosen_node_len = 0;
|
||||
peer->instance_address = uwsgi_str_split_nget(peer->tmp_socket_name, peer->instance_address_len, '|', choosen_node, &choosen_node_len);
|
||||
if (!peer->instance_address) goto end;
|
||||
peer->instance_address_len = choosen_node_len;
|
||||
}
|
||||
else {
|
||||
peer->instance_address = peer->tmp_socket_name;
|
||||
}
|
||||
char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
|
||||
peer->instance_address_len = (cs_mod - peer->instance_address);
|
||||
}
|
||||
end:
|
||||
uwsgi_rwunlock(ucr->cache->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+13
-10
@@ -161,7 +161,7 @@ request:
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req)) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
@@ -201,7 +201,18 @@ edge:
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
free_req_queue;
|
||||
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
|
||||
goto edge;
|
||||
}
|
||||
// in case of errors (or thundering herd, just rest it)
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
@@ -209,14 +220,6 @@ edge:
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
free_req_queue;
|
||||
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
|
||||
goto edge;
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// here we spawn an async {} block
|
||||
CV *async_xs_call = newXS(NULL, XS_coroae_accept_request, "uwsgi::coroae");
|
||||
|
||||
@@ -453,7 +453,8 @@ static int amqp_wait_connection_tune(int fd) {
|
||||
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
char *ptr = (char *) fh;
|
||||
ssize_t len = 0, rlen;
|
||||
size_t len = 0;
|
||||
ssize_t rlen;
|
||||
|
||||
while(len < 7) {
|
||||
rlen = recv(fd, ptr, 7-len, 0);
|
||||
|
||||
@@ -172,6 +172,9 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
|
||||
cr_peer_connected(peer, "fr_instance_connected()");
|
||||
|
||||
// we are connected, we cannot retry anymore
|
||||
peer->can_retry = 0;
|
||||
|
||||
// fix modifiers
|
||||
peer->in->buf[0] = peer->session->main_peer->modifier1;
|
||||
peer->in->buf[3] = peer->session->main_peer->modifier2;
|
||||
@@ -217,6 +220,8 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
if (new_peer->instance_address_len == 0)
|
||||
return -1;
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
cr_connect(new_peer, fr_instance_connected);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_rack ur;
|
||||
extern struct uwsgi_plugin rack_plugin;
|
||||
static struct uwsgi_plugin *rack_plugin;
|
||||
|
||||
struct ufib {
|
||||
int enabled;
|
||||
@@ -53,7 +53,7 @@ static void fiber_schedule_to_req() {
|
||||
}
|
||||
|
||||
if (error) {
|
||||
rack_plugin.exception_log(NULL);
|
||||
rack_plugin->exception_log(NULL);
|
||||
rb_gc_unregister_address(&ufiber.fib[id]);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
static int fiber_init() {
|
||||
rack_plugin = uwsgi_plugin_get("rack");
|
||||
if (!rack_plugin) {
|
||||
uwsgi_log("[ruby-fiber] rack plugin is not loaded !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
|
||||
environment was not blessed by the Go community.
|
||||
|
||||
Instead of completely dropping support for Go, we studied how the gccgo project works and we
|
||||
decided it was a better approach for uWSGI.
|
||||
|
||||
This new plugin works by initializing a new "go runtime" after each fork().
|
||||
|
||||
The runtime calls the Go main function (developed by the user), and pass the whole
|
||||
uWSGI control to it.
|
||||
|
||||
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
|
||||
manages mules, spoolers and workers)
|
||||
|
||||
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
|
||||
from your apps are native goroutines)
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin gccgo_plugin;
|
||||
|
||||
struct uwsgi_gccgo{
|
||||
struct uwsgi_string_list *libs;
|
||||
char *args;
|
||||
} ugccgo;
|
||||
|
||||
/*
|
||||
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
*/
|
||||
|
||||
struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
// no_split_stack is the key to avoid crashing !!!
|
||||
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
|
||||
|
||||
void runtime_check(void);
|
||||
void runtime_args(int, char **);
|
||||
void runtime_osinit(void);
|
||||
void runtime_schedinit(void);
|
||||
void *__go_go(void *, void *);
|
||||
void runtime_main(void);
|
||||
void runtime_mstart(void *);
|
||||
|
||||
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
|
||||
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
|
||||
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
|
||||
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
|
||||
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
|
||||
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
|
||||
|
||||
static void mainstart(void *arg __attribute__((unused))) {
|
||||
runtime_main();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) __asm__ ("main.main");
|
||||
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
|
||||
|
||||
void (*uwsgigo_hook_init)(void);
|
||||
void (*uwsgigo_hook_main)(void);
|
||||
|
||||
void uwsgigo_main_init(void) {
|
||||
uwsgigo_hook_init();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) {
|
||||
uwsgigo_hook_main();
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_request_body_read(struct wsgi_request *wsgi_req, char *p, uint64_t len) {
|
||||
ssize_t rlen = 0;
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, len, &rlen);
|
||||
if (buf == uwsgi.empty) {
|
||||
return 0;
|
||||
}
|
||||
else if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, buf, rlen);
|
||||
return (int) rlen;
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *handler) {
|
||||
return uwsgi_register_signal(signum, receiver, handler, gccgo_plugin.modifier1);
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_initialize() {
|
||||
struct uwsgi_string_list *usl = ugccgo.libs;
|
||||
while(usl) {
|
||||
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!handle) {
|
||||
uwsgi_log("unable to open go shared library: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(handle, "main.main");
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (!uwsgigo_hook_init || !uwsgigo_hook_main) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go runtime initialization
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
argc++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
free(argv_list);
|
||||
}
|
||||
runtime_check();
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
int n = 0;
|
||||
while(p) {
|
||||
argv[n] = p;
|
||||
n++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
runtime_args(argc, argv);
|
||||
}
|
||||
else {
|
||||
char *argv[2] = {0,0};
|
||||
runtime_args(0, argv);
|
||||
}
|
||||
runtime_osinit();
|
||||
runtime_schedinit();
|
||||
__go_go(mainstart, NULL);
|
||||
runtime_mstart(runtime_m());
|
||||
// never here
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->async_environ = uwsgigo_env(wsgi_req);
|
||||
int i;
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
uwsgigo_env_add(wsgi_req->async_environ, 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);
|
||||
i++;
|
||||
}
|
||||
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
|
||||
uwsgigo_signal_handler(handler, signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin gccgo_plugin = {
|
||||
.name = "gccgo",
|
||||
.modifier1 = 11,
|
||||
.options = uwsgi_gccgo_options,
|
||||
//.on_load = uwsgi_gccgo_on_load,
|
||||
.request = uwsgi_gccgo_request,
|
||||
.after_request = uwsgi_gccgo_after_request,
|
||||
.post_fork = uwsgi_gccgo_initialize,
|
||||
.signal_handler = uwsgi_gccgo_signal_handler,
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
package uwsgi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
//extern uwsgi_takeover
|
||||
func uwsgi_takeover()
|
||||
//extern uwsgi_response_write_body_do
|
||||
func uwsgi_response_write_body_do(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_response_prepare_headers_int
|
||||
func uwsgi_response_prepare_headers_int(*interface{}, int) int
|
||||
//extern uwsgi_response_add_header
|
||||
func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
|
||||
//extern uwsgi_gccgo_helper_request_body_read
|
||||
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_gccgo_helper_register_signal
|
||||
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
|
||||
|
||||
var uwsgi_signals_gc [256]func(uint8)
|
||||
|
||||
func Env(wsgi_req *interface{}) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
return &env
|
||||
}
|
||||
|
||||
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
|
||||
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
r *http.Request
|
||||
wsgi_req *interface{}
|
||||
headers http.Header
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
uwsgi_response_write_body_do(w.wsgi_req, &p[0], uint64(len(p)))
|
||||
return len(p), err
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) WriteHeader(status int) {
|
||||
uwsgi_response_prepare_headers_int(w.wsgi_req, status )
|
||||
if w.headers.Get("Content-Type") == "" {
|
||||
w.headers.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
for k := range w.headers {
|
||||
for _, v := range w.headers[k] {
|
||||
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
|
||||
v = strings.TrimSpace(v)
|
||||
kb := []byte(k)
|
||||
vb := []byte(v)
|
||||
uwsgi_response_add_header(w.wsgi_req, &kb[0], uint16(len(k)), &vb[0], uint16(len(v)))
|
||||
}
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Header() http.Header {
|
||||
return w.headers
|
||||
}
|
||||
|
||||
|
||||
type BodyReader struct {
|
||||
wsgi_req *interface{}
|
||||
}
|
||||
|
||||
// there is no close in request body
|
||||
func (br *BodyReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *BodyReader) Read(p []byte) (n int, err error) {
|
||||
var rlen int = uwsgi_request_body_read(br.wsgi_req, &p[0], uint64(len(p)))
|
||||
if (rlen == 0) {
|
||||
err = io.EOF;
|
||||
return 0, err
|
||||
} else if (rlen == -1) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
return 0, err
|
||||
}
|
||||
return rlen, err
|
||||
}
|
||||
|
||||
func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
|
||||
httpReq, err := cgi.RequestFromMap(*env)
|
||||
if err == nil {
|
||||
httpReq.Body = &BodyReader{wsgi_req}
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
}
|
||||
|
||||
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
var b []byte = []byte(receiver)
|
||||
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
|
||||
return false
|
||||
}
|
||||
uwsgi_signals_gc[signum] = handler
|
||||
return true
|
||||
}
|
||||
|
||||
func SignalHandler(handler func(uint8), signum uint8) {
|
||||
handler(signum)
|
||||
}
|
||||
|
||||
func Run() {
|
||||
uwsgi_takeover()
|
||||
}
|
||||
@@ -164,14 +164,6 @@ edge:
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
free_req_queue;
|
||||
@@ -183,6 +175,14 @@ edge:
|
||||
goto clear;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// hack to easily pass wsgi_req pointer to the greenlet
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
|
||||
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
#include <uwsgi.h>
|
||||
#include <api/glfs.h>
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Author: Roberto De Ioris
|
||||
|
||||
--glusterfs-mount mountpoint=/foo,server=192.168.173.13:24007;192.168.173.17:0,volfile=foo.vol;volume=unbit001
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_plugin glusterfs_plugin;
|
||||
|
||||
struct uwsgi_glusterfs {
|
||||
int timeout;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} uglusterfs;
|
||||
|
||||
static struct uwsgi_option uwsgi_glusterfs_options[] = {
|
||||
{"glusterfs-mount", required_argument, 0, "virtual mount the specified glusterfs volume in a uri", uwsgi_opt_add_string_list, &uglusterfs.mountpoints, UWSGI_OPT_MIME},
|
||||
{"glusterfs-timeout", required_argument, 0, "timeout for glusterfs async mode", uwsgi_opt_set_int, &uglusterfs.timeout, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
static int uwsgi_glusterfs_read_sync(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
|
||||
while(remains > 0) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0);
|
||||
if (rlen <= 0) return -1;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) return -1;
|
||||
remains -= rlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
async read of a resource
|
||||
the uwsgi_glusterfs_async_io structure is passed between threads
|
||||
the callback simply signal the main core about the availability of data
|
||||
*/
|
||||
struct uwsgi_glusterfs_async_io {
|
||||
int fd[2];
|
||||
ssize_t rlen;
|
||||
};
|
||||
|
||||
static void uwsgi_glusterfs_read_async_cb(glfs_fd_t *fd, ssize_t rlen, void *data) {
|
||||
struct uwsgi_glusterfs_async_io *aio = (struct uwsgi_glusterfs_async_io *) data;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[glusterfs-cb] rlen = %d\n", rlen);
|
||||
#endif
|
||||
aio->rlen = rlen;
|
||||
// signal the core
|
||||
if (write(aio->fd[1], "\1", 1) <= 0) {
|
||||
uwsgi_error("uwsgi_glusterfs_read_async_cb()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_glusterfs_read_async(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
|
||||
char buf[8192];
|
||||
struct uwsgi_glusterfs_async_io aio;
|
||||
int ret = -1;
|
||||
if (pipe(aio.fd)) {
|
||||
uwsgi_error("uwsgi_glusterfs_read_async()/pipe()");
|
||||
return -1;
|
||||
}
|
||||
aio.rlen = -1;
|
||||
while(remains > 0) {
|
||||
// trigger an async read
|
||||
if (glfs_read_async(fd, buf, 8192, 0, uwsgi_glusterfs_read_async_cb, &aio)) goto end;
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(aio.fd[0], uglusterfs.timeout) <= 0) goto end;
|
||||
if (aio.rlen <= 0) goto end;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, aio.rlen)) goto end;
|
||||
remains -= aio.rlen;
|
||||
}
|
||||
ret = 0;
|
||||
end:
|
||||
close(aio.fd[0]);
|
||||
close(aio.fd[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_glusterfs_try(struct uwsgi_app *ua, char *node) {
|
||||
int ret = -1;
|
||||
char *colon = strchr(node, ':');
|
||||
// unix socket
|
||||
if (!colon) {
|
||||
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "unix", node, 0)) {
|
||||
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
|
||||
return -1;
|
||||
}
|
||||
goto connect;
|
||||
}
|
||||
|
||||
*colon = 0;
|
||||
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "tcp", node, atoi(colon+1))) {
|
||||
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
|
||||
return -1;
|
||||
}
|
||||
connect:
|
||||
ret = glfs_init((glfs_t *)ua->interpreter);
|
||||
if (ret) { uwsgi_error("[glusterfs] glfs_init()"); }
|
||||
else {
|
||||
if (colon) *colon = ':';
|
||||
uwsgi_log("[glusterfs] worker %d connected to %s\n", uwsgi.mywid, node);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_glusterfs_connect_do(struct uwsgi_app *ua) {
|
||||
char *servers = uwsgi_str(ua->callable);
|
||||
char *p = strtok(servers, ";");
|
||||
while(p) {
|
||||
uwsgi_log("[glusterfs] try connect to %s for mountpoint %.*s on worker %d ...\n", p, ua->mountpoint_len, ua->mountpoint, uwsgi.mywid);
|
||||
if (uwsgi_glusterfs_try(ua, p)) {
|
||||
goto end;
|
||||
}
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
end:
|
||||
free(servers);
|
||||
}
|
||||
|
||||
static void uwsgi_glusterfs_connect() {
|
||||
int i;
|
||||
// search for all of the glusterfs apps and connect to the server-based ones
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
if (uwsgi_apps[i].modifier1 != glusterfs_plugin.modifier1) continue;
|
||||
if (!uwsgi_apps[i].callable) {
|
||||
if (glfs_init((glfs_t *)uwsgi_apps[i].interpreter)) {
|
||||
uwsgi_error("[glusterfs] glfs_init()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[glusterfs] worker %d connected using volfile\n", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
uwsgi_glusterfs_connect_do(&uwsgi_apps[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_glusterfs_add_mountpoint(char *arg, size_t arg_len) {
|
||||
char *ugfs_mountpoint = NULL;
|
||||
char *ugfs_server = NULL;
|
||||
char *ugfs_volfile = NULL;
|
||||
char *ugfs_volume = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &ugfs_mountpoint,
|
||||
"server", &ugfs_server,
|
||||
"servers", &ugfs_server,
|
||||
"volfile", &ugfs_volfile,
|
||||
"volume", &ugfs_volume,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse glusterfs mountpoint definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!ugfs_mountpoint || (!ugfs_server && !ugfs_volfile) || !ugfs_volume) {
|
||||
uwsgi_log("[glusterfs] mount requires a mountpoint, a volume and at least one server or volfile\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
time_t now = uwsgi_now();
|
||||
uwsgi_log("[glusterfs] mounting %s ...\n", ugfs_mountpoint);
|
||||
// this should fail only if memory is not available
|
||||
glfs_t *volume = glfs_new(ugfs_volume);
|
||||
if (!volume) {
|
||||
uwsgi_error("unable to initialize glusterfs mountpoint: glfs_new()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ugfs_volfile) {
|
||||
if (glfs_set_volfile(volume, ugfs_volfile)) {
|
||||
uwsgi_error("unable to set glusterfs volfile: glfs_set_volfile\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
here we pass ugfs_server as the callable field.
|
||||
After fork() if this field is defined we will start trying to connect to each one of the configuratio nodes
|
||||
This is required to have fallback management
|
||||
*/
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, glusterfs_plugin.modifier1, ugfs_mountpoint, strlen(ugfs_mountpoint), volume, ugfs_server);
|
||||
if (!ua) {
|
||||
uwsgi_log("[glusterfs] unable to mount %s\n", ugfs_mountpoint);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ua->started_at = now;
|
||||
ua->startup_time = uwsgi_now() - now;
|
||||
uwsgi_log("GlusterFS app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, ugfs_mountpoint, (int) ua->startup_time, volume);
|
||||
}
|
||||
|
||||
// we translate the string list to an app representation
|
||||
// this happens before fork() if not in lazy/lazy-apps mode
|
||||
static void uwsgi_glusterfs_setup() {
|
||||
|
||||
if (!uglusterfs.timeout) {
|
||||
uglusterfs.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uglusterfs.mountpoints;
|
||||
while(usl) {
|
||||
uwsgi_glusterfs_add_mountpoint(usl->value, usl->len);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) {
|
||||
char filename[PATH_MAX+1];
|
||||
/* Standard GlusterFS request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty GlusterFS request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// blocks empty paths
|
||||
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) {
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1);
|
||||
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
||||
if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
}
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
filename[wsgi_req->path_info_len] = 0;
|
||||
|
||||
glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY);
|
||||
if (!fd) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct stat st;
|
||||
if (glfs_fstat(fd, &st)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len);
|
||||
if (mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end;
|
||||
|
||||
// skip body on HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
size_t remains = st.st_size;
|
||||
if (uwsgi.async > 1) {
|
||||
if (uwsgi_glusterfs_read_async(wsgi_req, fd, remains)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_glusterfs_read_sync(wsgi_req, fd, remains)) goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
glfs_close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin glusterfs_plugin = {
|
||||
.name = "glusterfs",
|
||||
.modifier1 = 27,
|
||||
.options = uwsgi_glusterfs_options,
|
||||
.post_fork = uwsgi_glusterfs_setup,
|
||||
.fixup = uwsgi_glusterfs_connect,
|
||||
.request = uwsgi_glusterfs_request,
|
||||
.after_request = log_request,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
NAME='glusterfs'
|
||||
|
||||
CFLAGS = os.popen('pkg-config --cflags glusterfs-api').read().rstrip().split()
|
||||
LDFLAGS = []
|
||||
LIBS = os.popen('pkg-config --libs glusterfs-api').read().rstrip().split()
|
||||
GCC_LIST = ['glusterfs']
|
||||
+91
-8
@@ -10,6 +10,7 @@ struct uwsgi_http uhttp;
|
||||
|
||||
struct uwsgi_option http_options[] = {
|
||||
{"http", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
|
||||
{"httprouter", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"https", required_argument, 0, "add an https router/server on the specified address with specified certificate and key", uwsgi_opt_https, &uhttp, 0},
|
||||
{"https2", required_argument, 0, "add an https/spdy router/server using keyval options", uwsgi_opt_https2, &uhttp, 0},
|
||||
@@ -121,7 +122,6 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
hr->content_length = uwsgi_str_num(val, vallen);
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
|
||||
// in the future we could support chunked requests...
|
||||
@@ -183,24 +183,44 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
peer->out_pos = 0;
|
||||
|
||||
struct uwsgi_buffer *out = peer->out;
|
||||
int found = 0;
|
||||
|
||||
// REQUEST_METHOD
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == ' ') {
|
||||
if (uwsgi_buffer_append_keyval(out, "REQUEST_METHOD", 14, base, ptr - base)) return -1;
|
||||
ptr++;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
else if (*ptr == '\r' || *ptr == '\n') break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// ensure we have a method
|
||||
if (!found) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// REQUEST_URI / PATH_INFO / QUERY_STRING
|
||||
base = ptr;
|
||||
found = 0;
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == '?' && !query_string) {
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
hr->path_info_len = ptr - base;
|
||||
hr->path_info = uwsgi_malloc(hr->path_info_len);
|
||||
if (!hr->path_info) {
|
||||
hr->path_info_len = ptr - base;
|
||||
hr->path_info = uwsgi_malloc(hr->path_info_len);
|
||||
}
|
||||
else {
|
||||
size_t new_path_info = ptr - base;
|
||||
if (new_path_info > hr->path_info_len) {
|
||||
char *tmp_buf = realloc(hr->path_info, new_path_info);
|
||||
if (!tmp_buf) return -1;
|
||||
hr->path_info = tmp_buf;
|
||||
}
|
||||
hr->path_info_len = new_path_info;
|
||||
}
|
||||
http_url_decode(base, &hr->path_info_len, hr->path_info);
|
||||
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
|
||||
query_string = ptr + 1;
|
||||
@@ -211,8 +231,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
if (uwsgi_buffer_append_keyval(out, "REQUEST_URI", 11, base, ptr - base)) return -1;
|
||||
if (!query_string) {
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
hr->path_info_len = ptr - base;
|
||||
hr->path_info = uwsgi_malloc(hr->path_info_len);
|
||||
if (!hr->path_info) {
|
||||
hr->path_info_len = ptr - base;
|
||||
hr->path_info = uwsgi_malloc(hr->path_info_len);
|
||||
}
|
||||
else {
|
||||
size_t new_path_info = ptr - base;
|
||||
if (new_path_info > hr->path_info_len) {
|
||||
char *tmp_buf = realloc(hr->path_info, new_path_info);
|
||||
if (!tmp_buf) return -1;
|
||||
hr->path_info = tmp_buf;
|
||||
}
|
||||
hr->path_info_len = new_path_info;
|
||||
}
|
||||
http_url_decode(base, &hr->path_info_len, hr->path_info);
|
||||
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
|
||||
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, "", 0)) return -1;
|
||||
@@ -221,13 +252,20 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, query_string, ptr - query_string)) return -1;
|
||||
}
|
||||
ptr++;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// ensure we have a URI
|
||||
if (!found) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SERVER_PROTOCOL
|
||||
base = ptr;
|
||||
found = 0;
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == '\r') {
|
||||
if (ptr + 1 >= watermark)
|
||||
@@ -239,11 +277,17 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
hr->session.can_keepalive = 1;
|
||||
}
|
||||
ptr += 2;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// ensure we have a protocol
|
||||
if (!found) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SCRIPT_NAME
|
||||
if (uwsgi_buffer_append_keyval(out, "SCRIPT_NAME", 11, "", 0)) return -1;
|
||||
|
||||
@@ -409,6 +453,9 @@ ssize_t hr_instance_connected(struct corerouter_peer* peer) {
|
||||
|
||||
cr_peer_connected(peer, "hr_instance_connected()");
|
||||
|
||||
// we are connected, we cannot retry anymore
|
||||
peer->can_retry = 0;
|
||||
|
||||
// prepare for write
|
||||
peer->out_pos = 0;
|
||||
|
||||
@@ -459,6 +506,8 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
|
||||
struct http_session *hr = (struct http_session *) peer->session;
|
||||
ssize_t len = cr_read(peer, "hr_instance_read()");
|
||||
if (!len) {
|
||||
// disable keepalive on unread body
|
||||
if (hr->content_length) hr->session.can_keepalive = 0;
|
||||
if (hr->session.can_keepalive) {
|
||||
peer->session->main_peer->disabled = 0;
|
||||
hr->rnrn = 0;
|
||||
@@ -543,8 +592,10 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
|
||||
}
|
||||
#endif
|
||||
else if (hr->force_chunked) {
|
||||
peer->in->limit = 0;
|
||||
if (uwsgi_buffer_insert_chunked(peer->in, 0, len)) return -1;
|
||||
if (uwsgi_buffer_append(peer->in, "\r\n", 2)) return -1;
|
||||
peer->in->len = UMIN(peer->in->len, UMAX16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,9 +626,16 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (main_peer->in->pos > hr->content_length) {
|
||||
main_peer->in->pos = hr->content_length;
|
||||
hr->content_length = 0;
|
||||
// on pipeline attempt, disable keepalive
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
else {
|
||||
hr->content_length -= main_peer->in->pos;
|
||||
if (hr->content_length == 0) {
|
||||
main_peer->disabled = 1;
|
||||
// stop reading from the client
|
||||
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -649,10 +707,11 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
|
||||
if (hr->remains > 0) {
|
||||
hr->session.can_keepalive = 0;
|
||||
if (hr->content_length < hr->remains) {
|
||||
hr->remains = hr->content_length;
|
||||
hr->content_length = 0;
|
||||
// we need to avoid problems with pipelined requests
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
else {
|
||||
hr->content_length -= hr->remains;
|
||||
@@ -660,7 +719,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (uwsgi_buffer_append(new_peer->out, main_peer->in->buf + hr->headers_size + 1, hr->remains)) return -1;
|
||||
}
|
||||
|
||||
if (hr->session.can_keepalive) {
|
||||
if (hr->session.can_keepalive && hr->content_length == 0) {
|
||||
main_peer->disabled = 1;
|
||||
// stop reading from the client
|
||||
if (uwsgi_cr_set_hooks(main_peer, NULL, NULL)) return -1;
|
||||
@@ -674,7 +733,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
cr_connect(new_peer, hr_instance_connected);
|
||||
break;
|
||||
}
|
||||
@@ -744,7 +803,31 @@ ssize_t hr_recv_stud4(struct corerouter_peer * main_peer) {
|
||||
|
||||
}
|
||||
|
||||
// retry connection to the backend
|
||||
static int hr_retry(struct corerouter_peer *peer) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = peer->session->corerouter;
|
||||
|
||||
if (peer->instance_address_len > 0) goto retry;
|
||||
|
||||
if (ucr->mapper(ucr, peer)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (peer->instance_address_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
retry:
|
||||
// start async connect (again)
|
||||
cr_connect(peer, hr_instance_connected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
// set the retry hook
|
||||
cs->retry = hr_retry;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
// set the modifier1
|
||||
cs->main_peer->modifier1 = uhttp.modifier1;
|
||||
|
||||
@@ -568,6 +568,8 @@ static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
|
||||
new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
|
||||
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
cr_connect(new_peer, hr_instance_connected);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -25,8 +25,10 @@ struct uwsgi_jvm {
|
||||
jclass input_stream_class;
|
||||
jclass file_class;
|
||||
jclass hashmap_class;
|
||||
jclass list_class;
|
||||
jclass set_class;
|
||||
jclass iterator_class;
|
||||
jclass bool_class;
|
||||
|
||||
jclass runtime_exception;
|
||||
jclass io_exception;
|
||||
@@ -63,6 +65,10 @@ jmethodID uwsgi_jvm_get_static_method_id_quiet(jclass, char *, char *);
|
||||
jobject uwsgi_jvm_str(char *, size_t);
|
||||
jobject uwsgi_jvm_hashmap(void);
|
||||
int uwsgi_jvm_hashmap_put(jobject, jobject, jobject);
|
||||
int uwsgi_jvm_hashmap_has(jobject, jobject);
|
||||
|
||||
jobject uwsgi_jvm_list(void);
|
||||
int uwsgi_jvm_list_add(jobject, jobject);
|
||||
|
||||
jobject uwsgi_jvm_call_object(jobject, jmethodID, ...);
|
||||
jobject uwsgi_jvm_call_object_static(jclass, jmethodID, ...);
|
||||
@@ -96,6 +102,7 @@ int uwsgi_jvm_call_bool(jobject, jmethodID, ...);
|
||||
int uwsgi_jvm_consume_input_stream(struct wsgi_request *, size_t, jobject);
|
||||
jobject uwsgi_jvm_num(long);
|
||||
jobject uwsgi_jvm_request_body_input_stream(void);
|
||||
jobject uwsgi_jvm_bool(long);
|
||||
|
||||
size_t uwsgi_jvm_array_len(jobject);
|
||||
jobject uwsgi_jvm_array_get(jobject, long);
|
||||
|
||||
@@ -215,15 +215,42 @@ JNIEXPORT jint JNICALL uwsgi_jvm_request_body_read_bytearray(JNIEnv *env, jobjec
|
||||
return rlen;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_readline_bytearray(JNIEnv *env, jobject o, jobject b) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
ssize_t rlen = 0;
|
||||
size_t len = uwsgi_jvm_array_len(b);
|
||||
char *chunk = uwsgi_request_body_readline(wsgi_req, len, &rlen);
|
||||
if (!chunk) {
|
||||
uwsgi_jvm_throw_io("error reading request body");
|
||||
return -1;
|
||||
}
|
||||
if (chunk == uwsgi.empty) {
|
||||
return -1;
|
||||
}
|
||||
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, b, JNI_FALSE);
|
||||
if (!buf) return -1;
|
||||
memcpy(buf, chunk, rlen);
|
||||
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, b, (jbyte *) buf, 0);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_available(JNIEnv *env, jobject o) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return (jint) (wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL uwsgi_jvm_request_body_seek(JNIEnv *env, jobject o, jint pos) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
uwsgi_request_body_seek(wsgi_req, pos);
|
||||
}
|
||||
|
||||
static JNINativeMethod uwsgi_jvm_request_body_methods[] = {
|
||||
{"read", "()I", (void *) &uwsgi_jvm_request_body_read},
|
||||
{"read", "([B)I", (void *) &uwsgi_jvm_request_body_read_bytearray},
|
||||
{"readLine", "([B)I", (void *) &uwsgi_jvm_request_body_readline_bytearray},
|
||||
{"available", "()I", (void *) &uwsgi_jvm_request_body_available},
|
||||
{"seek", "(I)V", (void *) &uwsgi_jvm_request_body_seek},
|
||||
};
|
||||
|
||||
static struct uwsgi_option uwsgi_jvm_options[] = {
|
||||
@@ -684,6 +711,23 @@ void uwsgi_jvm_local_unref(jobject obj) {
|
||||
(*ujvm_env)->DeleteLocalRef(ujvm_env, obj);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_list() {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "<init>", "()V");
|
||||
if (!mid) return NULL;
|
||||
}
|
||||
|
||||
jobject ll = (*ujvm_env)->NewObject(ujvm_env, ujvm.list_class, mid);
|
||||
if (uwsgi_jvm_exception()) {
|
||||
return NULL;
|
||||
}
|
||||
return ll;
|
||||
}
|
||||
|
||||
|
||||
jobject uwsgi_jvm_hashmap() {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -712,6 +756,18 @@ int uwsgi_jvm_hashmap_put(jobject hm, jobject key, jobject value) {
|
||||
return uwsgi_jvm_call(hm, mid, key, value);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_list_add(jobject ll, jobject value) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "add", "(Ljava/lang/Object;)Z");
|
||||
if (!mid) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_jvm_call(ll, mid, value);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -724,6 +780,21 @@ jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
|
||||
return uwsgi_jvm_call_object(hm, mid, key);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_hashmap_has(jobject hm, jobject key) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.hashmap_class, "containsKey", "(Ljava/lang/Object;)Z");
|
||||
if (!mid) return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_jvm_call_bool(hm, mid, key)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_iterator(jobject set) {
|
||||
// optimization
|
||||
static jmethodID mid = 0;
|
||||
@@ -825,6 +896,19 @@ jobject uwsgi_jvm_num(long num) {
|
||||
return o;
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_bool(long b) {
|
||||
static jmethodID mid = 0;
|
||||
if (!mid) {
|
||||
mid = uwsgi_jvm_get_method_id(ujvm.int_class, "<init>", "(I)V");
|
||||
if (!mid) return NULL;
|
||||
}
|
||||
jobject o = (*ujvm_env)->NewObject(ujvm_env, ujvm.bool_class, mid, b);
|
||||
if (uwsgi_jvm_exception()) {
|
||||
return NULL;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_str(char *str, size_t len) {
|
||||
jobject new_str;
|
||||
if (len > 0) {
|
||||
@@ -992,6 +1076,9 @@ static void uwsgi_jvm_create(void) {
|
||||
ujvm.int_class = uwsgi_jvm_class("java/lang/Integer");
|
||||
if (!ujvm.int_class) exit(1);
|
||||
|
||||
ujvm.bool_class = uwsgi_jvm_class("java/lang/Boolean");
|
||||
if (!ujvm.bool_class) exit(1);
|
||||
|
||||
ujvm.long_class = uwsgi_jvm_class("java/lang/Long");
|
||||
if (!ujvm.long_class) exit(1);
|
||||
|
||||
@@ -1010,6 +1097,9 @@ static void uwsgi_jvm_create(void) {
|
||||
ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap");
|
||||
if (!ujvm.hashmap_class) exit(1);
|
||||
|
||||
ujvm.list_class = uwsgi_jvm_class("java/util/ArrayList");
|
||||
if (!ujvm.list_class) exit(1);
|
||||
|
||||
ujvm.set_class = uwsgi_jvm_class("java/util/Set");
|
||||
if (!ujvm.set_class) exit(1);
|
||||
|
||||
@@ -1026,6 +1116,52 @@ static void uwsgi_jvm_create(void) {
|
||||
if (!uwsgi_class) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
start filling uwsgi.opt
|
||||
*/
|
||||
jfieldID opt_fid = (*ujvm_env)->GetStaticFieldID(ujvm_env, uwsgi_class, "opt", "Ljava/util/HashMap;");
|
||||
if (uwsgi_jvm_exception()) {
|
||||
exit(1);
|
||||
}
|
||||
jobject opt_hm = uwsgi_jvm_hashmap();
|
||||
int j;
|
||||
for (j = 0; j < uwsgi.exported_opts_cnt; j++) {
|
||||
jstring j_opt_key = uwsgi_jvm_str(uwsgi.exported_opts[j]->key, 0);
|
||||
if (uwsgi_jvm_hashmap_has(opt_hm, (jobject) j_opt_key)) {
|
||||
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
|
||||
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_bool(JNI_TRUE));
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
jobject ll = uwsgi_jvm_list();
|
||||
uwsgi_jvm_list_add(ll, j_opt_value);
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_list_add(ll, uwsgi_jvm_bool(JNI_TRUE));
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, ll);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[j]->value == NULL) {
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_bool(JNI_TRUE));
|
||||
}
|
||||
else {
|
||||
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
(*ujvm_env)->SetStaticObjectField(ujvm_env, uwsgi_class, opt_fid, opt_hm);
|
||||
|
||||
|
||||
(*ujvm_env)->RegisterNatives(ujvm_env, uwsgi_class, uwsgi_jvm_api_methods, sizeof(uwsgi_jvm_api_methods)/sizeof(uwsgi_jvm_api_methods[0]));
|
||||
if (uwsgi_jvm_exception()) {
|
||||
exit(1);
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class uwsgi {
|
||||
|
||||
static HashMap<String,Object> opt;
|
||||
|
||||
public static class RequestBody extends InputStream {
|
||||
public native int read();
|
||||
public native int read(byte[] b);
|
||||
public native int readLine(byte[] b);
|
||||
public native int available();
|
||||
public native void seek(int pos);
|
||||
}
|
||||
|
||||
public interface SignalHandler {
|
||||
|
||||
@@ -9,6 +9,7 @@ struct uwsgi_jwsgi {
|
||||
char *app;
|
||||
jmethodID app_mid;
|
||||
jclass app_class;
|
||||
jobject app_instance;
|
||||
} ujwsgi;
|
||||
|
||||
static struct uwsgi_option uwsgi_jwsgi_options[] = {
|
||||
@@ -20,7 +21,16 @@ static int uwsgi_jwsgi_add_request_item(jobject hm, char *key, uint16_t key_len,
|
||||
jobject j_key = uwsgi_jvm_str(key, key_len);
|
||||
if (!j_key) return -1;
|
||||
|
||||
jobject j_value = uwsgi_jvm_str(value, value_len);
|
||||
jobject j_value = NULL;
|
||||
// avoid clobbering vars
|
||||
if (value_len > 0) {
|
||||
j_value = uwsgi_jvm_str(value, value_len);
|
||||
}
|
||||
else {
|
||||
char *tmp = uwsgi_str("");
|
||||
j_value = uwsgi_jvm_str(tmp, 0);
|
||||
free(tmp);
|
||||
}
|
||||
if (!j_value) {
|
||||
uwsgi_jvm_local_unref(j_value);
|
||||
return -1;
|
||||
@@ -72,7 +82,12 @@ static int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi_jwsgi_add_request_input(hm, "jwsgi.input", 11)) goto end;
|
||||
|
||||
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
|
||||
if (!ujwsgi.app_instance) {
|
||||
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
|
||||
}
|
||||
else {
|
||||
response = uwsgi_jvm_call_object(ujwsgi.app_instance, ujwsgi.app_mid, hm);
|
||||
}
|
||||
if (!response) goto end;
|
||||
|
||||
if (uwsgi_jvm_array_len(response) != 3) {
|
||||
@@ -135,23 +150,31 @@ static int uwsgi_jwsgi_setup() {
|
||||
|
||||
char *app = uwsgi_str(ujwsgi.app);
|
||||
|
||||
char *method = "application";
|
||||
char *colon = strchr(app, ':');
|
||||
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid JWSGI app definition, must be class:method\n");
|
||||
exit(1);
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
method = colon + 1;
|
||||
}
|
||||
|
||||
*colon = 0;
|
||||
|
||||
ujwsgi.app_class = uwsgi_jvm_class(app);
|
||||
if (!ujwsgi.app_class) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id(ujwsgi.app_class, colon+1, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (!ujwsgi.app_mid) {
|
||||
exit(1);
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id_quiet(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
|
||||
jmethodID mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, "<init>", "()V");
|
||||
if (uwsgi_jvm_exception() || !mid) exit(1);
|
||||
ujwsgi.app_instance = (*ujvm_env)->NewObject(ujvm_env, ujwsgi.app_class, mid);
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_instance) {
|
||||
exit(1);
|
||||
}
|
||||
ujwsgi.app_mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
|
||||
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("JWSGI app \"%s\" loaded\n", ujwsgi.app);
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#if LUA_VERSION_NUM < 502
|
||||
# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
|
||||
# define lua_rawlen lua_objlen
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_lua {
|
||||
@@ -347,7 +352,7 @@ static int uwsgi_api_unlock(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_reg uwsgi_api[] = {
|
||||
static const luaL_Reg uwsgi_api[] = {
|
||||
{"log", uwsgi_api_log},
|
||||
{"connection_fd", uwsgi_api_req_fd},
|
||||
|
||||
@@ -411,7 +416,7 @@ static void uwsgi_lua_app() {
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
ulua.L[i] = luaL_newstate();
|
||||
luaL_openlibs(ulua.L[i]);
|
||||
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
|
||||
luaL_newlib(ulua.L[i], uwsgi_api);
|
||||
|
||||
lua_pushstring(ulua.L[i], UWSGI_VERSION);
|
||||
lua_setfield(ulua.L[i], -2, "version");
|
||||
@@ -711,7 +716,7 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
|
||||
static void uwsgi_lua_configurator_array(lua_State *L) {
|
||||
|
||||
int i;
|
||||
int n = luaL_getn(L, -3);
|
||||
int n = lua_rawlen(L, -3);
|
||||
|
||||
for(i=1;i<=n;i++) {
|
||||
lua_rawgeti(L, 1, i);
|
||||
|
||||
+26
-15
@@ -1,22 +1,33 @@
|
||||
import os,sys
|
||||
|
||||
try:
|
||||
LUALIB = os.environ['UWSGICONFIG_LUALIB']
|
||||
except:
|
||||
LUALIB = 'lua5.1'
|
||||
LUAINC = os.environ.get('UWSGICONFIG_LUAINC')
|
||||
LUALIB = os.environ.get('UWSGICONFIG_LUALIB')
|
||||
LUALIBPATH = os.environ.get('UWSGICONFIG_LUALIBPATH')
|
||||
LUAPC = os.environ.get('UWSGICONFIG_LUAPC', 'lua5.1')
|
||||
|
||||
try:
|
||||
LUAINC = os.environ['UWSGICONFIG_LUAINC']
|
||||
except:
|
||||
LUAINC = '/usr/include/lua5.1'
|
||||
# we LUAINC/LUALIB/LUALIBPATH override the LUAPC for backwards compat
|
||||
if LUAINC:
|
||||
CFLAGS = ['-I%s' % LUAINC]
|
||||
else:
|
||||
try:
|
||||
CFLAGS = os.popen('pkg-config --cflags %s' % LUAPC).read().rstrip().split()
|
||||
except:
|
||||
CFLAGS = ['-I/usr/include/lua5.1']
|
||||
|
||||
try:
|
||||
LUALIBPATH = os.environ['UWSGICONFIG_LUALIBPATH']
|
||||
except:
|
||||
LUALIBPATH = '/usr/lib/lua5.1'
|
||||
if LUALIB:
|
||||
LIBS = ['-l%s' % LUALIB]
|
||||
else:
|
||||
try:
|
||||
LIBS = os.popen('pkg-config --libs %s' % LUAPC).read().rstrip().split()
|
||||
except:
|
||||
LIBS = ['-llua5.1']
|
||||
|
||||
if LUALIBPATH:
|
||||
LDFLAGS = ['-L%s' % LUALIBPATH]
|
||||
else:
|
||||
LDFLAGS = []
|
||||
|
||||
NAME='lua'
|
||||
CFLAGS = ['-I%s' % LUAINC]
|
||||
LDFLAGS = ['-L%s' % LUALIBPATH]
|
||||
GCC_LIST = ['lua_plugin']
|
||||
LIBS = ['-l%s' % LUALIB]
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ struct uwsgi_mono {
|
||||
struct uwsgi_option uwsgi_mono_options[] = {
|
||||
|
||||
{"mono-app", required_argument, 0, "load a Mono asp.net app from the specified directory", uwsgi_opt_add_string_list, &umono.app, 0},
|
||||
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default, run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
|
||||
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default: run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
|
||||
{"mono-key", required_argument, 0, "select the ApplicationHost based on the specified CGI var", uwsgi_opt_add_string_list, &umono.key, 0},
|
||||
{"mono-version", required_argument, 0, "set the Mono jit version", uwsgi_opt_set_str, &umono.version, 0},
|
||||
{"mono-config", required_argument, 0, "set the Mono config file", uwsgi_opt_set_str, &umono.config, 0},
|
||||
@@ -547,7 +547,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
pthread_mutex_lock(&umono.lock_loader);
|
||||
}
|
||||
|
||||
// check if the mean time, something changed
|
||||
// check if in the mean time, something changed
|
||||
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct uwsgi_plugin objc_gc_plugin = {
|
||||
.name = "objc_gc",
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME="objc_gc"
|
||||
CFLAGS=["-fobjc-gc"]
|
||||
LDFLAGS=[]
|
||||
LIBS=[]
|
||||
GCC_LIST=['objc_gc.m']
|
||||
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
}
|
||||
else {
|
||||
char *sl = SG(sapi_headers).http_status_line;
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
|
||||
uwsgi_response_prepare_headers(wsgi_req, sl + 9 , strlen(sl + 9));
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
|
||||
+5
-1
@@ -1,5 +1,5 @@
|
||||
#undef __USE_GNU
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define HAS_BOOL 1
|
||||
@@ -50,6 +50,9 @@ struct uwsgi_perl {
|
||||
SV *atexit;
|
||||
|
||||
int loaded;
|
||||
|
||||
struct uwsgi_string_list *exec;
|
||||
struct uwsgi_string_list *exec_post_fork;
|
||||
};
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
@@ -66,3 +69,4 @@ int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
|
||||
PerlInterpreter *uwsgi_perl_new_interpreter(void);
|
||||
int uwsgi_perl_mule(char *);
|
||||
void uwsgi_perl_run_hook(SV *);
|
||||
void uwsgi_perl_exec(char *);
|
||||
|
||||
@@ -483,6 +483,16 @@ void uwsgi_psgi_app() {
|
||||
//load app in the main interpreter list
|
||||
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
|
||||
}
|
||||
// create a perl environment (if needed)
|
||||
else if (uperl.exec) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uperl.exec) {
|
||||
uwsgi_perl_exec(usl->value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -502,3 +512,10 @@ int uwsgi_perl_mule(char *opt) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_perl_exec(char *filename) {
|
||||
size_t size = 0;
|
||||
char *buf = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
perl_eval_pv(buf, 0);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
+28
-10
@@ -21,6 +21,8 @@ struct uwsgi_option uwsgi_perl_options[] = {
|
||||
#endif
|
||||
{"perl-args", required_argument, 0, "add items (space separated) to @ARGV", uwsgi_opt_set_str, &uperl.argv_items, 0},
|
||||
{"perl-arg", required_argument, 0, "add an item to @ARGV", uwsgi_opt_add_string_list, &uperl.argv_item, 0},
|
||||
{"perl-exec", required_argument, 0, "exec the specified perl file before fork()", uwsgi_opt_add_string_list, &uperl.exec, 0},
|
||||
{"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -394,33 +396,44 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->dynamic) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&uperl.lock_loader);
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, psgi_plugin.modifier1);
|
||||
// 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 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
||||
if (uwsgi_apps[uwsgi.default_app].modifier1 == psgi_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (wsgi_req->dynamic) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_unlock(&uperl.lock_loader);
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- unable to find perl application ---\n");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
wi->requests++;
|
||||
@@ -577,6 +590,11 @@ void uwsgi_perl_post_fork() {
|
||||
SvREADONLY_on(GvSV(tmpgv));
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uperl.exec_post_fork) {
|
||||
uwsgi_perl_exec(usl->value);
|
||||
}
|
||||
|
||||
if (uperl.postfork) {
|
||||
uwsgi_perl_run_hook(uperl.postfork);
|
||||
}
|
||||
@@ -712,7 +730,7 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
|
||||
STRLEN rlen;
|
||||
SV *response = POPs;
|
||||
char *value = SvPV(response, rlen );
|
||||
ret = UMIN(UMAX16, rlen);
|
||||
ret = UMIN(UMAX16-1, rlen);
|
||||
memcpy(buffer, value, ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,16 @@ XS(XS_signal) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_set_user_harakiri) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
set_user_harakiri( SvIV(ST(0)) );
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_reload) {
|
||||
dXSARGS;
|
||||
|
||||
@@ -549,5 +559,7 @@ void init_perl_embedded_module() {
|
||||
|
||||
psgi_xs(add_timer);
|
||||
psgi_xs(add_rb_timer);
|
||||
|
||||
psgi_xs(set_user_harakiri);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
#include <uwsgi.h>
|
||||
#ifdef __linux__
|
||||
#include <pty.h>
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#include <util.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <libutil.h>
|
||||
#endif
|
||||
#ifndef __FreeBSD__
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_pty_client {
|
||||
int fd;
|
||||
struct uwsgi_pty_client *prev;
|
||||
struct uwsgi_pty_client *next;
|
||||
};
|
||||
|
||||
static struct uwsgi_pty {
|
||||
char *addr;
|
||||
char *remote;
|
||||
int queue;
|
||||
int server_fd;
|
||||
int master_fd;
|
||||
int slave_fd;
|
||||
int log;
|
||||
int original_log;
|
||||
int input;
|
||||
int original_input;
|
||||
int no_isig;
|
||||
char *command;
|
||||
pid_t command_pid;
|
||||
struct uwsgi_pty_client *head;
|
||||
struct uwsgi_pty_client *tail;
|
||||
} upty;
|
||||
|
||||
static struct uwsgi_pty_client *uwsgi_pty_client_new(int fd) {
|
||||
struct uwsgi_pty_client *upc = uwsgi_calloc(sizeof(struct uwsgi_pty_client));
|
||||
upc->fd = fd;
|
||||
if (upty.tail) {
|
||||
upc->prev = upty.tail;
|
||||
upty.tail->next = upc;
|
||||
}
|
||||
upty.tail = upc;
|
||||
if (!upty.head) upty.head = upc;
|
||||
return upc;
|
||||
}
|
||||
|
||||
static void uwsgi_pty_client_remove(struct uwsgi_pty_client *upc) {
|
||||
struct uwsgi_pty_client *prev = upc->prev;
|
||||
struct uwsgi_pty_client *next = upc->next;
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
if (upc == upty.head) {
|
||||
upty.head = next;
|
||||
}
|
||||
|
||||
if (upc == upty.tail) {
|
||||
upty.tail = prev;
|
||||
}
|
||||
|
||||
close(upc->fd);
|
||||
free(upc);
|
||||
}
|
||||
|
||||
static struct uwsgi_option uwsgi_pty_options[] = {
|
||||
{"pty-socket", required_argument, 0, "bind the pty server on the specified address", uwsgi_opt_set_str, &upty.addr, 0},
|
||||
{"pty-log", no_argument, 0, "send stdout/stderr to the log engine too", uwsgi_opt_true, &upty.log, 0},
|
||||
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
|
||||
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
|
||||
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
|
||||
{"pty-exec", no_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
void uwsgi_pty_setterm(int fd) {
|
||||
struct termios tio;
|
||||
tcgetattr(fd, &tio);
|
||||
|
||||
tio.c_iflag |= IGNPAR;
|
||||
tio.c_iflag &= ~(ISTRIP | IMAXBEL | BRKINT | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
|
||||
#ifdef IUCLC
|
||||
tio.c_iflag &= ~IUCLC;
|
||||
#endif
|
||||
tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
|
||||
if (upty.no_isig) {
|
||||
tio.c_lflag &= ~(ISIG);
|
||||
}
|
||||
#ifdef IEXTEN
|
||||
tio.c_lflag &= ~IEXTEN;
|
||||
#endif
|
||||
tio.c_oflag &= ~OPOST;
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 0;
|
||||
|
||||
#ifdef B38400
|
||||
cfsetispeed(&tio, B38400);
|
||||
cfsetospeed(&tio, B38400);
|
||||
#endif
|
||||
|
||||
tcsetattr(fd, TCSANOW, &tio);
|
||||
}
|
||||
|
||||
static void *uwsgi_pty_loop(void *arg) {
|
||||
|
||||
/*
|
||||
if slave is ready there is something to send to the clients (and logs)
|
||||
|
||||
if client is ready we have something to write to the master pty
|
||||
*/
|
||||
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
|
||||
if (ret == 0) continue;
|
||||
if (ret < 0) continue;
|
||||
|
||||
if (upty.input && interesting_fd == upty.original_input) {
|
||||
ssize_t rlen = read(upty.original_input, buf, 8192);
|
||||
if (rlen <= 0) continue;
|
||||
if (write(upty.master_fd, buf, rlen) != rlen) {
|
||||
// what to do ?
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == upty.master_fd) {
|
||||
ssize_t rlen = read(upty.master_fd, buf, 8192);
|
||||
if (rlen == 0) exit(1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("uwsgi_pty_loop()/read()");
|
||||
}
|
||||
if (upty.log && upty.original_log >= 0) {
|
||||
if (write(upty.original_log, buf, rlen) != rlen) {
|
||||
// what to do ?
|
||||
}
|
||||
}
|
||||
struct uwsgi_pty_client *upc = upty.head;
|
||||
while(upc) {
|
||||
if (write(upc->fd, buf, rlen) != rlen) {
|
||||
struct uwsgi_pty_client *tmp_upc = upc->next;
|
||||
uwsgi_pty_client_remove(upc);
|
||||
upc = tmp_upc;
|
||||
continue;
|
||||
}
|
||||
upc = upc->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == upty.server_fd) {
|
||||
struct sockaddr_un client_src;
|
||||
memset(&client_src, 0, sizeof(struct sockaddr_un));
|
||||
socklen_t client_src_len = 0;
|
||||
|
||||
int client_fd = accept(upty.server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
continue;
|
||||
}
|
||||
struct uwsgi_pty_client *upc = uwsgi_pty_client_new(client_fd);
|
||||
event_queue_add_fd_read(upty.queue, upc->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct uwsgi_pty_client *upc = upty.head;
|
||||
while(upc) {
|
||||
if (interesting_fd == upc->fd) {
|
||||
ssize_t rlen = read(upc->fd, buf, 8192);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_pty_client_remove(upc);
|
||||
break;
|
||||
}
|
||||
if (write(upty.master_fd, buf, rlen) != rlen) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
upc = upc->next;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_pty_init() {
|
||||
|
||||
if (!upty.addr) return;
|
||||
if (!uwsgi.master_process) return;
|
||||
if (uwsgi.mywid > 1) return;
|
||||
|
||||
char *tcp_port = strrchr(upty.addr, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
upty.server_fd = bind_to_tcp(upty.addr, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
upty.server_fd = bind_to_unix(upty.addr, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
if (upty.log) {
|
||||
upty.original_log = dup(1);
|
||||
}
|
||||
|
||||
if (upty.input) {
|
||||
upty.original_input = dup(0);
|
||||
}
|
||||
|
||||
if (openpty(&upty.master_fd, &upty.slave_fd, NULL, NULL, NULL)) {
|
||||
uwsgi_error("uwsgi_pty_init()/openpty()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("pty server %s (fd: %d) enabled on %s master: %d slave: %d\n", upty.addr, upty.server_fd, ttyname(upty.slave_fd), upty.master_fd, upty.slave_fd);
|
||||
|
||||
upty.queue = event_queue_init();
|
||||
|
||||
event_queue_add_fd_read(upty.queue, upty.master_fd);
|
||||
event_queue_add_fd_read(upty.queue, upty.server_fd);
|
||||
if (upty.input) {
|
||||
event_queue_add_fd_read(upty.queue, upty.original_input);
|
||||
uwsgi_pty_setterm(upty.original_input);
|
||||
}
|
||||
|
||||
login_tty(upty.slave_fd);
|
||||
|
||||
if (upty.command) {
|
||||
upty.command_pid = uwsgi_run_command(upty.command, NULL, -1);
|
||||
}
|
||||
|
||||
pthread_t t;
|
||||
pthread_create(&t, NULL, uwsgi_pty_loop, NULL);
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_pty_client() {
|
||||
if (!upty.remote) return 0;
|
||||
|
||||
uwsgi_log("[pty] connecting to %s ...\n", upty.remote);
|
||||
|
||||
// save current terminal settings
|
||||
if (!tcgetattr(0, &uwsgi.termios)) {
|
||||
uwsgi.restore_tc = 1;
|
||||
}
|
||||
|
||||
upty.server_fd = uwsgi_connect(upty.remote, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (upty.server_fd < 0) {
|
||||
uwsgi_error("uwsgi_pty_client()/connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(upty.server_fd);
|
||||
uwsgi_socket_nb(0);
|
||||
|
||||
uwsgi_log("[pty] connected.\n");
|
||||
|
||||
uwsgi_pty_setterm(0);
|
||||
|
||||
upty.queue = event_queue_init();
|
||||
event_queue_add_fd_read(upty.queue, upty.server_fd);
|
||||
event_queue_add_fd_read(upty.queue, 0);
|
||||
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
|
||||
if (ret <= 0) break;
|
||||
if (interesting_fd == 0) {
|
||||
ssize_t rlen = read(0, buf, 8192);
|
||||
if (rlen <= 0) break;
|
||||
if (write(upty.server_fd, buf, rlen) != rlen) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == upty.server_fd) {
|
||||
ssize_t rlen = read(upty.server_fd, buf, 8192);
|
||||
if (rlen <= 0) break;
|
||||
if (write(0, buf, rlen) != rlen) break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
// never here
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin pty_plugin = {
|
||||
.name = "pty",
|
||||
.options = uwsgi_pty_options,
|
||||
.init = uwsgi_pty_client,
|
||||
.post_fork = uwsgi_pty_init,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
NAME='pty'
|
||||
|
||||
import os
|
||||
uwsgi_os = os.uname()[0]
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
if uwsgi_os in ('Linux', 'FreeBSD'):
|
||||
LIBS = ['-lutil']
|
||||
else:
|
||||
LIBS = []
|
||||
GCC_LIST = ['pty']
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user