mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38682590e9 | ||
|
|
aa2a212be8 | ||
|
|
51714203a7 | ||
|
|
fbac57a903 | ||
|
|
768d1c4099 | ||
|
|
82fa510030 | ||
|
|
a6e6bff082 | ||
|
|
304f847dc6 | ||
|
|
5bb7f02921 | ||
|
|
02ee60c6ef | ||
|
|
4d3526a377 | ||
|
|
ca9d1830bb | ||
|
|
4ff485d565 | ||
|
|
63d5c6afc9 | ||
|
|
3a36551d1f | ||
|
|
26877e1da9 | ||
|
|
d81330c514 | ||
|
|
441013b71b | ||
|
|
a6b9e653a4 | ||
|
|
c7161139e7 | ||
|
|
ce07c1a454 | ||
|
|
4eb3b76c35 | ||
|
|
3519fcbcc6 | ||
|
|
70dd9fca32 | ||
|
|
a573602171 | ||
|
|
29418654d7 | ||
|
|
31c31c4ce2 | ||
|
|
0217766dd1 | ||
|
|
3d15660407 | ||
|
|
57ce416ae1 | ||
|
|
248a22b064 | ||
|
|
49c5206d86 | ||
|
|
5b17363b40 | ||
|
|
e6c3c04e64 | ||
|
|
9a36b2b891 | ||
|
|
bfd699dac5 | ||
|
|
cc3e43eb3d | ||
|
|
b934ac9588 | ||
|
|
92b6c62cac | ||
|
|
46cceb0465 | ||
|
|
f1b3522c2a | ||
|
|
c99f5d0875 | ||
|
|
b972c2d6bb | ||
|
|
d226f65890 | ||
|
|
60b54c4d7c | ||
|
|
ace79b1179 | ||
|
|
9993e3710c | ||
|
|
98541dbc65 | ||
|
|
cabb6d72d9 | ||
|
|
217f2f99ff | ||
|
|
890e0004b6 | ||
|
|
d17d947cd1 | ||
|
|
a69c775cd5 | ||
|
|
4c051d90ed | ||
|
|
f55c52eaff | ||
|
|
88b5f968a4 | ||
|
|
6fdeecce0f | ||
|
|
f6923728d8 | ||
|
|
cf96783dce | ||
|
|
e4d3d209c8 | ||
|
|
5182eaf485 | ||
|
|
082d47e156 | ||
|
|
0715031b00 | ||
|
|
27c3532617 | ||
|
|
cb1370b148 | ||
|
|
9cc58a3c13 | ||
|
|
150f0c631e | ||
|
|
0574a120bc | ||
|
|
c6550ece68 | ||
|
|
e76a40530b | ||
|
|
31c73ce298 | ||
|
|
b304766718 | ||
|
|
0ab1cfacc9 | ||
|
|
b1f06bce32 | ||
|
|
347ef1a5bf | ||
|
|
b4d9eb4f73 | ||
|
|
f44a36900a | ||
|
|
b6c969254d | ||
|
|
c5003561dd | ||
|
|
18dead4cd2 | ||
|
|
62aee259fa | ||
|
|
69c49f713e | ||
|
|
08525a91ee | ||
|
|
40fee74a5f | ||
|
|
6d8f179863 | ||
|
|
d0b3c442c1 | ||
|
|
de82b58952 | ||
|
|
eb33fa7b19 | ||
|
|
9dde5f9d82 | ||
|
|
036df0e5ff | ||
|
|
1154aa8ddc | ||
|
|
3371dd2f94 | ||
|
|
06791376af | ||
|
|
30e0af3826 | ||
|
|
e4903ee0bf | ||
|
|
859c386b40 | ||
|
|
b83fecf4d3 | ||
|
|
25dc608fa3 | ||
|
|
c01cf1f6be | ||
|
|
9825f95ed5 | ||
|
|
36143381e1 | ||
|
|
8c25bafc73 | ||
|
|
826f49c010 | ||
|
|
8b006c0874 | ||
|
|
5806c333f5 | ||
|
|
e606d1e5d1 | ||
|
|
ec954b8aa7 | ||
|
|
95d20e9f48 | ||
|
|
165aad8cd0 | ||
|
|
29c339a3c3 | ||
|
|
12afba035b | ||
|
|
eeb203afd4 | ||
|
|
2ccdd0fb67 | ||
|
|
6a18d10c56 | ||
|
|
d1383d7749 | ||
|
|
0abbabbe10 | ||
|
|
ea44525c22 | ||
|
|
2396c7cf31 | ||
|
|
4805a9c219 | ||
|
|
882cdcc2b6 | ||
|
|
59c8bb51b4 | ||
|
|
3c2350f5ad | ||
|
|
422e958fe3 | ||
|
|
4d9c7809d6 | ||
|
|
6b3d8ea146 | ||
|
|
b5d8538fe8 | ||
|
|
47796b315e | ||
|
|
222bcd8fdc | ||
|
|
f92b800a7c | ||
|
|
dec2b234f8 | ||
|
|
3dbd7e3115 | ||
|
|
09d8747918 | ||
|
|
fa78fd915b | ||
|
|
db56141485 | ||
|
|
7685af4652 | ||
|
|
21cb62db6c | ||
|
|
c62aa8e7ed | ||
|
|
4765965d8e | ||
|
|
556feaef2c | ||
|
|
799b8a22e0 | ||
|
|
2336580164 | ||
|
|
ca4f30c003 | ||
|
|
d7d0a71d87 | ||
|
|
44b92f1578 | ||
|
|
abed95362f | ||
|
|
72ecc217f7 | ||
|
|
1405d01d50 | ||
|
|
def65c4793 | ||
|
|
26386909de | ||
|
|
2d4e04059a | ||
|
|
ac557739c2 | ||
|
|
73bfc20ba1 | ||
|
|
6d5ae96d50 | ||
|
|
20b5b7b0dc | ||
|
|
82c5afd0c7 | ||
|
|
ec14f5b0fe | ||
|
|
d93bdcb7b4 | ||
|
|
b68ffc842d | ||
|
|
0326c1d508 | ||
|
|
42f45bfbf9 | ||
|
|
d018d3af99 | ||
|
|
42afc476d7 | ||
|
|
b5037d3f0f | ||
|
|
065dd7cfff | ||
|
|
7909e092b5 | ||
|
|
9da53f5fd4 | ||
|
|
025cb7744e | ||
|
|
e48a3ff1b7 | ||
|
|
2be371003c | ||
|
|
60d940e301 | ||
|
|
96c56cd8d5 | ||
|
|
4184619f7b | ||
|
|
50a8ec8a19 | ||
|
|
79c702278a | ||
|
|
8fc41a4c85 | ||
|
|
9c6455252d | ||
|
|
83e41844f3 | ||
|
|
2cc17d6b11 | ||
|
|
14057b72c8 | ||
|
|
faf72b6a77 | ||
|
|
963afa5174 | ||
|
|
ce8ff8c45f | ||
|
|
5ae742e8e1 | ||
|
|
60f6572985 | ||
|
|
4ea34c63d2 | ||
|
|
5699d21aa7 | ||
|
|
dda8d25495 | ||
|
|
d4f690322c | ||
|
|
4f2f30d1e5 | ||
|
|
d3b28e7956 | ||
|
|
ab4afdbeaa | ||
|
|
54e2d698cb | ||
|
|
8b0565c0b8 | ||
|
|
102d6f25ed | ||
|
|
d0a53aa976 | ||
|
|
f8cf808e47 | ||
|
|
f8bbd2177e | ||
|
|
f44c145941 | ||
|
|
f34ac9f6aa | ||
|
|
b971230fd9 | ||
|
|
5c6340caac | ||
|
|
c0b97b47d3 | ||
|
|
a6b7f6e5bb | ||
|
|
1b99f9a750 | ||
|
|
a434195318 | ||
|
|
a6a8faea78 | ||
|
|
31458320ab | ||
|
|
037a1f7f77 | ||
|
|
10d4d10ac9 | ||
|
|
00e8d509f8 | ||
|
|
c9ca14df4d | ||
|
|
841cdfc62d | ||
|
|
fc7026c076 | ||
|
|
b96581c183 | ||
|
|
4fa5d72af6 | ||
|
|
f4be581666 | ||
|
|
24fb5518d8 | ||
|
|
2e8061d62a | ||
|
|
23d70f6936 | ||
|
|
95ea88628a | ||
|
|
68b411f487 | ||
|
|
40bfbc0a44 | ||
|
|
fc9b6ea275 | ||
|
|
522f3bb3a1 | ||
|
|
743c7ceaa6 | ||
|
|
c780cd47ce | ||
|
|
54e7e01c05 | ||
|
|
7d422d11e4 | ||
|
|
5c35b60d1d | ||
|
|
94353efb3f | ||
|
|
0586a2ba47 | ||
|
|
be6081c6f7 | ||
|
|
955fb6479e | ||
|
|
1b334e8cf7 | ||
|
|
718e198ac8 | ||
|
|
3757e5a8bb | ||
|
|
d505964321 | ||
|
|
1114c1a429 | ||
|
|
f58a9c6119 | ||
|
|
e791cb2c00 | ||
|
|
f741dbb01b | ||
|
|
d5f0741e8d | ||
|
|
b265ed8313 | ||
|
|
6cb160bb26 | ||
|
|
009a3f2c0d | ||
|
|
11b3d1fb94 | ||
|
|
7a39472700 | ||
|
|
4489b48603 | ||
|
|
d2f69af964 | ||
|
|
34e9dabffc | ||
|
|
6a4f46639e | ||
|
|
0d07ff25f9 | ||
|
|
c1d9c4ef12 | ||
|
|
0227ff7a9b | ||
|
|
082b178ae3 | ||
|
|
0e695cbd6e | ||
|
|
be2ed4dc4a | ||
|
|
4777666588 | ||
|
|
5647057ecc | ||
|
|
94cb950058 | ||
|
|
8d65371bf6 | ||
|
|
c747a36ae1 | ||
|
|
e51cb65857 | ||
|
|
8fa4fdb8c8 | ||
|
|
d584857c78 | ||
|
|
f0b1d79f8b | ||
|
|
28566ad772 | ||
|
|
40c0e139d4 | ||
|
|
04f2444ea0 | ||
|
|
9f71d28afa | ||
|
|
af262fb325 | ||
|
|
243657b5aa | ||
|
|
032302edaa | ||
|
|
d4bd658d84 | ||
|
|
78843c3e06 | ||
|
|
692ba1f6b3 | ||
|
|
400a9d72ef | ||
|
|
11f8f0385a | ||
|
|
c40d15981c | ||
|
|
baa1bf21f1 | ||
|
|
3dd3122236 | ||
|
|
927ef2ccde | ||
|
|
af6eaf6737 | ||
|
|
7c543f5627 | ||
|
|
b06e35c610 | ||
|
|
842c2148d7 | ||
|
|
a2a94bd78e | ||
|
|
4452c30fc8 | ||
|
|
f462792c8e | ||
|
|
03879fdc0c | ||
|
|
389d0b95d5 | ||
|
|
6ec32e192f | ||
|
|
22c034cdca | ||
|
|
396d8c3022 | ||
|
|
a535ecbe17 | ||
|
|
fd436c3e4f | ||
|
|
e5c245ea2f | ||
|
|
3008b7c83b | ||
|
|
eca6cd3066 | ||
|
|
691a41f290 | ||
|
|
df4cf539a1 | ||
|
|
baa1167dfe | ||
|
|
d8a83ab7cf | ||
|
|
8184351b3b | ||
|
|
4a4dbbcf69 | ||
|
|
56f79efc74 | ||
|
|
ea073a9bbd | ||
|
|
c5b2ca4b20 | ||
|
|
c0f9d8d2ff | ||
|
|
497660279f | ||
|
|
625395bd26 | ||
|
|
79a7797409 | ||
|
|
3b13de3e6e | ||
|
|
7f99855527 | ||
|
|
8c29178f81 | ||
|
|
ed71000033 | ||
|
|
20860ed069 | ||
|
|
2e62f13917 | ||
|
|
1b2a83ce70 | ||
|
|
113ec5ae9e | ||
|
|
68e81828d1 | ||
|
|
543790dc83 | ||
|
|
be24060578 | ||
|
|
bdedc1c94c | ||
|
|
e2454aa898 | ||
|
|
dfa4834be3 | ||
|
|
f204249110 | ||
|
|
f4c25a6cd1 | ||
|
|
fbfbacce14 | ||
|
|
a0eed32b3f | ||
|
|
9fe9fe1bb6 | ||
|
|
192312e3ea | ||
|
|
ee46fe6ba6 | ||
|
|
58abd07a88 | ||
|
|
c246a6008e | ||
|
|
706f1b59c3 | ||
|
|
ddbc8920f7 | ||
|
|
7e3bf6868e | ||
|
|
4c7ecef577 | ||
|
|
e3da0aaad4 | ||
|
|
99e576e40c | ||
|
|
7604ce3441 | ||
|
|
a0082b5b98 | ||
|
|
c90c639348 | ||
|
|
2e188dc25a | ||
|
|
312d21cb3f | ||
|
|
4ee138be7c | ||
|
|
299aef99b3 | ||
|
|
06953e4547 | ||
|
|
7565ee8740 | ||
|
|
10377f02a3 | ||
|
|
a41e6e2c61 | ||
|
|
6b2b909d33 | ||
|
|
70cd18bffb | ||
|
|
d6be4bcad9 | ||
|
|
85530b5d8e | ||
|
|
e3848e84d3 | ||
|
|
4ec9312b10 | ||
|
|
aedf3b2455 | ||
|
|
2210ec7f71 | ||
|
|
a9bee41707 | ||
|
|
3adbfd100f | ||
|
|
8d8de4b8da | ||
|
|
099403d554 | ||
|
|
13938a6aa7 | ||
|
|
9be3a4aaf8 | ||
|
|
009e42f349 | ||
|
|
207dd3bc77 | ||
|
|
feec6b3151 | ||
|
|
bf8207f0f1 | ||
|
|
9fcbc6ee68 | ||
|
|
dcb58aaa34 | ||
|
|
7163d8ddd4 | ||
|
|
c7b24eec45 | ||
|
|
1e7098f787 | ||
|
|
b28f0d9863 | ||
|
|
b49c4f4af9 | ||
|
|
2c39aafb0b | ||
|
|
1036d9c18b | ||
|
|
f0c8cbf190 | ||
|
|
f51db4481b | ||
|
|
717eba7ab3 | ||
|
|
3cc971ba55 | ||
|
|
23b3d7483f | ||
|
|
ba03837e29 | ||
|
|
06952fbaff | ||
|
|
27be00b4cc | ||
|
|
b50a377190 | ||
|
|
1ed9cb0bec | ||
|
|
a548ede3c7 | ||
|
|
de26c09030 | ||
|
|
19aa7c2560 | ||
|
|
215e0c4cbc | ||
|
|
d484acefa4 | ||
|
|
4032efd3e8 | ||
|
|
f9d412bcca | ||
|
|
5f52063b9e | ||
|
|
87833abb42 | ||
|
|
0fcbd5e334 | ||
|
|
5b55bf5f5c | ||
|
|
b8cc1d962f | ||
|
|
762c73e2ac | ||
|
|
57cd0e9135 | ||
|
|
5e0a85bff0 | ||
|
|
d2eaef524c | ||
|
|
a98c5a3931 | ||
|
|
040da07323 | ||
|
|
34f43ec97b | ||
|
|
7e3cfe94d6 | ||
|
|
e2c3b650a1 | ||
|
|
404dfaeda7 | ||
|
|
a1ec530945 | ||
|
|
b8dfd617f2 | ||
|
|
f34ed4dc47 | ||
|
|
cd2ff0e585 | ||
|
|
449955562f | ||
|
|
41a4bbccfc | ||
|
|
87b17c001d | ||
|
|
67b7753814 | ||
|
|
b190744b77 | ||
|
|
4b603071d8 | ||
|
|
16c55f0217 | ||
|
|
c989f2fb33 | ||
|
|
6429a47b0d | ||
|
|
f8a48a3ae9 | ||
|
|
fb3272d165 | ||
|
|
be5f67906e | ||
|
|
f730023e88 | ||
|
|
50954d34db | ||
|
|
ef2d9e781f | ||
|
|
a9bb310a20 | ||
|
|
86f37556da | ||
|
|
a57617c09a | ||
|
|
63ac62cf1d | ||
|
|
ac371730fd | ||
|
|
4ed6588c80 | ||
|
|
81d20edc4c | ||
|
|
a9fc6adccf | ||
|
|
21ad94ba4e | ||
|
|
571b9f27e1 | ||
|
|
cbf9ccf062 | ||
|
|
dd8fd8f19c | ||
|
|
1535b8ee13 | ||
|
|
f2491536dd | ||
|
|
88ce0181b3 | ||
|
|
4ad2658090 | ||
|
|
8d80c5e84d | ||
|
|
bae9235103 | ||
|
|
8ae2d0d00c | ||
|
|
373b89e70c | ||
|
|
c14e18b270 | ||
|
|
68ec3afd1a | ||
|
|
8918e81256 | ||
|
|
469fd697cb | ||
|
|
20844ebfca | ||
|
|
38652076d3 | ||
|
|
f13ae47fc0 | ||
|
|
ad4ee9d5c3 | ||
|
|
03a4e900ea | ||
|
|
b52dbf2aa0 | ||
|
|
c7a22c3b53 | ||
|
|
775aae3f1e | ||
|
|
862731ba91 | ||
|
|
8c302eee51 | ||
|
|
b6d34067c4 | ||
|
|
dbe15195b7 | ||
|
|
5642aa1eb5 | ||
|
|
5dd465ccc1 | ||
|
|
ae78c3007e | ||
|
|
16211d9439 | ||
|
|
515619fe2a | ||
|
|
a7d550165d | ||
|
|
efceacd9e5 | ||
|
|
ea5ebc2d15 | ||
|
|
fba82c203c | ||
|
|
a50516af7a | ||
|
|
6056b51653 | ||
|
|
23a3170c59 | ||
|
|
e136128408 | ||
|
|
fce94e0f54 | ||
|
|
06fa65bc5d | ||
|
|
571ec5ca72 | ||
|
|
39bc0ecd46 | ||
|
|
7a5373360c | ||
|
|
15453ffef6 | ||
|
|
a25747a096 | ||
|
|
bb1ef59b52 | ||
|
|
6bb3af840d | ||
|
|
0223c74ecc | ||
|
|
c7004d7ba4 | ||
|
|
915d2e9192 | ||
|
|
df79b9367b | ||
|
|
ce3d026037 | ||
|
|
d0f6c4130b | ||
|
|
26bcf28182 | ||
|
|
272d1ccc03 | ||
|
|
6c440af24e | ||
|
|
8954520cb9 | ||
|
|
31bde74fab | ||
|
|
13c64a383c | ||
|
|
809028f11b | ||
|
|
dee9d2ba1e | ||
|
|
29d80ce061 | ||
|
|
abcd3242d8 | ||
|
|
f4762299f9 | ||
|
|
107f4309a4 | ||
|
|
d2a8df19ea | ||
|
|
29efd15534 | ||
|
|
e7fb216a8d | ||
|
|
952b96cdcb | ||
|
|
8ee82fc296 | ||
|
|
afe2bfb856 | ||
|
|
5b63e9aea0 | ||
|
|
91f70259e2 | ||
|
|
f120cacc03 | ||
|
|
aff1d782b8 | ||
|
|
b489fd8a24 | ||
|
|
47e0eb68c2 | ||
|
|
9498e25245 | ||
|
|
a33e18b589 | ||
|
|
f2dcdf2289 | ||
|
|
74c53e8a61 | ||
|
|
1feed87c10 | ||
|
|
f89742d81a | ||
|
|
340b9d603e | ||
|
|
1c0fc64243 | ||
|
|
1d5173d923 | ||
|
|
49a8bf0b9b | ||
|
|
0a7e5a41a2 | ||
|
|
43ff563429 | ||
|
|
2daf6f1f66 | ||
|
|
985f56768f | ||
|
|
35278588f5 | ||
|
|
f6545be647 | ||
|
|
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 | ||
|
|
9cbdfc7764 | ||
|
|
cb1423436f | ||
|
|
2fb391795a | ||
|
|
9ec20f2d8f | ||
|
|
9323ca5136 | ||
|
|
978e6072ab | ||
|
|
d0e3869d54 | ||
|
|
15c7e956f2 | ||
|
|
ed61545ec7 | ||
|
|
1aac5becdc | ||
|
|
4bca26debc | ||
|
|
d6eecd1637 | ||
|
|
00e7620d2e | ||
|
|
d657283aad | ||
|
|
70a879ea94 | ||
|
|
591ee22472 | ||
|
|
956b05d39d | ||
|
|
5bdad6d4cb | ||
|
|
29a6ac6ed7 | ||
|
|
8f7f091e9b | ||
|
|
63dfe7628b | ||
|
|
ce507e7851 | ||
|
|
a9cd76173e | ||
|
|
44f8ffb434 | ||
|
|
28c395f111 | ||
|
|
39df68c38e | ||
|
|
b33ca9225a | ||
|
|
bd137afecf | ||
|
|
a3b9bed8c2 | ||
|
|
0a157739bc | ||
|
|
c46b08ad5e | ||
|
|
754e6193a4 | ||
|
|
56b49fe2dd | ||
|
|
36a7215f94 | ||
|
|
702247affd | ||
|
|
e752b1f8e5 | ||
|
|
920eee36e3 | ||
|
|
a5070a5d98 | ||
|
|
ccb5aefa61 | ||
|
|
378b08e37c | ||
|
|
5763483c91 | ||
|
|
559f8ee095 | ||
|
|
4382ef360c | ||
|
|
0cb576cf1a | ||
|
|
dee4d047b4 | ||
|
|
2520cc7bb9 | ||
|
|
192c31efe0 | ||
|
|
a1d8ebc2d2 | ||
|
|
14a9de2147 | ||
|
|
a760a9a3f1 | ||
|
|
efd14e1c7a | ||
|
|
6019c46cee | ||
|
|
ec6acfbc1c | ||
|
|
e925dbaad6 | ||
|
|
8321adf0bc | ||
|
|
e1c5e9e874 | ||
|
|
0aec581714 | ||
|
|
b77b8623d1 | ||
|
|
5ab986d6d9 | ||
|
|
09b8332236 | ||
|
|
d05345abc0 | ||
|
|
804c369f0d | ||
|
|
8f67fc886c | ||
|
|
ca3b1a9b30 | ||
|
|
63c1dbb3ed | ||
|
|
9a424dfe29 | ||
|
|
0a6eb596bb | ||
|
|
34452376db | ||
|
|
53a90a59c5 | ||
|
|
ec491ebd83 | ||
|
|
cdc41c305e | ||
|
|
6cf67b399c | ||
|
|
dc3c56bccc | ||
|
|
4657f2039a | ||
|
|
b0082fbd0d | ||
|
|
ede1b4df11 | ||
|
|
d78a3d1f8a | ||
|
|
6152555f26 | ||
|
|
bbad505044 | ||
|
|
11c5429184 | ||
|
|
4e865c4525 | ||
|
|
2fa785a539 | ||
|
|
296a8449c9 | ||
|
|
f20213ff10 | ||
|
|
8a7067ee24 | ||
|
|
a3024e9f5a | ||
|
|
86e651f5e7 | ||
|
|
409710b2b1 | ||
|
|
14a406a276 | ||
|
|
28a283b1c1 | ||
|
|
ccf298a148 | ||
|
|
914b600af4 | ||
|
|
4944994667 | ||
|
|
3a487578a5 | ||
|
|
39eeccb16a | ||
|
|
32acd3b9d1 | ||
|
|
c57baae477 | ||
|
|
4a6ed633b9 | ||
|
|
2ab1845547 | ||
|
|
f4d2e1f20c | ||
|
|
81dca1f690 | ||
|
|
2b331fd68f | ||
|
|
cc77e4dba7 | ||
|
|
620a13a308 | ||
|
|
42d4ba09d7 | ||
|
|
ca071fa52f | ||
|
|
d38e5dec7b | ||
|
|
e5db38f7c0 | ||
|
|
68a29730c0 | ||
|
|
5c33c4d341 | ||
|
|
a1d6270089 | ||
|
|
1968175b00 | ||
|
|
cf1e2aeeba | ||
|
|
199b0b9f57 | ||
|
|
87a0daa465 | ||
|
|
c2af90b58f | ||
|
|
62f01453af | ||
|
|
375d6ee331 | ||
|
|
222ca2915b | ||
|
|
5ca848f9fe | ||
|
|
68d878ff6b | ||
|
|
782a7b418a | ||
|
|
724d7854ad | ||
|
|
f8e64d17e8 | ||
|
|
3b40799000 | ||
|
|
709964ca92 | ||
|
|
d2cdedc610 | ||
|
|
b7d0730343 | ||
|
|
30b4ea7d49 | ||
|
|
546dadbd06 | ||
|
|
76edf902de | ||
|
|
7c4caef5e7 | ||
|
|
068024134c | ||
|
|
538ab57b6e | ||
|
|
fd6d9148f3 | ||
|
|
f033f59755 | ||
|
|
7168c6dd69 | ||
|
|
f121d41c2f | ||
|
|
e56e774eac | ||
|
|
6d9b0918a3 | ||
|
|
d445418611 | ||
|
|
6d15a51c9a | ||
|
|
42a615efdd | ||
|
|
54cd1f79a6 | ||
|
|
8ed8f46374 | ||
|
|
dd3a2996a4 | ||
|
|
bf1f90a96a | ||
|
|
2d6200231a | ||
|
|
032cd23304 | ||
|
|
de4c0a9e1c | ||
|
|
e33f8e8920 | ||
|
|
22615c7921 | ||
|
|
9d8809c580 | ||
|
|
96b92c98ff | ||
|
|
07939acecd | ||
|
|
30abcb2563 | ||
|
|
35ce8f2b8d | ||
|
|
d6453eab38 | ||
|
|
e0964d07ea | ||
|
|
fc359f1956 | ||
|
|
322261d65d | ||
|
|
bd1163c439 | ||
|
|
e203a8c706 | ||
|
|
6a1ba2af74 | ||
|
|
22569e64df | ||
|
|
dcafe41cde | ||
|
|
dd2adc08a3 | ||
|
|
d7534d2673 | ||
|
|
0a59920025 | ||
|
|
77602a8de4 | ||
|
|
65b3fde97c | ||
|
|
b690148452 | ||
|
|
4c7bc9ada6 | ||
|
|
432651489f | ||
|
|
82aa232a37 | ||
|
|
19b13bf7a7 | ||
|
|
f7e25d807d | ||
|
|
cf05316b95 | ||
|
|
001c4386b5 | ||
|
|
572527f8cb | ||
|
|
b4252beda6 | ||
|
|
edbff83fd6 |
@@ -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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
----------------------------------------------------------------------
|
||||
|
||||
LINKING EXCEPTION
|
||||
|
||||
In addition to the permissions in the GNU General Public License,
|
||||
the authors give you unlimited permission to link the compiled
|
||||
version of this library into combinations with other programs,
|
||||
and to distribute those combinations without any restriction
|
||||
coming from the use of this file. (The General Public License
|
||||
restrictions do apply in other respects; for example, they cover
|
||||
modification of the file, and distribution when not linked into
|
||||
a combined executable.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
PYTHON := python
|
||||
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
$(PYTHON) uwsgiconfig.py --clean
|
||||
|
||||
check:
|
||||
python uwsgiconfig.py --check
|
||||
$(PYTHON) uwsgiconfig.py --check
|
||||
|
||||
plugin.%:
|
||||
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
|
||||
|
||||
%:
|
||||
$(PYTHON) uwsgiconfig.py --build $@
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
surprise i am empty !
|
||||
The uWSGI project
|
||||
|
||||
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
|
||||
For commercial support check: http://unbit.com/
|
||||
|
||||
@@ -7,7 +7,7 @@ filename = sys.argv[1]
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
os.write(1, f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
os.write(1, (struct.pack("<Q", size)))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -48,9 +48,6 @@ static int uwsgi_go_init() {
|
||||
|
||||
uwsgi_log("Go version \"%s\" initialized\n", uwsgi_go_helper_version_c());
|
||||
|
||||
// call PostInit()
|
||||
uwsgi_go_helper_post_init_c();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,9 +77,7 @@ static int uwsgi_go_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
static void uwsgi_go_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
log_request(wsgi_req);
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_go_signal_handler(uint8_t signum, void *handler) {
|
||||
@@ -101,11 +96,18 @@ static void uwsgi_go_on_load() {
|
||||
uwsgi_register_loop("goroutines", goroutines_loop);
|
||||
}
|
||||
|
||||
static void uwsgi_go_call_init_hook() {
|
||||
if (uwsgi_go_helper_post_init_c) {
|
||||
uwsgi_go_helper_post_init_c();
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin go_plugin = {
|
||||
.name = "go",
|
||||
.modifier1 = 11,
|
||||
.request = uwsgi_go_request,
|
||||
.after_request = uwsgi_go_after_request,
|
||||
.preinit_apps = uwsgi_go_call_init_hook,
|
||||
.post_fork = uwsgi_go_post_fork,
|
||||
.init = uwsgi_go_init,
|
||||
.signal_handler = uwsgi_go_signal_handler,
|
||||
@@ -150,7 +150,7 @@ func CacheGet(key string, cache string) []byte {
|
||||
|
||||
var p []byte
|
||||
|
||||
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, c)
|
||||
c_value := C.uwsgi_cache_magic_get(k, C.uint16_t(kl), &vl, (*C.uint64_t)(nil), c)
|
||||
|
||||
if c_value != nil {
|
||||
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
|
||||
@@ -411,10 +411,10 @@ func uwsgi_go_helper_run_core(core_id int) {
|
||||
the main function, running the uWSGI server via libuwsgi.so
|
||||
*/
|
||||
func Run() {
|
||||
argc := len(os.Args)
|
||||
argc := len(os.Args) + 1
|
||||
argv := C.uwsgi_go_helper_create_argv(C.int(argc))
|
||||
for i, s := range os.Args {
|
||||
C.uwsgi_go_helper_set_argv(argv, C.int(i), C.CString(s))
|
||||
}
|
||||
C.uwsgi_init(C.int(argc), argv, nil)
|
||||
C.uwsgi_init(C.int(argc-1), argv, nil)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy
|
||||
inherit = base
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
xml = auto
|
||||
yaml = true
|
||||
json = auto
|
||||
zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
@@ -16,7 +15,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
|
||||
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, router_metrics, transformation_template, stats_pusher_socket
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi,coroae
|
||||
inherit = base
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
# pypy,jvm,ring,jwsgi
|
||||
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
|
||||
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
|
||||
inherit = base
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gccgo
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
@@ -1,5 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -0,0 +1,31 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
yaml = false
|
||||
json = false
|
||||
ssl = false
|
||||
pcre = false
|
||||
routing = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = none
|
||||
yaml_implementation = none
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin =
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi
|
||||
inherit = minimal
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = pypy
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rados
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack,rbthreads,fiber
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = jvm,servlet
|
||||
inherit = base
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = false
|
||||
zeromq = false
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = v8
|
||||
inherit = base
|
||||
@@ -1 +0,0 @@
|
||||
the uwsgi handler is included in the official Cherokee distribution
|
||||
@@ -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
|
||||
|
||||
|
||||
+141
-13
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
|
||||
uwsgi_route_signal(uai->data8);
|
||||
}
|
||||
|
||||
// simply log an alarm
|
||||
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
if (msg[len-1] != '\n') {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s\n", len, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s", len, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run a command on alarm
|
||||
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = uai->arg;
|
||||
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
|
||||
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
|
||||
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
|
||||
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
|
||||
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
|
||||
}
|
||||
|
||||
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
|
||||
@@ -160,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
|
||||
// map instances to the log
|
||||
char *list = uwsgi_str(alarms);
|
||||
char *p = strtok(list, ",");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) {
|
||||
free(list);
|
||||
@@ -181,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
else {
|
||||
ual->alarms = uall;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
@@ -189,21 +212,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
|
||||
// add uwsgi_alarm_fd;
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
event_queue_add_fd_read(ut->queue, uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
if (interesting_fd == ut->pipe[1]) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
}
|
||||
}
|
||||
// check for alarm_fd
|
||||
else {
|
||||
uafd = uwsgi.alarm_fds;
|
||||
int fd_read = 0;
|
||||
while(uafd) {
|
||||
if (interesting_fd == uafd->fd) {
|
||||
if (fd_read) goto raise;
|
||||
size_t remains = uafd->buf_len;
|
||||
while(remains) {
|
||||
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("[uwsgi-alarm-fd]/read()");
|
||||
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
|
||||
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
|
||||
break;
|
||||
}
|
||||
remains-=len;
|
||||
}
|
||||
fd_read = 1;
|
||||
raise:
|
||||
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
|
||||
}
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +299,37 @@ void uwsgi_alarms_init() {
|
||||
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
|
||||
// map alarm file descriptors
|
||||
usl = uwsgi.alarm_fd_list;
|
||||
while(usl) {
|
||||
char *space0 = strchr(usl->value, ' ');
|
||||
if (!space0) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space0 = 0;
|
||||
size_t buf_len = 1;
|
||||
char *space1 = strchr(space0+1, ' ');
|
||||
if (!space1) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *colon = strchr(space0+1, ':');
|
||||
if (colon) {
|
||||
buf_len = strtoul(colon+1, NULL, 10);
|
||||
*colon = 0;
|
||||
}
|
||||
int fd = atoi(space0+1);
|
||||
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
|
||||
*space0 = ' ';
|
||||
*space1 = ' ';
|
||||
if (colon) {
|
||||
*colon = ':';
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
@@ -340,3 +427,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
|
||||
if (!uai) {
|
||||
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!buf_len) buf_len = 1;
|
||||
|
||||
while(uafd) {
|
||||
// check if an equal alarm has been added
|
||||
if (uafd->fd == fd && uafd->alarm == uai) {
|
||||
return uafd;
|
||||
}
|
||||
old_uafd = uafd;
|
||||
uafd = uafd->next;
|
||||
}
|
||||
|
||||
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
|
||||
uafd->fd = fd;
|
||||
uafd->buf = uwsgi_malloc(buf_len);
|
||||
uafd->buf_len = buf_len;
|
||||
uafd->msg = msg;
|
||||
uafd->msg_len = msg_len;
|
||||
uafd->alarm = uai;
|
||||
|
||||
if (!old_uafd) {
|
||||
uwsgi.alarm_fds = uafd;
|
||||
}
|
||||
else {
|
||||
old_uafd->next = uafd;
|
||||
}
|
||||
|
||||
// avoid the fd to be closed
|
||||
uwsgi_add_safe_fd(fd);
|
||||
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
|
||||
|
||||
return uafd;
|
||||
}
|
||||
|
||||
+202
-112
@@ -2,6 +2,24 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general-purpose async loop engine (it expects a coroutine-based approach)
|
||||
|
||||
You can see it as an hub holding the following structures:
|
||||
|
||||
1) the runqueue, cores ready to be run are appended to this list
|
||||
|
||||
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
|
||||
|
||||
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
|
||||
|
||||
|
||||
IMPORTANT: this is not a callback-based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
// this is called whenever a new connection is ready, but there are no cores to handle it
|
||||
void uwsgi_async_queue_is_full(time_t now) {
|
||||
if (now > uwsgi.async_queue_is_full) {
|
||||
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
|
||||
@@ -10,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
|
||||
}
|
||||
|
||||
void uwsgi_async_init() {
|
||||
int i;
|
||||
|
||||
uwsgi.async_queue = event_queue_init();
|
||||
|
||||
@@ -22,13 +39,9 @@ void uwsgi_async_init() {
|
||||
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
// optimization, this array maps file descriptor to requests
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +65,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
if (u_request == uwsgi.async_runqueue) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
|
||||
@@ -61,33 +74,33 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
}
|
||||
|
||||
free(u_request);
|
||||
|
||||
uwsgi.async_runqueue_cnt--;
|
||||
}
|
||||
|
||||
static void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_async_request *uar;
|
||||
// do not push the same request in the runqueue
|
||||
struct uwsgi_async_request *uar = uwsgi.async_runqueue;
|
||||
while(uar) {
|
||||
if (uar->wsgi_req == wsgi_req) return;
|
||||
uar = uar->next;
|
||||
}
|
||||
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = NULL;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
|
||||
if (uwsgi.async_runqueue == NULL) {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
uwsgi.async_runqueue = uar;
|
||||
}
|
||||
else {
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
}
|
||||
|
||||
uwsgi.async_runqueue_cnt++;
|
||||
|
||||
if (uwsgi.async_runqueue_last) {
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
}
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
}
|
||||
|
||||
struct wsgi_request *find_first_available_wsgi_req() {
|
||||
@@ -103,11 +116,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
|
||||
return wsgi_req;
|
||||
}
|
||||
|
||||
void async_reset_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *uaf = wsgi_req->waiting_fds;
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
struct uwsgi_async_fd *current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
}
|
||||
|
||||
static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for (;;) {
|
||||
@@ -121,20 +151,9 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
uaf = wsgi_req->waiting_fds;
|
||||
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
// put th request in the runqueue
|
||||
// reset the request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
@@ -146,12 +165,17 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -179,7 +203,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;
|
||||
}
|
||||
@@ -193,8 +221,49 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
|
||||
// reset already registered fd
|
||||
async_reset_request(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wsgi_req->async_ready_fd) {
|
||||
*fd = wsgi_req->async_last_ready_fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -203,12 +272,17 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -238,6 +312,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;
|
||||
}
|
||||
@@ -252,7 +329,61 @@ static int async_wait_fd_write(int fd, int timeout) {
|
||||
}
|
||||
|
||||
void async_schedule_to_req(void) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
// a trick to avoid calling routes again
|
||||
uwsgi.wsgi_req->is_routing = 1;
|
||||
#endif
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
}
|
||||
return;
|
||||
|
||||
end:
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
}
|
||||
|
||||
void async_schedule_to_req_green(void) {
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
if (uwsgi.schedule_fix) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
end:
|
||||
#endif
|
||||
// re-set the global state
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
async_reset_request(wsgi_req);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
// re-set the global state (routing could have changed it)
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
|
||||
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
@@ -262,7 +393,6 @@ void async_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *tmp_uaf;
|
||||
int interesting_fd, i;
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
int timeout;
|
||||
@@ -271,16 +401,18 @@ void async_loop() {
|
||||
|
||||
uint64_t now;
|
||||
|
||||
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
|
||||
struct uwsgi_async_request *current_request = NULL;
|
||||
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi_async_init();
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
uwsgi.wait_read2_hook = async_wait_fd_read2;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
@@ -292,13 +424,13 @@ 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) {
|
||||
|
||||
now = (uint64_t) uwsgi_now();
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
if (uwsgi.async_runqueue) {
|
||||
timeout = 0;
|
||||
}
|
||||
else {
|
||||
@@ -328,16 +460,15 @@ void async_loop() {
|
||||
// manage events
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
// signals are executed in the main stack... in the future we could have dedicated stacks for them
|
||||
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
is_a_new_connection = 0;
|
||||
|
||||
// new request coming in ?
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
|
||||
@@ -351,6 +482,7 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// on error re-insert the request in the queue
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
@@ -364,6 +496,9 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// by default the core is in UWSGI_AGAIN mode
|
||||
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
|
||||
// some protocol (like zeromq) do not need additional parsing, just push it in the runqueue
|
||||
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
}
|
||||
@@ -380,21 +515,18 @@ void async_loop() {
|
||||
if (uwsgi.wsgi_req) {
|
||||
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
|
||||
// reset timeout
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
// put request in the runqueue
|
||||
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
continue;
|
||||
}
|
||||
else if (proto_parser_status < 0) {
|
||||
if (proto_parser_status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
continue;
|
||||
@@ -404,7 +536,7 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// app event
|
||||
// app-registered event
|
||||
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
|
||||
// unknown fd, remove it (for safety)
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
@@ -413,79 +545,37 @@ void async_loop() {
|
||||
}
|
||||
|
||||
// remove all the fd monitors and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_ready_fd = 1;
|
||||
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
|
||||
|
||||
// put the request in the runqueue again
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
// avoid managing other enqueued events...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// event queue managed, give cpu to runqueue
|
||||
if (!current_request)
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
// event queue managed, give cpu to runqueue
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
while(current_request) {
|
||||
|
||||
// current_request could be nulled on error/end of request
|
||||
struct uwsgi_async_request *next_request = current_request->next;
|
||||
|
||||
uwsgi.wsgi_req = current_request->wsgi_req;
|
||||
|
||||
uwsgi.schedule_to_req();
|
||||
uwsgi.wsgi_req->switches++;
|
||||
|
||||
next_async_request = current_request->next;
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
// remove all the monitored fds and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
// remove from the list
|
||||
runqueue_remove(current_request);
|
||||
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
|
||||
// push wsgi_request in the unused stack
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
|
||||
}
|
||||
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove this request from suspended list
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
|
||||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
current_request = next_async_request;
|
||||
|
||||
current_request = 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) {
|
||||
@@ -169,6 +172,16 @@ int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
|
||||
uint8_t buf[4];
|
||||
uint32_t *pnum = (uint32_t *) #
|
||||
buf[3] = (uint8_t) (*pnum & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
@@ -191,6 +204,33 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
uint8_t buf[8];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[3] = (uint8_t) ((num >> 24) & 0xff);
|
||||
buf[4] = (uint8_t) ((num >> 32) & 0xff);
|
||||
buf[5] = (uint8_t) ((num >> 40) & 0xff);
|
||||
buf[6] = (uint8_t) ((num >> 48) & 0xff);
|
||||
buf[7] = (uint8_t) ((num >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
|
||||
uint8_t buf[8];
|
||||
uint64_t *pnum = (uint64_t *) #
|
||||
buf[7] = (uint8_t) (*pnum & 0xff);
|
||||
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
@@ -270,6 +310,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);
|
||||
@@ -354,3 +401,11 @@ struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
|
||||
return ub;
|
||||
}
|
||||
|
||||
void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
if (ub->buf) {
|
||||
free(ub->buf);
|
||||
}
|
||||
ub->buf = buf;
|
||||
ub->pos = len;
|
||||
ub->len = len;
|
||||
}
|
||||
|
||||
+276
-32
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* how the cache bitmap works:
|
||||
|
||||
a bitmap is a shared mempry area allocated when requested by the user with --cache2
|
||||
a bitmap is a shared memory area allocated when requested by the user with --cache2
|
||||
|
||||
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
|
||||
the block is usable otherwise the block scanner will search for the next one.
|
||||
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
|
||||
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
|
||||
if (!uwsgi_strncmp(k, kl, "items", 5)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->max_items) {
|
||||
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->blocksize) {
|
||||
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
|
||||
exit(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,12 +230,52 @@ 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;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
usl = uwsgi.load_file_in_cache_gzip;
|
||||
while(usl) {
|
||||
size_t len = 0;
|
||||
char *value = NULL;
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next2;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
value = uwsgi_open_and_read(key, &len, 0, NULL);
|
||||
if (value) {
|
||||
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
|
||||
if (gzipped) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
|
||||
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_buffer_destroy(gzipped);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
next2:
|
||||
usl = usl->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
exit(1);
|
||||
}
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
|
||||
exit(1);
|
||||
}
|
||||
@@ -259,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
else {
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -301,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) {
|
||||
@@ -382,6 +460,67 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t uwsgi_cache_num2(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
|
||||
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 0;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
int64_t *num = (int64_t *) (uc->data + (uci->first_block * uc->blocksize));
|
||||
return *num;
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
|
||||
|
||||
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 (expires)
|
||||
*expires = uci->expires;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
|
||||
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) {
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
@@ -427,6 +566,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
|
||||
uci->expires = 0;
|
||||
|
||||
uc->n_items--;
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = uwsgi_now();
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
@@ -473,6 +616,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uint8_t rollback_mode = 0;
|
||||
|
||||
int ret = -1;
|
||||
time_t now = 0;
|
||||
|
||||
if (!keylen || !vallen)
|
||||
return -1;
|
||||
@@ -482,6 +626,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
|
||||
if (vallen > uc->max_item_size) return -1;
|
||||
|
||||
if ((flags & UWSGI_CACHE_FLAG_MATH) && vallen != 8) return -1;
|
||||
|
||||
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) {
|
||||
@@ -518,13 +664,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
}
|
||||
else if (rollback_mode == 2) {
|
||||
uc->first_available_block--;
|
||||
uc->first_available_block--;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -532,14 +678,42 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
|
||||
}
|
||||
}
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
|
||||
expires += uwsgi_now();
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
}
|
||||
uci->expires = expires;
|
||||
uci->hash = uc->hash->func(key, keylen);
|
||||
uci->hits = 0;
|
||||
uci->flags = flags;
|
||||
memcpy(uci->key, key, keylen);
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
// ok math operations here
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
*num = uc->math_initial;
|
||||
int64_t *delta = (int64_t *) val;
|
||||
if (flags & UWSGI_CACHE_FLAG_INC) {
|
||||
*num += *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DEC) {
|
||||
*num -= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_MUL) {
|
||||
*num *= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DIV) {
|
||||
if (*delta == 0) {
|
||||
*num = 0;
|
||||
}
|
||||
else {
|
||||
*num /= *delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set this as late as possibile (to reduce races risk)
|
||||
|
||||
@@ -571,8 +745,9 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = cache_item(index);
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
expires += uwsgi_now();
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE) && !(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
uci->expires = expires;
|
||||
}
|
||||
if (uc->blocks_bitmap) {
|
||||
@@ -587,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -597,11 +772,38 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
// unmark the old blocks
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
}
|
||||
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
int64_t *delta = (int64_t *) val;
|
||||
if (flags & UWSGI_CACHE_FLAG_INC) {
|
||||
*num += *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DEC) {
|
||||
*num -= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_MUL) {
|
||||
*num *= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DIV) {
|
||||
if (*delta == 0) {
|
||||
*num = 0;
|
||||
}
|
||||
else {
|
||||
*num /= *delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
uci->valsize = vallen;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = (now ? now : uwsgi_now());
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
|
||||
}
|
||||
@@ -879,6 +1081,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->nodes = uwsgi.cache_udp_node;
|
||||
uc->udp_servers = uwsgi.cache_udp_server;
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
|
||||
|
||||
if (uwsgi.cache_sync) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
|
||||
@@ -898,6 +1101,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
char *c_bitmap = NULL;
|
||||
char *c_use_last_modified = NULL;
|
||||
char *c_math_initial = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -923,6 +1128,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"udpservers", &c_udp_servers,
|
||||
"udpserver", &c_udp_servers,
|
||||
"bitmap", &c_bitmap,
|
||||
"lastmod", &c_use_last_modified,
|
||||
"math_initial", &c_math_initial,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -947,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");
|
||||
@@ -955,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);
|
||||
@@ -967,6 +1176,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->use_blocks_bitmap = 1;
|
||||
uc->max_item_size = uc->blocksize * uc->blocks;
|
||||
}
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
|
||||
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
|
||||
@@ -979,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->store = c_store;
|
||||
|
||||
if (c_nodes) {
|
||||
char *p = strtok(c_nodes, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_sync) {
|
||||
char *p = strtok(c_sync, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_sync, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_udp_servers) {
|
||||
char *p = strtok(c_udp_servers, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->udp_servers, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1223,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
// ok now wait for the response, using the same buffer of the request
|
||||
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
|
||||
// try to fix the buffer to maintain size info
|
||||
ub->pos = rlen;
|
||||
|
||||
@@ -1233,7 +1442,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
|
||||
struct uwsgi_cache_magic_context ucmc;
|
||||
struct uwsgi_cache *uc = NULL;
|
||||
char *cache_server = NULL;
|
||||
@@ -1258,7 +1467,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
// we have a local cache !!!
|
||||
if (uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
|
||||
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return NULL;
|
||||
@@ -1328,6 +1537,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
*vallen = ucmc.size;
|
||||
if (expires) {
|
||||
*expires = ucmc.expires;
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
@@ -1625,7 +1837,6 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
|
||||
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
@@ -1656,14 +1867,14 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, NULL)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
uwsgi_hooked_parse(ub->buf, rlen, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
@@ -1707,3 +1918,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() {}
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
|
||||
return poll(NULL, 0, timeout);
|
||||
}
|
||||
|
||||
|
||||
// in the future we will need to use the best clock source for each os/system
|
||||
time_t uwsgi_now() {
|
||||
return uwsgi.clock->seconds();
|
||||
|
||||
+768
@@ -31,3 +31,771 @@ 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, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int uwsgi_opt_exists(char *name) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) return 1;
|
||||
op++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
avoid loops here !!!
|
||||
*/
|
||||
struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
struct uwsgi_option *op;
|
||||
int round = 0;
|
||||
retry:
|
||||
round++;
|
||||
if (round > 2) goto end;
|
||||
op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) {
|
||||
return op;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
if (uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(name)) goto retry;
|
||||
}
|
||||
|
||||
end:
|
||||
if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
add_exported_option_do(key, value, configured, 0);
|
||||
}
|
||||
|
||||
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
|
||||
|
||||
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;
|
||||
|
||||
if (placeholder_only) {
|
||||
if (uwsgi_opt_exists(key)) {
|
||||
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// enable metrics ?
|
||||
if (op->flags & UWSGI_OPT_METRICS) {
|
||||
uwsgi.has_metrics = 1;
|
||||
}
|
||||
// immediate ?
|
||||
if (op->flags & UWSGI_OPT_IMMEDIATE) {
|
||||
op->func(key, value, op->data);
|
||||
uwsgi.exported_opts[id]->configured = 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
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_manage_opt(char *key, char *value) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
op->func(key, value, op->data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_configure() {
|
||||
|
||||
int i;
|
||||
|
||||
// and now apply the remaining configs
|
||||
restart:
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (uwsgi.exported_opts[i]->configured)
|
||||
continue;
|
||||
uwsgi.dirty_config = 0;
|
||||
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
|
||||
// some option could cause a dirty config tree
|
||||
if (uwsgi.dirty_config)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_custom(char *key, char *value, void *data ) {
|
||||
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
value_len = strlen(value);
|
||||
off_t pos = 0;
|
||||
char **opt_argv;
|
||||
char *tmp_val = NULL, *p = NULL;
|
||||
|
||||
// now count the number of args
|
||||
for (i = 0; i < value_len; i++) {
|
||||
if (value[i] == ' ') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate a tmp array
|
||||
opt_argv = uwsgi_calloc(sizeof(char *) * count);
|
||||
//make a copy of the value;
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no argument specified
|
||||
opt_argv[0] = "";
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found custom option %s with %d args\n", key, count);
|
||||
#endif
|
||||
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
*equal = '\0';
|
||||
|
||||
// build the key
|
||||
char *new_key = uwsgi_str(p);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_key = new_key;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
|
||||
if (new_key != old_key)
|
||||
free(old_key);
|
||||
free(placeholder);
|
||||
}
|
||||
|
||||
// build the value
|
||||
char *new_value = uwsgi_str(equal + 1);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_value = new_value;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
|
||||
if (new_value != old_value)
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
// ignore return value here
|
||||
uwsgi_manage_opt(new_key, new_value);
|
||||
}
|
||||
|
||||
clear:
|
||||
free(tmp_val);
|
||||
free(tmp_opt);
|
||||
free(opt_argv);
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_get_exported_opt(char *key) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
|
||||
return uwsgi.exported_opts[i]->value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_get_optname_by_index(int index) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (op->shortcut == index) {
|
||||
return op->name;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
this works as a pipeline
|
||||
|
||||
processes = 2
|
||||
cpu_cores = 8
|
||||
foobar = %(processes cpu_cores + 2)
|
||||
|
||||
translate as:
|
||||
|
||||
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
|
||||
|
||||
step1 + = step1_apply_func_plus (func token)
|
||||
|
||||
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_manage_placeholder(char *key) {
|
||||
enum {
|
||||
concat = 0,
|
||||
sum,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
} state;
|
||||
|
||||
state = concat;
|
||||
char *current_value = NULL;
|
||||
|
||||
char *space = strchr(key, ' ');
|
||||
if (!space) {
|
||||
return uwsgi_get_exported_opt(key);
|
||||
}
|
||||
// let's start the heavy metal here
|
||||
char *tmp_value = uwsgi_str(key);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
|
||||
char *value = NULL;
|
||||
if (is_a_number(p)) {
|
||||
value = uwsgi_str(p);
|
||||
}
|
||||
else if (!strcmp(p, "+")) {
|
||||
state = sum;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "-")) {
|
||||
state = sub;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "*")) {
|
||||
state = mul;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "/")) {
|
||||
state = div;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "++")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_num+1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "--")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_num-1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
// find the option
|
||||
else {
|
||||
char *ov = uwsgi_get_exported_opt(p);
|
||||
if (!ov) ov = "";
|
||||
value = uwsgi_str(ov);
|
||||
}
|
||||
|
||||
int64_t arg1n = 0, arg2n = 0;
|
||||
char *arg1 = "", *arg2 = "";
|
||||
|
||||
switch(state) {
|
||||
case concat:
|
||||
if (current_value) arg1 = current_value;
|
||||
if (value) arg2 = value;
|
||||
char *ret = uwsgi_concat2(arg1, arg2);
|
||||
if (current_value) free(current_value);
|
||||
current_value = ret;
|
||||
break;
|
||||
case sum:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n + arg2n);
|
||||
break;
|
||||
case sub:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n - arg2n);
|
||||
break;
|
||||
case mul:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n * arg2n);
|
||||
break;
|
||||
case div:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
// avoid division by zero
|
||||
if (arg2n == 0) {
|
||||
current_value = uwsgi_64bit2str(0);
|
||||
}
|
||||
else {
|
||||
current_value = uwsgi_64bit2str(arg1n / arg2n);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// over engineering
|
||||
if (value)
|
||||
free(value);
|
||||
|
||||
// reset state to concat
|
||||
state = concat;
|
||||
}
|
||||
free(tmp_value);
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
|
||||
int i;
|
||||
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));
|
||||
|
||||
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
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, ' ');
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job >= 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// check for legion cron
|
||||
if (current_cron->legion) {
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
|
||||
goto next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 ?
|
||||
if (now - current_cron->last_job >= 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (current_cron->func) {
|
||||
current_cron->func(current_cron, now);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+140
-33
@@ -1,4 +1,4 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
External uwsgi daemons
|
||||
|
||||
There are 3 kind of daemons (read: external applications) that can be managed
|
||||
There are 3 kinds of daemons (read: external applications) that can be managed
|
||||
by uWSGI.
|
||||
|
||||
1) dumb daemons (attached with --attach-daemon)
|
||||
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
|
||||
and the process is respawned
|
||||
2) smart daemons with daemonization
|
||||
you specify a pidfile and a command
|
||||
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
|
||||
the daemon is respawned
|
||||
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master check - if the pidfile does not exist or if it points to a non-existent pid
|
||||
the daemon is respawned
|
||||
3) smart daemons without daemonization
|
||||
same as 2, but the daemonization and pidfile creation is managed by uWSGI
|
||||
same as 2, but the daemonization and pidfile creation are managed by uWSGI
|
||||
|
||||
status:
|
||||
|
||||
@@ -42,6 +42,31 @@ void uwsgi_daemons_smart_check() {
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion) {
|
||||
if (uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// lord, spawn if not running
|
||||
if (ud->pid <= 0) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// not lord, kill daemon if running
|
||||
if (ud->pid > 0) {
|
||||
if (!kill(ud->pid, 0)) {
|
||||
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
|
||||
kill(-ud->pid, SIGTERM);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
ud->pid = -1;
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -52,8 +77,14 @@ void uwsgi_daemons_smart_check() {
|
||||
else {
|
||||
ud->pidfile_checks++;
|
||||
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
if (!ud->has_daemonized) {
|
||||
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
|
||||
ud->pidfile_checks = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,13 +101,24 @@ void uwsgi_daemons_smart_check() {
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a dumb daemon dies and we do not wat to respawn it
|
||||
// this function is called when a dumb daemon dies and we do not want to respawn it
|
||||
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
return -1;
|
||||
if (ud->pid == diedpid) {
|
||||
if (!ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!ud->has_daemonized) {
|
||||
ud->has_daemonized = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -87,7 +129,20 @@ int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->pid == diedpid && ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion but not lord, don't respawn
|
||||
ud->pid = -1;
|
||||
uwsgi_log("uwsgi-daemons] legion \"%s\" daemon \"%s\" (pid: %d) annihilated\n", ud->legion, ud->command, (int) diedpid);
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
if (ud->control) {
|
||||
gracefully_kill_them_all(0);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
}
|
||||
@@ -133,6 +188,20 @@ void uwsgi_daemons_spawn_all() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (!ud->registered) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion, register but don't spawn it yet
|
||||
if (ud->pidfile) {
|
||||
ud->pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (ud->pid > 0)
|
||||
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
|
||||
}
|
||||
ud->registered = 1;
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ud->registered = 1;
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -146,7 +215,6 @@ void uwsgi_daemons_spawn_all() {
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -156,8 +224,31 @@ void uwsgi_daemons_spawn_all() {
|
||||
void uwsgi_detach_daemons() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && !ud->pidfile)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
#ifdef UWSGI_SSL
|
||||
// stop any legion daemon, doesn't matter if dumb or smart
|
||||
if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
|
||||
#else
|
||||
// stop only dumb daemons
|
||||
if (ud->pid > 0 && !ud->pidfile) {
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
// try to stop daemon gracefully, kill it if it won't die
|
||||
// if mercy is not set then wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, SIGTERM);
|
||||
sleep(1);
|
||||
waitpid(-ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
kill(-ud->pid, SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// unregister daemon to prevent it from being respawned
|
||||
ud->registered = 0;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
@@ -165,11 +256,15 @@ void uwsgi_detach_daemons() {
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
int devnull = -1;
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
// if ud->respawns == 0 then we can end up with throttle < 0
|
||||
if (throttle <= 0) throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -179,6 +274,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->has_daemonized = 0;
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
ud->pidfile_checks = 0;
|
||||
@@ -210,18 +306,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -240,7 +325,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep(throttle);
|
||||
sleep((unsigned int) throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
|
||||
@@ -261,11 +346,26 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
char *pidfile = NULL;
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
char *space = NULL;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
|
||||
char *space = strchr(command, ' ');
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion = NULL;
|
||||
if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid legion daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
legion = command;
|
||||
command = space+1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
@@ -279,7 +379,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;
|
||||
}
|
||||
}
|
||||
@@ -308,6 +408,13 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
uwsgi_ud->control = 0;
|
||||
if (!strcmp(opt, "attach-control-daemon")) {
|
||||
uwsgi_ud->control = 1;
|
||||
}
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = legion;
|
||||
#endif
|
||||
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
|
||||
+538
-93
@@ -59,12 +59,12 @@ void uwsgi_emperor_blacklist_add(char *id) {
|
||||
uebi->throttle_level += (uwsgi.emperor_throttle * 1000);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uwsgi_log_verbose("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uebi->throttle_level = uebi->throttle_level / 2;
|
||||
}
|
||||
uebi->attempt++;
|
||||
if (uebi->attempt == 2) {
|
||||
uwsgi_log("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
uwsgi_log_verbose("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -318,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
struct stat st;
|
||||
struct uwsgi_instance *ui_current;
|
||||
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("glob()");
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -328,11 +354,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 +422,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;
|
||||
@@ -556,7 +603,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi_log("[emperor] %s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
|
||||
}
|
||||
|
||||
uwsgi_log("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
// put the instance in the blacklist (or update its throttling value)
|
||||
if (!c_ui->loyal) {
|
||||
uwsgi_emperor_blacklist_add(c_ui->name);
|
||||
@@ -575,24 +622,38 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// remove uWSGI instance
|
||||
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_stop()/write()");
|
||||
}
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_curse(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// curse uWSGI instance
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log_verbose("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_respawn/write()");
|
||||
}
|
||||
|
||||
// push the config to the config pipe (if needed)
|
||||
@@ -614,8 +675,12 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
c_ui->last_run = uwsgi_now();
|
||||
// reset readyness
|
||||
c_ui->ready = 0;
|
||||
// reset accepting
|
||||
c_ui->accepting = 0;
|
||||
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
|
||||
@@ -702,6 +767,9 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->uid = uid;
|
||||
n_ui->gid = gid;
|
||||
n_ui->last_mod = born;
|
||||
// start non-ready
|
||||
n_ui->last_ready = 0;
|
||||
n_ui->ready = 0;
|
||||
// start without loyalty
|
||||
n_ui->last_loyal = 0;
|
||||
n_ui->loyal = 0;
|
||||
@@ -748,15 +816,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 +843,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) && !defined(__ia64__)
|
||||
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) && !defined(__ia64__)
|
||||
}
|
||||
#endif
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()")
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/fork()")
|
||||
}
|
||||
else if (pid > 0) {
|
||||
n_ui->pid = pid;
|
||||
@@ -812,9 +885,141 @@ 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
|
||||
uwsgi_hooks_run(uwsgi.hook_as_emperor, "as-emperor", 0);
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
|
||||
uwsgi_log("mounting \"%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);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
|
||||
uwsgi_log("un-mounting \"%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);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
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", (int) n_ui->pid); argv[1] = argv_pid;
|
||||
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", (int) n_ui->uid); argv[2] = argv_uid;
|
||||
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", (int) 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) {
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#ifdef CLONE_NEWUSER
|
||||
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
|
||||
if (setuid(0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
|
||||
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
|
||||
int i;
|
||||
for(i=0;i<=CAP_LAST_CAP;i++) {
|
||||
|
||||
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
|
||||
if (has_cap == 1) {
|
||||
if (i == CAP_SETPCAP) continue;
|
||||
int j;int found = 0;
|
||||
for(j=0;j<uwsgi.emperor_cap_count;j++) {
|
||||
if (uwsgi.emperor_cap[j] == (int) i) {
|
||||
found = 1; break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
|
||||
uwsgi_log_verbose("unable to drop capability %lu\n", i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// just for being paranoid
|
||||
#ifdef SECBIT_KEEP_CAPS
|
||||
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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 +1042,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 +1068,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 +1105,40 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
counter = 4;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
int counter = 4;
|
||||
struct uwsgi_string_list *uct;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
|
||||
|
||||
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
|
||||
|
||||
// reset counter
|
||||
counter = 1;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_set) {
|
||||
vassal_argv[counter] = "--set";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
char *colon = NULL;
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
@@ -914,55 +1146,60 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
vassal_argv[counter] = "--inherit";
|
||||
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
vassal_argv[counter] = "--xml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
vassal_argv[counter] = "--ini";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
vassal_argv[counter] = "--json";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
vassal_argv[counter] = "--json";
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
vassal_argv[counter] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
// start config filename...
|
||||
counter++;
|
||||
|
||||
|
||||
vassal_argv[2] = n_ui->name;
|
||||
vassal_argv[counter] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
// start templates,includes,inherit...
|
||||
counter++;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
@@ -976,22 +1213,13 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
// 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 +1229,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 +1241,60 @@ 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);
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_vassal, "as-vassal", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_vassal) {
|
||||
uwsgi_log("mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_vassal) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 +1302,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) {
|
||||
@@ -1272,13 +1552,14 @@ void emperor_loop() {
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
|
||||
emperor_curse(ui_current);
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
ui_current->loyal = 1;
|
||||
ui_current->last_loyal = uwsgi_now();
|
||||
uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
// remove it from the blacklist
|
||||
uwsgi_emperor_blacklist_remove(ui_current->name);
|
||||
// TODO post-start hook
|
||||
@@ -1291,12 +1572,22 @@ void emperor_loop() {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
// here we discard socket name as broodlord/zerg cannot be on demand
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
|
||||
free(zerg_name);
|
||||
}
|
||||
else if (byte == 5) {
|
||||
ui_current->accepting = 1;
|
||||
ui_current->last_accepting = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s is ready to accept requests\n", ui_current->name);
|
||||
}
|
||||
else if (byte == 1) {
|
||||
ui_current->ready = 1;
|
||||
ui_current->last_ready = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1322,10 +1613,14 @@ void emperor_loop() {
|
||||
while (ui_current) {
|
||||
if (ui_current->last_heartbeat > 0) {
|
||||
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
// set last_heartbeat to 0 avoiding races
|
||||
ui_current->last_heartbeat = 0;
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
if (ui_current->pid > 0) {
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_current = ui_current->ui_next;
|
||||
@@ -1374,14 +1669,8 @@ void emperor_loop() {
|
||||
ui_current = ui;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->status == 1) {
|
||||
if (ui_current->config)
|
||||
free(ui_current->config);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (ui_current->pid == diedpid) {
|
||||
time_t now = uwsgi_now();
|
||||
if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
|
||||
@@ -1404,6 +1693,13 @@ void emperor_loop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
|
||||
ui_current->cursed_at = now;
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1494,12 +1790,22 @@ void emperor_send_stats(int fd) {
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "loyal", (unsigned long long) c_ui->loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "ready", (unsigned long long) c_ui->ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) c_ui->accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_loyal", (unsigned long long) c_ui->last_loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_ready", (unsigned long long) c_ui->last_ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_accepting", (unsigned long long) c_ui->last_accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "first_run", (unsigned long long) c_ui->first_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
@@ -1643,6 +1949,46 @@ void uwsgi_emperor_start() {
|
||||
}
|
||||
|
||||
void uwsgi_check_emperor() {
|
||||
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
|
||||
if (emperor_fd_pass) {
|
||||
for(;;) {
|
||||
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
|
||||
if (proxy_fd < 0) {
|
||||
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
int count = 2;
|
||||
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
|
||||
if (fds && count > 0) {
|
||||
char *env_emperor_fd = uwsgi_num2str(fds[0]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
|
||||
free(env_emperor_fd);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd);
|
||||
if (count > 1) {
|
||||
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
|
||||
free(env_emperor_fd_config);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd_config);
|
||||
}
|
||||
break;
|
||||
}
|
||||
next:
|
||||
if (fds) free(fds);
|
||||
close(proxy_fd);
|
||||
sleep(1);
|
||||
}
|
||||
unsetenv("UWSGI_EMPEROR_PROXY");
|
||||
}
|
||||
|
||||
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
|
||||
if (emperor_env) {
|
||||
uwsgi.has_emperor = 1;
|
||||
@@ -1698,3 +2044,102 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor_proxy() {
|
||||
|
||||
struct sockaddr_un epsun;
|
||||
socklen_t epsun_len = sizeof(struct sockaddr_un);
|
||||
|
||||
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
|
||||
if (ep_client < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
int num_fds = 1;
|
||||
if (uwsgi.emperor_fd_config > -1) num_fds++;
|
||||
|
||||
struct msghdr ep_msg;
|
||||
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
|
||||
struct iovec ep_iov[2];
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ep_iov[0].iov_base = "uwsgi-emperor";
|
||||
ep_iov[0].iov_len = 13;
|
||||
ep_iov[1].iov_base = &num_fds;
|
||||
ep_iov[1].iov_len = sizeof(int);
|
||||
|
||||
ep_msg.msg_name = NULL;
|
||||
ep_msg.msg_namelen = 0;
|
||||
|
||||
ep_msg.msg_iov = ep_iov;
|
||||
ep_msg.msg_iovlen = 2;
|
||||
|
||||
ep_msg.msg_flags = 0;
|
||||
ep_msg.msg_control = ep_msg_control;
|
||||
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&ep_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
|
||||
|
||||
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
|
||||
if (num_fds > 1) {
|
||||
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
|
||||
}
|
||||
|
||||
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
|
||||
}
|
||||
|
||||
free(ep_msg_control);
|
||||
|
||||
close(ep_client);
|
||||
}
|
||||
|
||||
static void emperor_notify_ready() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
char byte = 1;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("emperor_notify_ready()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_setup_emperor() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
uwsgi.notify_ready = emperor_notify_ready;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
struct stat st;
|
||||
if (!stat(usl->value, &st)) {
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// generate internal server error message
|
||||
void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
|
||||
}
|
||||
|
||||
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
|
||||
}
|
||||
@@ -18,6 +40,7 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1214,6 +1231,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#elif defined(__arm__)
|
||||
return syscall(350, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
@@ -1224,6 +1243,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__arm__)
|
||||
return syscall(353, __ufd, __flags, __utmr, __otmr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
|
||||
|
||||
if (do_exit) goto check_catch;
|
||||
|
||||
if (wsgi_req && uwsgi.exception_handlers_instance) {
|
||||
if (uwsgi.exception_handlers_instance) {
|
||||
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
|
||||
if (ehi) {
|
||||
uwsgi_exception_run_handlers(ehi);
|
||||
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
|
||||
}
|
||||
|
||||
void uwsgi_exceptions_handler_thread_start() {
|
||||
|
||||
if (!uwsgi.exception_handlers_instance) return;
|
||||
// start the exception_handler_thread
|
||||
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
|
||||
if (!uwsgi.exception_handler_thread) {
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
the --master-fifo option create a unix named pipe (fifo) you can use to send management
|
||||
commands to the master:
|
||||
|
||||
echo r > myfifo
|
||||
|
||||
*/
|
||||
|
||||
// this var can be accessed by plugins and hooks
|
||||
void (*uwsgi_fifo_table[256])(int);
|
||||
|
||||
static char *uwsgi_fifo_by_slot() {
|
||||
int count = 0;
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.master_fifo) {
|
||||
if (count == uwsgi.master_fifo_slot) return usl->value;
|
||||
count++;
|
||||
}
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
|
||||
|
||||
static void subscriptions_blocker() {
|
||||
if (uwsgi.subscriptions_blocked) {
|
||||
uwsgi_log_verbose("subscriptions re-enabled\n");
|
||||
uwsgi.subscriptions_blocked = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.subscriptions_blocked = 1;
|
||||
uwsgi_log_verbose("subscriptions blocked\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
this is called as soon as possibile allowing plugins (or hooks) to override it
|
||||
|
||||
*/
|
||||
void uwsgi_master_fifo_prepare() {
|
||||
int i;
|
||||
for(i=0;i<256;i++) {
|
||||
uwsgi_fifo_table[i] = NULL;
|
||||
}
|
||||
|
||||
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
|
||||
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
|
||||
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
|
||||
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
|
||||
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
|
||||
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
|
||||
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
|
||||
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
|
||||
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
|
||||
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['f'] = uwsgi_refork_master;
|
||||
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
|
||||
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
|
||||
uwsgi_fifo_table['p'] = suspend_resume_them_all;
|
||||
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
|
||||
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
|
||||
uwsgi_fifo_table['Q'] = kill_them_all;
|
||||
uwsgi_fifo_table['r'] = grace_them_all;
|
||||
uwsgi_fifo_table['R'] = reap_them_all;
|
||||
uwsgi_fifo_table['s'] = stats;
|
||||
uwsgi_fifo_table['S'] = subscriptions_blocker;
|
||||
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
|
||||
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo() {
|
||||
|
||||
char *path = uwsgi_fifo_by_slot();
|
||||
|
||||
unlink(path);
|
||||
|
||||
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_master_fifo()/open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
unsigned char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_master_fifo_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
close(fd);
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_fifo_table[(int) cmd]) {
|
||||
uwsgi_fifo_table[(int) cmd](0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
#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);
|
||||
free(copy);
|
||||
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;
|
||||
}
|
||||
|
||||
+12
-2
@@ -18,7 +18,9 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
}
|
||||
}
|
||||
|
||||
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
|
||||
char *str = uwsgi_num2str(num);
|
||||
char *fullname = uwsgi_concat3(name, " ", str);
|
||||
free(str);
|
||||
|
||||
ug = &ushared->gateways[ushared->gateways_cnt];
|
||||
ug->pid = 0;
|
||||
@@ -28,11 +30,18 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
ug->fullname = fullname;
|
||||
ug->data = data;
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
||||
|
||||
if (!uwsgi.master_process && !uwsgi.force_gateway)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
ushared->gateways_cnt++;
|
||||
@@ -61,6 +70,7 @@ void gateway_respawn(int id) {
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
uwsgi_close_all_sockets();
|
||||
if (uwsgi.master_as_root)
|
||||
uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
|
||||
+21
-1
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
|
||||
|
||||
// Murmur2 hash Copyright (C) Austin Appleby
|
||||
// adapted from nginx
|
||||
uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
|
||||
uint32_t h, k;
|
||||
uint8_t *ukey = (uint8_t *) key;
|
||||
@@ -56,6 +56,23 @@ uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32_t random_hash(char *key, uint64_t keylen) {
|
||||
return (uint32_t) rand();
|
||||
}
|
||||
|
||||
/*
|
||||
not atomic, avoid its use in multithreaded modes
|
||||
*/
|
||||
static uint32_t rr_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t rr = 0;
|
||||
uint32_t max_value = uwsgi_str_num(key, keylen);
|
||||
uint32_t ret = rr;
|
||||
rr++;
|
||||
if (rr > max_value) {
|
||||
rr = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
|
||||
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
|
||||
@@ -90,4 +107,7 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
|
||||
void uwsgi_hash_algo_register_all() {
|
||||
uwsgi_hash_algo_register("djb33x", djb33x_hash);
|
||||
uwsgi_hash_algo_register("murmur2", murmur2_hash);
|
||||
uwsgi_hash_algo_register("random", random_hash);
|
||||
uwsgi_hash_algo_register("rand", random_hash);
|
||||
uwsgi_hash_algo_register("rr", rr_hash);
|
||||
}
|
||||
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
advanced (pluggable) hooks
|
||||
|
||||
they are executed before the other hooks, and can be extended by plugins
|
||||
|
||||
if a plugin tries to register an hook with a name already available in the list, its function
|
||||
will be overridden
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
|
||||
struct uwsgi_hook *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
return uh;
|
||||
}
|
||||
uh = uh->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
uh->func = func;
|
||||
return;
|
||||
}
|
||||
old_uh = uh;
|
||||
uh = uh->next;
|
||||
}
|
||||
|
||||
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
|
||||
uh->name = name;
|
||||
uh->func = func;
|
||||
|
||||
if (old_uh) {
|
||||
old_uh->next = uh;
|
||||
}
|
||||
else {
|
||||
uwsgi.hooks = uh;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chdir(char *arg) {
|
||||
int ret = chdir(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chdir()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exit(char *arg) {
|
||||
int exit_code = 0;
|
||||
if (strlen(arg) > 1) {
|
||||
exit_code = atoi(arg);
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_print(char *arg) {
|
||||
char *line = uwsgi_concat2(arg, "\n");
|
||||
uwsgi_log(line);
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_unlink(char *arg) {
|
||||
int ret = unlink(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_unlink()/unlink()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_writefifo(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
if (errno == ENODEV) return 0;
|
||||
#ifdef ENXIO
|
||||
if (errno == ENXIO) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_writefifo()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_write(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_write()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callint(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(num);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_call(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(space + 1);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callintret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(num);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(space + 1);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("write", uwsgi_hook_write);
|
||||
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
|
||||
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
|
||||
|
||||
uwsgi_register_hook("mount", uwsgi_mount_hook);
|
||||
uwsgi_register_hook("umount", uwsgi_umount_hook);
|
||||
|
||||
uwsgi_register_hook("call", uwsgi_hook_call);
|
||||
uwsgi_register_hook("callret", uwsgi_hook_callret);
|
||||
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
}
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
char *colon = strchr(usl->value, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid hook syntax, must be hook:args\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
|
||||
if (!uh) {
|
||||
uwsgi_log("hook not found: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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] = ':';
|
||||
}
|
||||
|
||||
+50
-12
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{"509", "Bandwidth Limit Exceeded"},
|
||||
{"", NULL},
|
||||
};
|
||||
|
||||
@@ -75,10 +76,12 @@ void uwsgi_init_default() {
|
||||
uwsgi.original_log_fd = -1;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
// default emperor scan frequency
|
||||
uwsgi.emperor_freq = 3;
|
||||
uwsgi.emperor_throttle = 1000;
|
||||
uwsgi.emperor_heartbeat = 30;
|
||||
uwsgi.emperor_curse_tolerance = 30;
|
||||
// max 3 minutes throttling
|
||||
uwsgi.emperor_max_throttle = 1000 * 180;
|
||||
uwsgi.emperor_pid = -1;
|
||||
@@ -161,10 +164,25 @@ 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.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
|
||||
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
|
||||
// clear reforked status
|
||||
uwsgi.master_is_reforked = 0;
|
||||
|
||||
uwsgi.master_fifo_fd = -1;
|
||||
uwsgi_master_fifo_prepare();
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -209,21 +227,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
|
||||
p = original_proc_name;
|
||||
p = strstr(p, "uwsgi_");
|
||||
if (p != NULL) {
|
||||
plugins_requested = strtok(uwsgi_str(p + 6), "_");
|
||||
while (plugins_requested) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
|
||||
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
|
||||
uwsgi_load_plugin(-1, plugins_requested, NULL);
|
||||
plugins_requested = strtok(NULL, "_");
|
||||
}
|
||||
}
|
||||
|
||||
plugins_requested = getenv("UWSGI_PLUGINS");
|
||||
if (plugins_requested) {
|
||||
plugins_requested = uwsgi_concat2(plugins_requested, "");
|
||||
char *p = strtok(plugins_requested, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
|
||||
uwsgi_load_plugin(-1, p, NULL);
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +348,6 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.workers[i].signal_pipe[0] = -1;
|
||||
uwsgi.workers[i].signal_pipe[1] = -1;
|
||||
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
|
||||
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
|
||||
}
|
||||
|
||||
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
|
||||
@@ -347,6 +362,13 @@ void uwsgi_setup_workers() {
|
||||
// allocate signal table
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.response_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
pid_t uwsgi_daemonize2() {
|
||||
@@ -374,6 +396,8 @@ pid_t uwsgi_daemonize2() {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) uwsgi_setup_log_master();
|
||||
|
||||
return uwsgi.mypid;
|
||||
}
|
||||
|
||||
@@ -425,17 +449,31 @@ void sanitize_args() {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
|
||||
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
|
||||
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
|
||||
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
|
||||
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) {
|
||||
|
||||
@@ -116,48 +116,31 @@ end:
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
extremely complex function for reading resources (files, url...)
|
||||
need a lot of refactoring...
|
||||
*/
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
|
||||
int fd = atoi(url);
|
||||
return uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
|
||||
int fd;
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url, NULL, cpipe[1]);
|
||||
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
|
||||
char byte;
|
||||
ssize_t len;
|
||||
char *uri, *colon;
|
||||
char *domain;
|
||||
char *ip;
|
||||
int body = 0;
|
||||
char *magic_buf;
|
||||
int body = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
}
|
||||
// fd ?
|
||||
else if (!strncmp("fd://", url, 5)) {
|
||||
fd = atoi(url + 5);
|
||||
buffer = uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
// exec ?
|
||||
else if (!strncmp("exec://", url, 5)) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url + 7, NULL, cpipe[1]);
|
||||
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
}
|
||||
// http url ?
|
||||
else if (!strncmp("http://", url, 7)) {
|
||||
domain = url + 7;
|
||||
uri = strchr(domain, '/');
|
||||
char *domain = url;
|
||||
char *uri = strchr(domain, '/');
|
||||
if (!uri) {
|
||||
uwsgi_log("invalid http url\n");
|
||||
exit(1);
|
||||
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
uri[0] = 0;
|
||||
uwsgi_log("domain: %s\n", domain);
|
||||
|
||||
colon = uwsgi_get_last_char(domain, ':');
|
||||
char *colon = uwsgi_get_last_char(domain, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
ip = uwsgi_resolve_ip(domain);
|
||||
char *ip = uwsgi_resolve_ip(domain);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve address %s\n", domain);
|
||||
exit(1);
|
||||
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
ip = uwsgi_concat2(ip, ":80");
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(ip, 0, 0);
|
||||
int fd = uwsgi_connect(ip, 0, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_scheme_http()/connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "GET ", 4);
|
||||
len = write(fd, uri, strlen(uri));
|
||||
len = write(fd, " HTTP/1.0\r\n", 11);
|
||||
len = write(fd, "Host: ", 6);
|
||||
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
uri[0] = 0;
|
||||
len = write(fd, domain, strlen(domain));
|
||||
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
|
||||
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
|
||||
len = write(fd, "\r\n\r\n", 4);
|
||||
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
int http_status_code_ptr = 0;
|
||||
|
||||
@@ -264,57 +248,233 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer[*size - 1] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
|
||||
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (!strncmp("emperor://", url, 10)) {
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
ssize_t rlen;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ssize_t rlen;
|
||||
*size = 0;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
|
||||
char *buffer = NULL;
|
||||
int fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -8, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
|
||||
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *s = func();
|
||||
if (!s) {
|
||||
uwsgi_log("called symbol %s did not return a string\n", url);
|
||||
exit(1);
|
||||
}
|
||||
*size = strlen(s);
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, s, strlen(s));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
|
||||
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
|
||||
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
|
||||
if (raw_symbol) {
|
||||
sym_start_ptr = *raw_symbol;
|
||||
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
|
||||
goto found;
|
||||
}
|
||||
char *symbol = uwsgi_concat3("_binary_", url, "_start");
|
||||
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url, "_end");
|
||||
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
|
||||
found:
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
|
||||
#ifdef UWSGI_ELF
|
||||
size_t s_len = 0;
|
||||
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
return buffer;
|
||||
#else
|
||||
uwsgi_log("section:// scheme not supported on this platform\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
if (!strcmp(usl->value, name)) goto found;
|
||||
}
|
||||
|
||||
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
|
||||
|
||||
found:
|
||||
usl->custom_ptr = func;
|
||||
return usl;
|
||||
}
|
||||
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
ssize_t len;
|
||||
char *magic_buf;
|
||||
int fd;
|
||||
|
||||
*size = 0;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
goto end;
|
||||
}
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
else if (url[0] == 0) {
|
||||
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
|
||||
@@ -324,108 +484,22 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
else if (!strncmp("data://", url, 7)) {
|
||||
fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url + 7);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -9, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp("sym://", url, 6)) {
|
||||
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
|
||||
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
|
||||
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
|
||||
if (!usl) goto fallback;
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
}
|
||||
#ifdef UWSGI_ELF
|
||||
else if (!strncmp("section://", url, 10)) {
|
||||
size_t s_len = 0;
|
||||
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
}
|
||||
#endif
|
||||
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
|
||||
buffer = func(url + usl->len + 3, size, add_zero);
|
||||
if (buffer) goto end;
|
||||
// never here !!!
|
||||
uwsgi_log("unable to parse config file %s\n", url);
|
||||
exit(1);
|
||||
|
||||
// fallback to file
|
||||
else {
|
||||
fallback:
|
||||
fd = open(url, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(url);
|
||||
@@ -457,7 +531,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
if (add_zero)
|
||||
buffer[sb.st_size] = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@@ -683,11 +756,12 @@ int uwsgi_write_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
int ret;
|
||||
|
||||
while(remains > 0) {
|
||||
errno = 0;
|
||||
ssize_t len = write(fd, ptr, remains);
|
||||
if (len > 0) goto written;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -838,7 +912,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
|
||||
}
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
}
|
||||
return -1;
|
||||
wait:
|
||||
@@ -870,12 +944,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
}
|
||||
|
||||
/*
|
||||
this is a pretty magic function used for read a full uwsgi response
|
||||
this is a pretty magic function used for reading a full uwsgi response
|
||||
it is true non blocking, so you can use it in request plugins
|
||||
buffer is expected to be at least 4 bytes, rlen is a get/set value
|
||||
*/
|
||||
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
|
||||
if (*rlen < 4) return -1;
|
||||
char *buf = *buffer;
|
||||
int ret;
|
||||
@@ -888,7 +962,7 @@ int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
|
||||
if (len > 0) goto readok;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -906,6 +980,10 @@ readok:
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (modifier1)
|
||||
*modifier1 = uh->modifier1;
|
||||
if (modifier2)
|
||||
*modifier2 = uh->modifier2;
|
||||
|
||||
if (pktsize > *rlen) {
|
||||
char *tmp_buf = realloc(buf, pktsize);
|
||||
@@ -926,7 +1004,7 @@ readok:
|
||||
if (len > 0) goto readok2;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
|
||||
if (uwsgi_is_again()) goto wait2;
|
||||
return -1;
|
||||
}
|
||||
wait2:
|
||||
@@ -955,6 +1033,8 @@ readok2:
|
||||
|
||||
int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) {
|
||||
|
||||
struct uwsgi_buffer *headers = NULL;
|
||||
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
@@ -988,21 +1068,151 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
|
||||
}
|
||||
|
||||
// read the response
|
||||
headers = uwsgi_buffer_new(8192);
|
||||
// max 64k headers
|
||||
ub->limit = UMAX16;
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
if (headers) {
|
||||
if (uwsgi_buffer_append(headers, buf, rlen)) {
|
||||
goto end;
|
||||
}
|
||||
// check if we have a full HTTP response
|
||||
if (uwsgi_is_full_http(headers)) {
|
||||
int ret = uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
|
||||
if (ret) continue;
|
||||
uwsgi_buffer_destroy(headers);
|
||||
headers = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
end:
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_file_write_do(struct uwsgi_string_list *usl) {
|
||||
|
||||
struct uwsgi_string_list *fl = usl;
|
||||
while(fl) {
|
||||
char *equal = strchr(fl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
FILE *f = fopen(fl->value, "w");
|
||||
if (!f) {
|
||||
uwsgi_error_open("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("writing \"%s\" to \"%s\" ...\n", equal+1, fl->value);
|
||||
if (fprintf(f, "%s\n", equal+1) <= 0 || ferror(f) || fclose(f)) {
|
||||
uwsgi_error("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to write empty value for \"%s\"\n", fl->value);
|
||||
exit(1);
|
||||
}
|
||||
*equal = '=';
|
||||
fl = fl->next;
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_fd_is_safe(int fd) {
|
||||
int i;
|
||||
for(i=0;i<uwsgi.safe_fds_cnt;i++) {
|
||||
if (uwsgi.safe_fds[i] == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void uwsgi_add_safe_fd(int fd) {
|
||||
// check if the fd is already safe
|
||||
if (uwsgi_fd_is_safe(fd)) return;
|
||||
|
||||
size_t len = sizeof(int) * (uwsgi.safe_fds_cnt+1);
|
||||
int *tmp = realloc(uwsgi.safe_fds, len);
|
||||
if (!tmp) {
|
||||
uwsgi_error("uwsgi_add_safe_fd()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.safe_fds = tmp;
|
||||
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;
|
||||
}
|
||||
|
||||
void uwsgi_setup_schemes() {
|
||||
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
|
||||
uwsgi_register_scheme("http", uwsgi_scheme_http);
|
||||
uwsgi_register_scheme("data", uwsgi_scheme_data);
|
||||
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
|
||||
uwsgi_register_scheme("section", uwsgi_scheme_section);
|
||||
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
|
||||
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
|
||||
uwsgi_register_scheme("call", uwsgi_scheme_call);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
char *url = uwsgi_concat2(usl->value, "://");
|
||||
int ret = uwsgi_startswith(file, url, strlen(url));
|
||||
free(url);
|
||||
if (!ret) return usl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_remap_fd(int fd, char *filename) {
|
||||
|
||||
int fdin = open(filename, O_RDWR);
|
||||
if (fdin < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (fdin != fd) {
|
||||
if (dup2(fdin, fd) < 0) {
|
||||
uwsgi_error("uwsgi_remap_fd()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fdin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
config_iter = json_object_iter_next(config, config_iter);
|
||||
}
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+72
-12
@@ -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)
|
||||
@@ -206,7 +209,7 @@ static void legions_check_nodes() {
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
@@ -232,12 +235,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
|
||||
|
||||
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
while (nodes) {
|
||||
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
nodes = nodes->next;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
|
||||
}
|
||||
|
||||
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
|
||||
@@ -273,12 +276,17 @@ static void legions_check_nodes_step2() {
|
||||
best_valor = node->valor;
|
||||
memcpy(best_uuid, node->uuid, 36);
|
||||
}
|
||||
else {
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
memset(best_uuid, 0, 36);
|
||||
}
|
||||
|
||||
// calculate the checksum
|
||||
uint64_t new_checksum = uwsgi_legion_checksum(ul);
|
||||
@@ -357,9 +365,9 @@ static void legions_check_nodes_step2() {
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
|
||||
if (ul->lord_scroll_len > 0) {
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n");
|
||||
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
|
||||
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
|
||||
}
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
@@ -376,6 +384,20 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
|
||||
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
|
||||
// no more quorum, leave the Lord state
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("unlord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->i_am_the_lord = 0;
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
@@ -395,6 +417,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
while (nodes) {
|
||||
// skip arbiters
|
||||
if (nodes->valor == 0) goto next;
|
||||
if (nodes->valor > best_valor) {
|
||||
best_node = nodes;
|
||||
best_valor = nodes->valor;
|
||||
@@ -407,11 +431,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
memcpy(best_uuid, nodes->uuid, 36);
|
||||
}
|
||||
}
|
||||
next:
|
||||
nodes = nodes->next;
|
||||
}
|
||||
|
||||
// first round ?
|
||||
if (ul->lord_valor == 0) {
|
||||
// first round ? (skip first round if arbiter)
|
||||
if (ul->valor > 0 && ul->lord_valor == 0) {
|
||||
ul->changed = 1;
|
||||
}
|
||||
else if (best_valor != ul->lord_valor) {
|
||||
@@ -578,7 +603,7 @@ static void *legion_loop(void *foobar) {
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
@@ -589,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;
|
||||
@@ -730,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) {
|
||||
@@ -775,6 +811,21 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
uwsgi_opt_legion(opt, value, foobar);
|
||||
char *legion = uwsgi_str(value);
|
||||
char *space = strchr(legion, ' ');
|
||||
// over engineering
|
||||
if (!space) exit(1);
|
||||
*space = 0;
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
@@ -1085,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;
|
||||
@@ -1103,6 +1162,7 @@ next:
|
||||
legion = legion->next;
|
||||
}
|
||||
|
||||
uwsgi_legion_announce_death();
|
||||
}
|
||||
|
||||
int uwsgi_legion_i_am_the_lord(char *name) {
|
||||
|
||||
+83
-11
@@ -474,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
@@ -495,7 +493,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
@@ -506,7 +504,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
}
|
||||
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
@@ -514,7 +512,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -534,7 +532,13 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +555,13 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -576,6 +586,8 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
if (uwsgi.persistent_ipcsem) return;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers)
|
||||
@@ -596,12 +608,27 @@ clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
#ifdef GETPID
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
int ret = semctl(semid, 0, GETPID);
|
||||
if (ret > 0) {
|
||||
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
|
||||
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
uli = uwsgi.registered_locks;
|
||||
#endif
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
@@ -612,6 +639,33 @@ 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);
|
||||
sleep(1);
|
||||
}
|
||||
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() {
|
||||
|
||||
@@ -661,7 +715,9 @@ ready:
|
||||
// application generic lock
|
||||
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
|
||||
for (i = 0; i < uwsgi.locks + 1; i++) {
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
|
||||
char *num = uwsgi_num2str(i);
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
|
||||
free(num);
|
||||
}
|
||||
|
||||
// event queue lock (mitigate same event on multiple queues)
|
||||
@@ -689,6 +745,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 +828,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;
|
||||
}
|
||||
|
||||
+705
-275
File diff suppressed because it is too large
Load Diff
+201
-124
@@ -2,15 +2,30 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_restore_auto_snapshot(int signum) {
|
||||
void uwsgi_update_load_counters() {
|
||||
|
||||
if (uwsgi.workers[1].snapshot > 0) {
|
||||
uwsgi.restore_snapshot = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[WARNING] no snapshot available\n");
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi_worker_is_busy(i) == 0) {
|
||||
idle_workers++;
|
||||
}
|
||||
else {
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
ushared->idle_workers = idle_workers;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_block_signal(int signum) {
|
||||
@@ -32,24 +47,25 @@ void uwsgi_unblock_signal(int signum) {
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_udp(int udp_fd) {
|
||||
char buf[4096];
|
||||
struct sockaddr_in udp_client;
|
||||
char udp_client_addr[16];
|
||||
int i;
|
||||
|
||||
socklen_t udp_len = sizeof(udp_client);
|
||||
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
|
||||
memset(udp_client_addr, 0, 16);
|
||||
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
|
||||
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
}
|
||||
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
else if (buf[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -57,7 +73,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
int udp_managed = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->manage_udp) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
|
||||
udp_managed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -66,74 +82,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
|
||||
// else a simple udp logger
|
||||
if (!udp_managed) {
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("inet_ntop()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_restore_snapshot() {
|
||||
int i, waitpid_status;
|
||||
uwsgi_log("[snapshot] restoring workers...\n");
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGURG);
|
||||
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.restore_snapshot = 0;
|
||||
}
|
||||
|
||||
void suspend_resume_them_all(int signum) {
|
||||
|
||||
int i;
|
||||
@@ -222,8 +181,8 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
#elif defined(__FreeBSD__)
|
||||
if (!uwsgi.shared->ti.__tcpi_sacked) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
|
||||
@@ -242,12 +201,12 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
|
||||
@@ -306,7 +265,6 @@ int master_loop(char **argv, char **environ) {
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
uwsgi_set_processname(uwsgi.procname_master);
|
||||
}
|
||||
@@ -332,9 +290,6 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
uwsgi_unix_signal(SIGINT, kill_them_all);
|
||||
uwsgi_unix_signal(SIGUSR1, stats);
|
||||
if (uwsgi.auto_snapshot) {
|
||||
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
|
||||
}
|
||||
|
||||
atexit(uwsgi_master_cleanup_hooks);
|
||||
|
||||
@@ -346,6 +301,11 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
if (uwsgi.master_fifo) {
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
@@ -374,6 +334,9 @@ int master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_start_legions();
|
||||
#endif
|
||||
uwsgi_metrics_start_collector();
|
||||
|
||||
uwsgi_add_reload_fds();
|
||||
|
||||
uwsgi_cache_start_sweepers();
|
||||
uwsgi_cache_start_sync_servers();
|
||||
@@ -381,7 +344,18 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
if (uwsgi.emperor_proxy) {
|
||||
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
|
||||
if (uwsgi.emperor_fd_proxy < 0) exit(1);
|
||||
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("[emperor-proxy] chmod()");
|
||||
exit(1);
|
||||
}
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
|
||||
}
|
||||
else {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
@@ -391,7 +365,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;
|
||||
@@ -473,6 +447,55 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
|
||||
// update exec touches
|
||||
struct uwsgi_string_list *usl = uwsgi.touch_exec;
|
||||
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_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();
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
@@ -527,21 +550,6 @@ int master_loop(char **argv, char **environ) {
|
||||
// check for daemons (smart and dumb)
|
||||
uwsgi_daemons_smart_check();
|
||||
|
||||
|
||||
if (uwsgi.respawn_snapshots) {
|
||||
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
}
|
||||
|
||||
uwsgi.respawn_snapshots = 0;
|
||||
}
|
||||
|
||||
if (uwsgi.restore_snapshot) {
|
||||
uwsgi_master_restore_snapshot();
|
||||
continue;
|
||||
}
|
||||
|
||||
// cheaper management
|
||||
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (!uwsgi_calc_cheaper())
|
||||
@@ -571,8 +579,10 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
/* all processes ok, doing status scan after N seconds */
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
}
|
||||
|
||||
|
||||
// add unregistered file monitors
|
||||
@@ -607,14 +617,14 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (ushared->rb_timers_cnt > 0) {
|
||||
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
}
|
||||
else {
|
||||
check_interval = min_timeout->value - uwsgi_now();
|
||||
if (check_interval <= 0) {
|
||||
if (min_timeout) {
|
||||
int delta = min_timeout->value - uwsgi_now();
|
||||
if (delta <= 0) {
|
||||
expire_rb_timeouts(rb_timers);
|
||||
check_interval = 0;
|
||||
}
|
||||
// if the timer expires before the check_interval, override it
|
||||
else if (delta < check_interval) {
|
||||
check_interval = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,6 +638,9 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// update load counter
|
||||
uwsgi_update_load_counters();
|
||||
|
||||
|
||||
// check uwsgi-cron table
|
||||
if (ushared->cron_cnt) {
|
||||
@@ -668,12 +681,15 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_master_check_idle();
|
||||
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
@@ -685,8 +701,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();
|
||||
@@ -694,6 +716,8 @@ 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();
|
||||
uwsgi_master_check_mountpoints();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
@@ -704,7 +728,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
|
||||
// resubscribe every 10 cycles by default
|
||||
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
uwsgi_subscribe_all(0, 0);
|
||||
}
|
||||
|
||||
@@ -728,26 +752,34 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
continue;
|
||||
}
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_reload_workers();
|
||||
continue;
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
if (touched) {
|
||||
if (uwsgi.status.chain_reloading == 0) {
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
}
|
||||
}
|
||||
|
||||
// be sure to run it as the last touch check
|
||||
touched = uwsgi_check_touches(uwsgi.touch_exec);
|
||||
if (touched) {
|
||||
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
|
||||
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;
|
||||
@@ -764,11 +796,18 @@ int master_loop(char **argv, char **environ) {
|
||||
// reload gateways and daemons only on normal workflow (+outworld status)
|
||||
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
|
||||
|
||||
if (uwsgi_master_check_emperor_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
|
||||
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_emperor_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid))
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -833,7 +872,9 @@ 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) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
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;
|
||||
}
|
||||
@@ -852,6 +893,11 @@ next:
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_BRUTAL_RELOAD_CODE) {
|
||||
uwsgi_log("!!! inconsistent state reported by worker %d (pid: %d) !!!\n", thewid, (int) diedpid);
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
@@ -906,3 +952,34 @@ next:
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
void uwsgi_reload_workers() {
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
void uwsgi_chain_reload() {
|
||||
if (!uwsgi.status.chain_reloading) {
|
||||
uwsgi_log_verbose("chain reload starting...\n");
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("chain reload already running...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_brutally_reload_workers() {
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+64
-2
@@ -35,13 +35,21 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
int i;
|
||||
int needed_procs = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
|
||||
needed_procs++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.status.chain_reloading > needed_procs) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
}
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
// do not curse a worker until the old one is ready
|
||||
if (uwsgi.workers[i].accepting == 0) break;
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
break;
|
||||
@@ -112,6 +120,9 @@ void uwsgi_master_check_idle() {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
@@ -177,6 +188,7 @@ void uwsgi_master_check_gateways_deadline() {
|
||||
if (ushared->gateways_harakiri[i] > 0) {
|
||||
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
uwsgi_log("*** HARAKIRI ON GATEWAY %s %d (pid: %d) ***\n", ushared->gateways[i].name, ushared->gateways[i].num, ushared->gateways[i].pid);
|
||||
kill(ushared->gateways[i].pid, SIGKILL);
|
||||
}
|
||||
ushared->gateways_harakiri[i] = 0;
|
||||
@@ -196,6 +208,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +227,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;
|
||||
}
|
||||
}
|
||||
@@ -276,3 +301,40 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mountpoints() {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
|
||||
if (uwsgi_check_mountpoint(usl->value)) {
|
||||
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
|
||||
uwsgi_nuclear_blast();
|
||||
//never here
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
@@ -36,12 +40,91 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
|
||||
// emperor event ?
|
||||
if (uwsgi.has_emperor) {
|
||||
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
|
||||
uwsgi_master_manage_emperor_proxy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (interesting_fd == uwsgi.emperor_fd) {
|
||||
uwsgi_master_manage_emperor();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (usl->custom2 > 8) free(tmp);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wakeup from cheap mode ?
|
||||
if (uwsgi.status.is_cheap) {
|
||||
|
||||
+373
-197
@@ -115,7 +115,49 @@ int uwsgi_calc_cheaper(void) {
|
||||
|
||||
last_check = now;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
int ignore_algo = 0;
|
||||
int needed_workers = 0;
|
||||
|
||||
// first check if memory usage is not exceeded
|
||||
if (uwsgi.cheaper_rss_limit_soft) {
|
||||
unsigned long long total_rss = 0;
|
||||
int i;
|
||||
int active_workers = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (!uwsgi.workers[i].cheaped) {
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && active_workers > 1 && total_rss >= uwsgi.cheaper_rss_limit_hard) {
|
||||
uwsgi_log("cheaper hard rss memory limit exceeded, cheap one of %d workers\n", active_workers);
|
||||
needed_workers = -1;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
else if (total_rss >= uwsgi.cheaper_rss_limit_soft) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cheaper soft rss memory limit exceeded, can't spawn more workers\n");
|
||||
#endif
|
||||
ignore_algo = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// then check for fifo
|
||||
if (uwsgi.cheaper_fifo_delta != 0) {
|
||||
if (!ignore_algo) {
|
||||
needed_workers = uwsgi.cheaper_fifo_delta;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
}
|
||||
|
||||
// if cheaper limits wants to change worker count, then skip cheaper algo
|
||||
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
|
||||
// safe check to verify if cheaper algo obeyed ignore_algo value
|
||||
if (ignore_algo && needed_workers > 0) {
|
||||
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
|
||||
needed_workers = 0;
|
||||
}
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
@@ -152,6 +194,11 @@ int uwsgi_calc_cheaper(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fake algo to allow control with the fifo
|
||||
int uwsgi_cheaper_algo_manual(int can_spawn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
|
||||
@@ -187,7 +234,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
*/
|
||||
|
||||
|
||||
int uwsgi_cheaper_algo_spare(void) {
|
||||
int uwsgi_cheaper_algo_spare(int can_spawn) {
|
||||
|
||||
int i;
|
||||
static uint64_t overload_count = 0;
|
||||
@@ -211,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) {
|
||||
healthy:
|
||||
|
||||
// are we overloaded ?
|
||||
if (overload_count > uwsgi.cheaper_overload) {
|
||||
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("overloaded !!!\n");
|
||||
@@ -279,7 +326,7 @@ healthy:
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_cheaper_algo_backlog(void) {
|
||||
int uwsgi_cheaper_algo_backlog(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
@@ -288,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) {
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int) uwsgi.cheaper_overload) {
|
||||
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
@@ -326,23 +373,30 @@ void uwsgi_reload(char **argv) {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
if (!uwsgi.master_is_reforked) {
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("fork()'ing uWSGI...\n");
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
@@ -351,6 +405,9 @@ void uwsgi_reload(char **argv) {
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
@@ -385,6 +442,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) {
|
||||
@@ -413,6 +476,13 @@ void uwsgi_reload(char **argv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef UWSGI_IPCSEM_ATEXIT
|
||||
// free ipc semaphores if in use
|
||||
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_ipcsem_clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
@@ -513,6 +583,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
|
||||
@@ -521,6 +592,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
// the workers is not accepting (obviously)
|
||||
uwsgi.workers[wid].accepting = 0;
|
||||
// we count the respawns before errors...
|
||||
uwsgi.workers[wid].respawn_count++;
|
||||
// ... same for update time
|
||||
@@ -630,178 +703,6 @@ int uwsgi_respawn_worker(int wid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = ucron->minute;
|
||||
uc_hour = ucron->hour;
|
||||
uc_day = ucron->day;
|
||||
uc_month = ucron->month;
|
||||
uc_week = ucron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day >= 0 && ucron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
uc_minute = current_cron->minute;
|
||||
uc_hour = current_cron->hour;
|
||||
uc_day = current_cron->day;
|
||||
uc_month = current_cron->month;
|
||||
uc_week = current_cron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (current_cron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (current_cron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (current_cron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (current_cron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job > 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
int i;
|
||||
@@ -852,11 +753,20 @@ 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;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
|
||||
}
|
||||
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 - 1)))
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
|
||||
goto end;
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
@@ -940,7 +850,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
|
||||
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
@@ -960,6 +873,70 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
struct uwsgi_metric *um = uwsgi.metrics;
|
||||
while(um) {
|
||||
int64_t um_val = *um->value;
|
||||
|
||||
if (uwsgi_stats_key(us, um->name)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_open(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_close(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
um = um->next;
|
||||
if (um) {
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_key(us, "sockets"))
|
||||
goto end;
|
||||
|
||||
@@ -1015,6 +992,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
@@ -1154,6 +1133,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
@@ -1232,6 +1214,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) {
|
||||
@@ -1378,7 +1422,7 @@ end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
|
||||
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
|
||||
@@ -1485,3 +1529,135 @@ void uwsgi_master_fix_request_counters() {
|
||||
uwsgi.workers[0].requests = total_counter;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = minute;
|
||||
uc_hour = hour;
|
||||
uc_day = day;
|
||||
uc_month = month;
|
||||
uc_week = week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (day >= 0 && week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return run_task;
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void uwsgi_refork_master() {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("uwsgi_refork_master()/fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
|
||||
return;
|
||||
}
|
||||
|
||||
// detach from the old master
|
||||
setsid();
|
||||
|
||||
uwsgi.master_is_reforked = 1;
|
||||
uwsgi_reload(uwsgi.argv);
|
||||
// never here
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_increase() {
|
||||
uwsgi.cheaper_fifo_delta++;
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_decrease() {
|
||||
uwsgi.cheaper_fifo_delta--;
|
||||
}
|
||||
|
||||
void uwsgi_go_cheap() {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
if (uwsgi.status.is_cheap) return;
|
||||
uwsgi_log_verbose("going cheap...\n");
|
||||
uwsgi.status.is_cheap = 1;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_go_cheap()/waitpid()");
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
+978
-42
File diff suppressed because it is too large
Load Diff
+254
@@ -0,0 +1,254 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
|
||||
|
||||
to simplify setups (expecially because the mount command could not be available in
|
||||
the initial phase of jailing, we need an api to mount/umount filesystems
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, int flags);
|
||||
int uwsgi_umount(char *where, int flags);
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
char *key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_BIND
|
||||
{"bind", MS_BIND},
|
||||
#endif
|
||||
#ifdef MS_DIRSYNC
|
||||
{"dirsync", MS_DIRSYNC},
|
||||
#endif
|
||||
#ifdef MS_MANDLOCK
|
||||
{"mandlock", MS_MANDLOCK},
|
||||
#endif
|
||||
#ifdef MS_MOVE
|
||||
{"move", MS_MOVE},
|
||||
#endif
|
||||
#ifdef MS_NOATIME
|
||||
{"noatime", MS_NOATIME},
|
||||
#endif
|
||||
#ifdef MS_NODEV
|
||||
{"nodev", MS_NODEV},
|
||||
#endif
|
||||
#ifdef MS_NOEXEC
|
||||
{"noexec", MS_NOEXEC},
|
||||
#endif
|
||||
#ifdef MS_RDONLY
|
||||
{"rdonly", MS_RDONLY},
|
||||
{"readonly", MS_RDONLY},
|
||||
{"ro", MS_RDONLY},
|
||||
#endif
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
#ifdef MNT_FORCE
|
||||
{"force", MNT_FORCE},
|
||||
#endif
|
||||
#ifdef MNT_DETACH
|
||||
{"detach", MNT_DETACH},
|
||||
#endif
|
||||
#ifdef MS_REC
|
||||
{"rec", MS_REC},
|
||||
{"recursive", MS_REC},
|
||||
#endif
|
||||
#ifdef MS_PRIVATE
|
||||
{"private", MS_PRIVATE},
|
||||
#endif
|
||||
#ifdef MS_SHARED
|
||||
{"shared", MS_SHARED},
|
||||
#endif
|
||||
#ifdef MNT_RDONLY
|
||||
{"rdonly", MNT_RDONLY},
|
||||
{"readonly", MNT_RDONLY},
|
||||
{"ro", MNT_RDONLY},
|
||||
#endif
|
||||
#ifdef MNT_NOEXEC
|
||||
{"noexec", MNT_NOEXEC},
|
||||
#endif
|
||||
#ifdef MNT_NOSUID
|
||||
{"nosuid", MNT_NOSUID},
|
||||
#endif
|
||||
#ifdef MNT_NOATIME
|
||||
{"noatime", MNT_NOATIME},
|
||||
#endif
|
||||
#ifdef MNT_SNAPSHOT
|
||||
{"snapshot", MNT_SNAPSHOT},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
struct uwsgi_mount_flag *umf = umflags;
|
||||
while(umf->key) {
|
||||
if (!strcmp(umf->key, mflag)) return umf->value;
|
||||
umf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown mount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
iov[1].iov_base = fs;
|
||||
iov[1].iov_len = strlen(fs) + 1;
|
||||
|
||||
iov[2].iov_base = "fspath";
|
||||
iov[2].iov_len = 7;
|
||||
iov[3].iov_base = where;
|
||||
iov[3].iov_len = strlen(where) + 1;
|
||||
|
||||
iov[4].iov_base = "target";
|
||||
iov[4].iov_len = 7;
|
||||
iov[5].iov_base = what;
|
||||
iov[5].iov_len = strlen(what) + 1;
|
||||
|
||||
return nmount(iov, 6, (int) mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount(char *where, char *flags) {
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown umount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
// we need a special case for recursive umount
|
||||
if (mountflags & MS_REC) {
|
||||
mountflags &= ~MS_REC;
|
||||
int unmounted = 1;
|
||||
char *slashed = uwsgi_concat2(where, "/");
|
||||
while (unmounted) {
|
||||
unmounted = 0;
|
||||
FILE *procmounts = fopen("/proc/self/mounts", "r");
|
||||
if (!procmounts) {
|
||||
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
char line[1024];
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
char *delim0 = strchr(line, ' ');
|
||||
if (!delim0) continue;
|
||||
delim0++;
|
||||
char *delim1 = strchr(delim0, ' ');
|
||||
if (!delim1) continue;
|
||||
*delim1 = 0;
|
||||
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
|
||||
continue;
|
||||
unmountable:
|
||||
if (!umount2(delim0, mountflags)) unmounted++;
|
||||
}
|
||||
fclose(procmounts);
|
||||
}
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
return unmount(where, mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_mount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *fs = tmp_arg;
|
||||
char *what = strchr(fs, ' ');
|
||||
if (!what) goto error;
|
||||
*what = 0; what++;
|
||||
char *where = strchr(what, ' ');
|
||||
if (!where) goto error;
|
||||
*where = 0; where++;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
error:
|
||||
free(tmp_arg);
|
||||
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *where = tmp_arg;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_umount(where, flags)) {
|
||||
uwsgi_error("uwsgi_umount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_check_mountpoint(char *mountpoint) {
|
||||
#ifdef __linux__
|
||||
struct statfs sfs;
|
||||
int ret = statfs(mountpoint, &sfs);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
uwsgi_log("this platform does not support mountpoints check !!!\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
+26
-21
@@ -77,19 +77,9 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
|
||||
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 +88,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 +417,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;
|
||||
|
||||
@@ -441,14 +448,14 @@ void uwsgi_setup_mules_and_farms() {
|
||||
mules_list++;
|
||||
|
||||
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
|
||||
free(farm_value);
|
||||
|
||||
|
||||
// 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) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mules_list, ",", p, ctx) {
|
||||
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
|
||||
if (!um) {
|
||||
uwsgi_log("invalid mule id: %s\n", p);
|
||||
@@ -456,13 +463,11 @@ void uwsgi_setup_mules_and_farms() {
|
||||
}
|
||||
|
||||
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
|
||||
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
|
||||
|
||||
farm_name = farm_name->next;
|
||||
|
||||
free(farm_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
+153
-4
@@ -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,13 +99,13 @@ 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;
|
||||
}
|
||||
|
||||
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
|
||||
uor->fd = uwsgi_connect(uor->name, 0, 1);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error("u_offload_transfer_prepare()/connect()");
|
||||
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
|
||||
@@ -257,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
|
||||
return 0;
|
||||
}
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+27
-6
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
if (!strcmp(p, "requires")) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
if (!plugin_already_loaded(equal+1)) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
@@ -24,7 +26,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 +35,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 +43,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 +55,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 +63,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 +100,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 +165,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) {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
|
||||
|
||||
/*
|
||||
|
||||
steps:
|
||||
|
||||
mkdir(.uwsgi_plugin_builder)
|
||||
generate .uwsgi_plugin_builder/uwsgi.h
|
||||
generate .uwsgi_plugin_builder/uwsgiconfig.py
|
||||
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
|
||||
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
|
||||
|
||||
*/
|
||||
|
||||
void uwsgi_build_plugin(char *directory) {
|
||||
|
||||
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
|
||||
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
|
||||
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *dot_h = uwsgi_get_dot_h();
|
||||
if (!dot_h) {
|
||||
uwsgi_log("unable to generate uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(dot_h) == 0) {
|
||||
free(dot_h);
|
||||
uwsgi_log("invalid uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (dot_h_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
|
||||
free(dot_h);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
|
||||
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *config_py = uwsgi_get_config_py();
|
||||
if (!config_py) {
|
||||
uwsgi_log("unable to generate uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(config_py) == 0) {
|
||||
uwsgi_log("invalid uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (config_py_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t config_py_len = (ssize_t) strlen(config_py);
|
||||
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *cflags = uwsgi_get_cflags();
|
||||
if (!cflags) {
|
||||
uwsgi_log("unable to find cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (strlen(cflags) == 0) {
|
||||
uwsgi_log("invalid cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
|
||||
uwsgi_error("uwsgi_build_plugin()/setenv()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// now run the python script
|
||||
char *argv[6];
|
||||
|
||||
argv[0] = getenv("PYTHON");
|
||||
if (!argv[0]) argv[0] = "python";
|
||||
|
||||
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
|
||||
argv[2] = "--extra-plugin";
|
||||
char *space = strchr(directory, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
argv[3] = directory;
|
||||
argv[4] = space+1;
|
||||
argv[5] = NULL;
|
||||
}
|
||||
else {
|
||||
argv[3] = directory;
|
||||
argv[4] = NULL;
|
||||
}
|
||||
|
||||
execvp(argv[0], argv);
|
||||
// never here...
|
||||
_exit(1);
|
||||
}
|
||||
+2
-2
@@ -739,7 +739,7 @@ next:
|
||||
// check if data are available in the local cache
|
||||
if (wsgi_req->cache_get_len > 0) {
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -750,7 +750,7 @@ next:
|
||||
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
|
||||
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
|
||||
uwsgi.queue_header->pos = 0;
|
||||
uwsgi.queue_header->pull_pos = 0;
|
||||
}
|
||||
if (!uwsgi.queue) {
|
||||
if (uwsgi.queue == MAP_FAILED) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+69
-12
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
|
||||
struct pollfd upoll[2];
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll[0].fd = fd0;
|
||||
upoll[0].events = POLLIN;
|
||||
upoll[0].revents = 0;
|
||||
|
||||
upoll[1].fd = fd1;
|
||||
upoll[1].events = POLLIN;
|
||||
upoll[1].revents = 0;
|
||||
|
||||
int ret = poll(upoll, 2, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll[0].revents & POLLIN) {
|
||||
*fd = fd0;
|
||||
return 1;
|
||||
}
|
||||
if (upoll[1].revents & POLLIN) {
|
||||
*fd = fd1;
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
seek()/rewind() language-independent implementations.
|
||||
*/
|
||||
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
if (wsgi_req->post_file) {
|
||||
if (pos < 0) {
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
@@ -95,7 +130,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("consume_body_for_readline()/realloc()");
|
||||
uwsgi_req_error("consume_body_for_readline()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_readline_buf = tmp_buf;
|
||||
@@ -114,7 +149,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
uwsgi_req_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += remains;
|
||||
@@ -140,6 +175,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
@@ -147,6 +183,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -159,6 +196,7 @@ wait:
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
@@ -167,6 +205,7 @@ wait:
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -204,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
|
||||
wsgi_req->post_readline_buf = malloc(amount);
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
uwsgi_error("uwsgi_request_body_readline()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -217,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
|
||||
|
||||
if (consume_body_for_readline(wsgi_req)) {
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -272,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (avail > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
@@ -320,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
wsgi_req->post_read_buf = malloc(remains);
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -331,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -348,7 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/fread()");
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
*rlen += remains;
|
||||
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wait:
|
||||
@@ -389,6 +435,8 @@ wait:
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
|
||||
goto wait;
|
||||
}
|
||||
*rlen = -1;
|
||||
if (len == 0) {
|
||||
@@ -396,6 +444,7 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -407,6 +456,7 @@ wait:
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -445,6 +495,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -460,6 +511,7 @@ wait:
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -478,9 +530,10 @@ 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_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -516,6 +569,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -529,11 +583,13 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -541,7 +597,8 @@ wait:
|
||||
|
||||
write:
|
||||
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
+729
-110
File diff suppressed because it is too large
Load Diff
+41
-13
@@ -1,8 +1,8 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
|
||||
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
|
||||
|
||||
struct uwsgi_rpc *urpc;
|
||||
int ret = -1;
|
||||
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
||||
already:
|
||||
memcpy(urpc->name, name, strlen(name));
|
||||
urpc->modifier1 = modifier1;
|
||||
urpc->plugin = plugin;
|
||||
urpc->args = args;
|
||||
urpc->func = func;
|
||||
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
||||
@@ -59,11 +59,11 @@ already:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
||||
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
|
||||
|
||||
struct uwsgi_rpc *urpc = NULL;
|
||||
uint64_t i;
|
||||
uint16_t ret = 0;
|
||||
uint64_t ret = 0;
|
||||
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max);
|
||||
|
||||
@@ -77,16 +77,23 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
}
|
||||
|
||||
if (urpc) {
|
||||
if (uwsgi.p[urpc->modifier1]->rpc) {
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
|
||||
if (urpc->plugin->rpc) {
|
||||
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
|
||||
size_t *r = (size_t *) data;
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
|
||||
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
|
||||
*r = uwsgi_str_num(value, vl);
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(UMAX16);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
|
||||
if (*buffer)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
// ok the reuqest is ready, let's send it in non blocking way
|
||||
// ok the request is ready, let's send it in non blocking way
|
||||
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// ok time to wait for the response in non blocking way
|
||||
size_t rlen = buffer_size+4;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uint8_t modifier2 = 0;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, &modifier2)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// 64bit response ?
|
||||
if (modifier2 == 5) {
|
||||
size_t content_len = 0;
|
||||
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
|
||||
|
||||
if (content_len > rlen) {
|
||||
char *tmp_buf = realloc(buffer, content_len);
|
||||
if (!tmp_buf) goto error;
|
||||
buffer = tmp_buf;
|
||||
}
|
||||
|
||||
rlen = content_len;
|
||||
|
||||
// read the raw value from the socket
|
||||
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
|
||||
+48
-8
@@ -4,26 +4,30 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
// sendfile() abstraction
|
||||
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
|
||||
if (uwsgi.disable_sendfile) goto no_sendfile;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sf_len = 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;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#else
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
if (pos > 0) {
|
||||
if (lseek(filefd, pos, SEEK_SET)) {
|
||||
if (lseek(filefd, pos, SEEK_SET) < 0) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/seek()");
|
||||
return -1;
|
||||
}
|
||||
@@ -34,6 +38,42 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
return write(sockfd, buf, rlen);
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
|
||||
//now close all the unbound fd
|
||||
for (j = 3; j < (int) uwsgi.max_fd; j++) {
|
||||
int useless = 1;
|
||||
|
||||
if (uwsgi_fd_is_safe(j)) continue;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (j == uwsgi.emperor_fd)
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is an high-performance memory area shared by all workers/cores/threads
|
||||
|
||||
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
|
||||
|
||||
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
|
||||
the language object.
|
||||
|
||||
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
|
||||
|
||||
You can configure multiple areas specifying multiple --sharedarea options
|
||||
|
||||
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
|
||||
if (id > uwsgi.sharedareas_cnt-1) return NULL;
|
||||
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
|
||||
if (pos > sa->max_pos) return NULL;
|
||||
return sa;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_update(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
sa->updates++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_rlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_wlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_unlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
if (len == 0) len = (sa->max_pos + 1) - pos;
|
||||
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
|
||||
uwsgi_rlock(sa->lock);
|
||||
memcpy(blob, sa->area + pos, len);
|
||||
sa->hits++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
memcpy(sa->area + pos, blob, len);
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
|
||||
return rlen == 8 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
|
||||
return rlen == 1 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
|
||||
return rlen == 2 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
|
||||
return rlen == 4 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
returns:
|
||||
0 -> on updates
|
||||
-1 -> on error
|
||||
-2 -> on timeout
|
||||
*/
|
||||
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
int waiting = 0;
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
if (!freq) freq = 100;
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
|
||||
uwsgi.wait_milliseconds_hook(freq);
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
if (sa->updates != updates) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
// unlock sa
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_new_id() {
|
||||
int id = uwsgi.sharedareas_cnt;
|
||||
uwsgi.sharedareas_cnt++;
|
||||
if (!uwsgi.sharedareas) {
|
||||
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
|
||||
}
|
||||
else {
|
||||
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
|
||||
if (!usa) {
|
||||
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas = usa;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
|
||||
return sa;
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = pages;
|
||||
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = area;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_pages = NULL;
|
||||
char *s_file = NULL;
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid sharedarea keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t len = 0;
|
||||
int pages = 0;
|
||||
if (s_size) {
|
||||
len = uwsgi_n64(s_size);
|
||||
pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) pages++;
|
||||
}
|
||||
|
||||
if (s_pages) {
|
||||
pages = atoi(s_pages);
|
||||
}
|
||||
|
||||
char *area = NULL;
|
||||
struct uwsgi_sharedarea *sa = NULL;
|
||||
if (s_file) {
|
||||
}
|
||||
else if (s_fd) {
|
||||
}
|
||||
else if (s_ptr) {
|
||||
}
|
||||
|
||||
if (pages) {
|
||||
if (!area) {
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pages) free(s_pages);
|
||||
if (s_file) free(s_file);
|
||||
if (s_fd) free(s_fd);
|
||||
if (s_ptr) free(s_ptr);
|
||||
if (s_size) free(s_size);
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sharedareas_init() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
|
||||
char *is_keyval = strchr(usl->value, '=');
|
||||
if (!is_keyval) {
|
||||
uwsgi_sharedarea_init(atoi(usl->value));
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_keyval(usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-58
@@ -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");
|
||||
@@ -203,63 +206,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
|
||||
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));
|
||||
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value + i;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
@@ -355,8 +301,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
uwsgi.shared->unrouted_signals++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi.shared->routed_signals++;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
+55
-14
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
|
||||
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
|
||||
|
||||
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
uwsgi_debug("SNMP version: %d\n", version);
|
||||
#endif
|
||||
|
||||
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
|
||||
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
|
||||
if (*ptr != SNMP_STRING)
|
||||
return;
|
||||
ptr++;
|
||||
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
ptr++;
|
||||
|
||||
oidlen = *ptr;
|
||||
if (oidlen != 11)
|
||||
if (oidlen < 11)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
|
||||
oid_part[0] = *ptr;
|
||||
|
||||
if (oid_part[0] != 1 && oid_part[0] != 2)
|
||||
return;
|
||||
ptr++;
|
||||
// old-style SNMP metrics
|
||||
if (oid_part[0] == 1 || oid_part[0] == 2) {
|
||||
ptr++;
|
||||
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
// metrics subsystem
|
||||
else {
|
||||
size_t metric_asn_len = oidlen - 9;
|
||||
char *metric_asn = (char *) ptr;
|
||||
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
|
||||
if (!um) return;
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int64_t value = *um->value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
|
||||
if (size > 0) {
|
||||
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
uint8_t tlen;
|
||||
int i, j;
|
||||
uint8_t *ptr = (uint8_t *) & snmp_val;
|
||||
int32_t val32 = (int32_t) snmp_val;
|
||||
|
||||
// check for counter, counter64 or gauge
|
||||
|
||||
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
}
|
||||
else {
|
||||
tlen = 4;
|
||||
ptr = (uint8_t *) &val32;
|
||||
}
|
||||
|
||||
buffer[0] = tlen;
|
||||
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
|
||||
|
||||
}
|
||||
|
||||
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
|
||||
uint8_t oid_sz;
|
||||
|
||||
if (type == UWSGI_METRIC_GAUGE) {
|
||||
buffer[size - 2] = SNMP_GAUGE;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
|
||||
}
|
||||
else {
|
||||
buffer[size - 2] = SNMP_COUNTER64;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
|
||||
}
|
||||
|
||||
if (oid_sz < 1)
|
||||
return -1;
|
||||
|
||||
oid_sz--;
|
||||
|
||||
buffer[1] += oid_sz;
|
||||
*seq1 += oid_sz;
|
||||
*seq2 += oid_sz;
|
||||
*seq3 += oid_sz;
|
||||
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
|
||||
uwsgi.snmp = 1;
|
||||
if (value) {
|
||||
|
||||
+175
-133
@@ -2,6 +2,26 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int connect_to_unix(char *, int, int);
|
||||
static int connect_to_tcp(char *, int, int, int);
|
||||
static int connect_to_udp(char *, int);
|
||||
|
||||
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
|
||||
if (!protocol) protocol = "uwsgi";
|
||||
struct uwsgi_protocol *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(protocol, up->name)) {
|
||||
up->func(uwsgi_sock);
|
||||
return;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to find protocol %s\n", protocol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
@@ -70,7 +90,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));
|
||||
@@ -183,6 +203,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
@@ -312,36 +340,46 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_connect_do(char *socket_name, int timeout, int async) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
return connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
}
|
||||
|
||||
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
|
||||
|
||||
int fd;
|
||||
|
||||
char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
|
||||
fd = uwsgi_connect(zeroed_socket_name, timeout, async);
|
||||
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_connect(char *socket_name, int timeout, int async) {
|
||||
|
||||
int ret;
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
ret = connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
// reset the socket name
|
||||
tcp_port--;
|
||||
tcp_port[0] = ':';
|
||||
return ret;
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
int uwsgi_connect_udp(char *socket_name) {
|
||||
int fd = -1;
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
char *udp_port = strchr(zeroed_socket_name, ':');
|
||||
if (!udp_port) goto end;
|
||||
*udp_port = 0;
|
||||
udp_port++;
|
||||
fd = connect_to_udp(zeroed_socket_name, atoi(udp_port));
|
||||
end:
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_un uws_addr;
|
||||
@@ -386,7 +424,7 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_in uws_addr;
|
||||
@@ -403,15 +441,13 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
socket_name[strlen(socket_name)] = ':';
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_error("connect_to_tcp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -427,6 +463,38 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
static int connect_to_udp(char *socket_name, int port) {
|
||||
|
||||
struct sockaddr_in uws_addr;
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("connect_to_udp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *generate_socket_name(char *socket_name) {
|
||||
|
||||
char *asterisk = strchr(socket_name, '*');
|
||||
@@ -1314,7 +1382,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
|
||||
}
|
||||
else if (uwsgi_sock->fd > -1) {
|
||||
@@ -1508,6 +1576,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
|
||||
@@ -1598,8 +1669,8 @@ void uwsgi_map_sockets() {
|
||||
}
|
||||
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
|
||||
enabled = 0;
|
||||
char *p = strtok(colon + 1, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
|
||||
int w = atoi(p);
|
||||
if (w < 1 || w > uwsgi.numproc) {
|
||||
uwsgi_log("invalid worker num: %d\n", w);
|
||||
@@ -1610,7 +1681,6 @@ void uwsgi_map_sockets() {
|
||||
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
|
||||
break;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1619,18 +1689,7 @@ void uwsgi_map_sockets() {
|
||||
|
||||
if (!enabled) {
|
||||
close(uwsgi_sock->fd);
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (fd != uwsgi_sock->fd) {
|
||||
if (dup2(fd, uwsgi_sock->fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
|
||||
uwsgi_sock->disabled = 1;
|
||||
}
|
||||
|
||||
@@ -1660,6 +1719,10 @@ void uwsgi_bind_sockets() {
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
|
||||
char *tcp_port = strrchr(uwsgi_sock->name, ':');
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
if (uwsgi_sock->no_defer) {
|
||||
uwsgi.no_defer_accept = 1;
|
||||
}
|
||||
if (tcp_port == NULL) {
|
||||
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -1667,6 +1730,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
|
||||
@@ -1689,6 +1756,7 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
@@ -1734,7 +1802,8 @@ void uwsgi_bind_sockets() {
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
uwsgi_log("WARNING: unable to remap stdin, /dev/null not available\n");
|
||||
goto stdin_done;
|
||||
}
|
||||
if (fd != 0) {
|
||||
if (dup2(fd, 0) < 0) {
|
||||
@@ -1752,6 +1821,8 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
}
|
||||
|
||||
stdin_done:
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1798,96 +1869,8 @@ void uwsgi_set_sockets_protocols() {
|
||||
|
||||
|
||||
setup_proto:
|
||||
if (!requested_protocol) {
|
||||
requested_protocol = uwsgi.protocol;
|
||||
}
|
||||
|
||||
if (requested_protocol && !strcmp("http", requested_protocol)) {
|
||||
uwsgi_sock->proto = uwsgi_proto_http_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
|
||||
uwsgi.zeromq = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
if (!requested_protocol) requested_protocol = uwsgi.protocol;
|
||||
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
@@ -1904,3 +1887,62 @@ void uwsgi_tcp_nodelay(int fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_accept(int server_fd) {
|
||||
struct sockaddr_un client_src;
|
||||
memset(&client_src, 0, sizeof(struct sockaddr_un));
|
||||
socklen_t client_src_len = 0;
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
return accept4(server_fd, (struct sockaddr *) &client_src, &client_src_len, SOCK_NONBLOCK);
|
||||
#elif defined(__linux__)
|
||||
int client_fd = accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd >= 0) {
|
||||
uwsgi_socket_nb(client_fd);
|
||||
}
|
||||
return client_fd;
|
||||
#else
|
||||
return accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
|
||||
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(name, up->name)) {
|
||||
goto found;
|
||||
}
|
||||
old_up = up;
|
||||
up = up->next;
|
||||
}
|
||||
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
|
||||
up->name = name;
|
||||
if (old_up) {
|
||||
old_up->next = up;
|
||||
}
|
||||
else {
|
||||
uwsgi.protocols = up;
|
||||
}
|
||||
found:
|
||||
up->func = func;
|
||||
return up;
|
||||
}
|
||||
|
||||
void uwsgi_protocols_register() {
|
||||
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
|
||||
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
|
||||
|
||||
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
|
||||
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
|
||||
#endif
|
||||
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
|
||||
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
|
||||
|
||||
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
|
||||
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
|
||||
|
||||
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
|
||||
}
|
||||
|
||||
+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);
|
||||
|
||||
+25
-4
@@ -1,5 +1,7 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
/*
|
||||
@@ -69,7 +71,11 @@ SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen,
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
|
||||
#else
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
|
||||
#endif
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return sess;
|
||||
}
|
||||
@@ -252,8 +258,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
|
||||
if (!uwsgi.ssl_sessions_cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
// check for default cache
|
||||
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
|
||||
uwsgi.ssl_sessions_cache = uwsgi.caches;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.ssl_sessions_cache->max_items) {
|
||||
@@ -406,8 +418,9 @@ char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
|
||||
}
|
||||
|
||||
char *uwsgi_ssl_rand(size_t len) {
|
||||
unsigned char *buf = uwsgi_calloc(len+1);
|
||||
unsigned char *buf = uwsgi_calloc(len);
|
||||
if (RAND_bytes(buf, len) <= 0) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
return (char *) buf;
|
||||
@@ -421,6 +434,14 @@ char *uwsgi_sha1(char *src, size_t len, char *dst) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_md5(char *src, size_t len, char *dst) {
|
||||
MD5_CTX md5;
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, src, len);
|
||||
MD5_Final((unsigned char *)dst, &md5);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
|
||||
SHA_CTX sha;
|
||||
SHA1_Init(&sha);
|
||||
|
||||
+42
-33
@@ -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,19 +43,19 @@ 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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_http_date(time_t t, char *dst) {
|
||||
int uwsgi_http_date(time_t t, char *dst) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -431,14 +440,12 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
int use_gzip = 0;
|
||||
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
// 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 (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
@@ -451,6 +458,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
@@ -462,7 +470,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0 ;
|
||||
fsize = 0;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
@@ -483,6 +491,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_add_expires_uri(wsgi_req, st);
|
||||
#endif
|
||||
|
||||
if (use_gzip) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
|
||||
@@ -497,29 +509,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// apache
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// raw
|
||||
else {
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
// set Content-Length (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use teh original size !!!
|
||||
// here use the original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
|
||||
}
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
// if it is a HEAD request just skip transfer
|
||||
@@ -571,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;
|
||||
}
|
||||
@@ -636,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;
|
||||
|
||||
+18
-45
@@ -440,6 +440,11 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(1);
|
||||
for (;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
|
||||
if (nevents < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
uwsgi_log_verbose("ending the stats pusher thread...\n");
|
||||
return;
|
||||
}
|
||||
if (nevents > 0) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, 0);
|
||||
char buf[4096];
|
||||
@@ -457,7 +462,8 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
struct uwsgi_stats *us = NULL;
|
||||
while (uspi) {
|
||||
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
|
||||
if ((uspi->last_run + delta) <= now) {
|
||||
if (((uspi->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
|
||||
if (uspi->needs_retry) uspi->retries++;
|
||||
if (uspi->raw) {
|
||||
uspi->pusher->func(uspi, now, NULL, 0);
|
||||
}
|
||||
@@ -470,6 +476,17 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
uspi->pusher->func(uspi, now, us->base, us->pos);
|
||||
}
|
||||
uspi->last_run = now;
|
||||
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
|
||||
uspi->next_retry = now + uspi->retry_delay;
|
||||
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
|
||||
uspi->needs_retry = 0;
|
||||
uspi->retries = 0;
|
||||
} else if (uspi->retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
|
||||
uspi->retries = 0;
|
||||
}
|
||||
}
|
||||
next:
|
||||
uspi = uspi->next;
|
||||
@@ -531,50 +548,6 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
return pusher;
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher_file_conf {
|
||||
char *path;
|
||||
char *freq;
|
||||
char *separator;
|
||||
};
|
||||
|
||||
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
|
||||
if (!uspi->configured) {
|
||||
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
|
||||
if (uspi->arg) {
|
||||
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
|
||||
free(uspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!uspic->path)
|
||||
uspic->path = "uwsgi.stats";
|
||||
if (!uspic->separator)
|
||||
uspic->separator = "\n\n";
|
||||
if (uspic->freq)
|
||||
uspi->freq = atoi(uspic->freq);
|
||||
uspi->configured = 1;
|
||||
uspi->data = uspic;
|
||||
}
|
||||
|
||||
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uspic->path);
|
||||
return;
|
||||
}
|
||||
ssize_t rlen = write(fd, json, json_len);
|
||||
if (rlen != (ssize_t) json_len) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
rlen = write(fd, uspic->separator, strlen(uspic->separator));
|
||||
if (rlen != (ssize_t) strlen(uspic->separator)) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
|
||||
+145
@@ -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;
|
||||
@@ -338,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
|
||||
return buf - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
status 0: append mode
|
||||
status 1: single quote found
|
||||
status 2: double quote found
|
||||
status 3: backslash found (on 0)
|
||||
status 4: backslash found (on 1)
|
||||
status 5: backslash found (on 2)
|
||||
|
||||
*/
|
||||
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
|
||||
size_t i;
|
||||
int status = 0;
|
||||
char *base = uwsgi_concat2n(what, what_len, "", 0);
|
||||
char *item = NULL;
|
||||
char *ptr = NULL;
|
||||
*rlen = 0;
|
||||
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
|
||||
|
||||
for(i=0;i<what_len;i++) {
|
||||
if (!item) {
|
||||
item = uwsgi_malloc((what_len - i)+1);
|
||||
ptr = item;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
if (base[i] == '\\') {
|
||||
status = 3;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 2;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 1;
|
||||
}
|
||||
else if (strchr(sep, base[i])) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
item = NULL;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash
|
||||
if (status == 3) {
|
||||
*ptr++= base[i];
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// single quote
|
||||
if (status == 1) {
|
||||
if (base[i] == '\\') {
|
||||
status = 4;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// double quote
|
||||
if (status == 2) {
|
||||
if (base[i] == '\\') {
|
||||
status = 5;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash single quote
|
||||
if (status == 4) {
|
||||
*ptr++= base[i];
|
||||
status = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash double quote
|
||||
if (status == 5) {
|
||||
*ptr++= base[i];
|
||||
status = 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (item) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
}
|
||||
|
||||
free(base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -812,6 +812,8 @@ end:
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
if (!uwsgi.subscriptions_blocked) return;
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
uWSGI transformations
|
||||
|
||||
each body chunk is passed (in chain) to every transformation
|
||||
|
||||
some of them supports streaming, other requires buffering
|
||||
|
||||
at the end of the request the "final chain" is called (and the whole chain freed)
|
||||
|
||||
Transformations (if required) could completely swallow already set headers
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// -1 error, 0 = no buffer, send the body, 1 = buffer
|
||||
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
char *t_buf = buf;
|
||||
size_t t_len = len;
|
||||
uint8_t flushed = 0;
|
||||
while(ut) {
|
||||
// allocate the buffer (if needed)
|
||||
if (!ut->chunk) {
|
||||
ut->chunk = uwsgi_buffer_new(t_len);
|
||||
}
|
||||
// skip final transformations before appending data
|
||||
if (ut->is_final) goto next;
|
||||
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if the transformation cannot stream, continue buffering (the func will be called at the end)
|
||||
if (!ut->can_stream) return 1;
|
||||
|
||||
ut->round++;
|
||||
if (ut->func(wsgi_req, ut)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ut->flushed) flushed = 1;
|
||||
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
// we reset the buffer, so we do not waste memory
|
||||
ut->chunk->pos = 0;
|
||||
next:
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
// if we are here we can tell the writer to send the body to the client
|
||||
// no buffering please
|
||||
if (!flushed) {
|
||||
wsgi_req->transformed_chunk = t_buf;
|
||||
wsgi_req->transformed_chunk_len = t_len;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
run all the remaining (or buffered) transformations
|
||||
|
||||
*/
|
||||
int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
char *t_buf = NULL;
|
||||
size_t t_len = 0;
|
||||
uint8_t flushed = 0;
|
||||
int found_nostream = 0;
|
||||
while(ut) {
|
||||
if (!found_nostream) {
|
||||
if (!ut->can_stream) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ut->chunk) {
|
||||
if (t_len > 0) {
|
||||
ut->chunk = uwsgi_buffer_new(t_len);
|
||||
}
|
||||
else {
|
||||
ut->chunk = uwsgi_buffer_new(uwsgi.page_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (t_len > 0) {
|
||||
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// run the transformation
|
||||
ut->round++;
|
||||
if (ut->func(wsgi_req, ut)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ut->flushed) flushed = 1;
|
||||
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
next:
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
// if we are here, all of the transformations are applied
|
||||
if (!flushed) {
|
||||
wsgi_req->transformed_chunk = t_buf;
|
||||
wsgi_req->transformed_chunk_len = t_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
struct uwsgi_transformation *current_ut = ut;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_transformation *), void *data) {
|
||||
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
old_ut = ut;
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
|
||||
ut->func = func;
|
||||
ut->fd = -1;
|
||||
ut->data = data;
|
||||
|
||||
if (old_ut) {
|
||||
old_ut->next = ut;
|
||||
}
|
||||
else {
|
||||
wsgi_req->transformations = ut;
|
||||
}
|
||||
|
||||
return ut;
|
||||
}
|
||||
+1493
-993
File diff suppressed because it is too large
Load Diff
+1039
-369
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user