mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c53f26cbd | ||
|
|
a5c74293d8 | ||
|
|
e5da0fc28c | ||
|
|
8e9bcc4758 | ||
|
|
bcf1f46d33 | ||
|
|
8cd13f2ad9 | ||
|
|
13df278cc4 | ||
|
|
56fedbd80c | ||
|
|
c4b563f260 | ||
|
|
39706c5899 | ||
|
|
e45f710694 | ||
|
|
0c86212aa2 | ||
|
|
3cfa743cb5 | ||
|
|
7fbc4013ca | ||
|
|
0324e5965c | ||
|
|
2050d38f96 | ||
|
|
fadce6cfe5 | ||
|
|
0ac4f8f1e4 | ||
|
|
51e81eff31 | ||
|
|
4818a5d386 | ||
|
|
4457fbefd6 | ||
|
|
9780e5fc5e | ||
|
|
9c18e0e12a | ||
|
|
c4c146dca4 | ||
|
|
08e1cf211c | ||
|
|
a52a6fc1e1 | ||
|
|
6e1c468eed | ||
|
|
1c186db72a | ||
|
|
92a8d6f2c5 | ||
|
|
144ffbaa25 | ||
|
|
3e910aaca2 | ||
|
|
5b2a3c28d0 | ||
|
|
01a5611159 | ||
|
|
bf692c4d18 | ||
|
|
a09ee5153d | ||
|
|
bc9f5d6f88 | ||
|
|
ec25be94ba | ||
|
|
7e8e113921 | ||
|
|
0575859f2d | ||
|
|
e9c0bf91ad | ||
|
|
53fb764830 | ||
|
|
76393e36be | ||
|
|
94a39e1755 | ||
|
|
e675b49ef8 | ||
|
|
78b330dd96 | ||
|
|
293ee92791 | ||
|
|
dac7457927 | ||
|
|
e1b3d8fd1a | ||
|
|
b1669d1887 | ||
|
|
095bd60f77 | ||
|
|
c3d33c90a0 | ||
|
|
4905b64f2e | ||
|
|
cfe1e9de7b | ||
|
|
82dcfd338d | ||
|
|
c696065d3c | ||
|
|
8746141afa | ||
|
|
e2b2a16b8c | ||
|
|
406daeb3ae | ||
|
|
acbc073c81 | ||
|
|
2ad23e95dd | ||
|
|
807259f25b | ||
|
|
4b06b2391c | ||
|
|
8c0adef6e7 | ||
|
|
52ea289283 | ||
|
|
bfb6e21e2a | ||
|
|
84d6f54ddd | ||
|
|
775afe1e86 | ||
|
|
cabb5f3e8e | ||
|
|
aae6413cb1 | ||
|
|
6666848ac3 | ||
|
|
c6f1911686 | ||
|
|
ef4ee87fed | ||
|
|
2a2f1a9928 | ||
|
|
f1caa39f51 | ||
|
|
536ffdcc79 | ||
|
|
d3313a39b7 | ||
|
|
89da4a97a6 | ||
|
|
3e41d5927a | ||
|
|
6a32f5d49d | ||
|
|
bf67984049 | ||
|
|
41b6005d30 | ||
|
|
497f7efa55 | ||
|
|
ad7ca0b098 | ||
|
|
1d591c95f2 | ||
|
|
d3daca0b16 | ||
|
|
bae1ade00a | ||
|
|
fd663aedbd | ||
|
|
6b9ce2d755 | ||
|
|
bd2728b391 | ||
|
|
dc250fd7b5 | ||
|
|
0a9345b8d4 | ||
|
|
db509f2d38 | ||
|
|
b12c39607d | ||
|
|
224260ce3e | ||
|
|
5f86d9522f | ||
|
|
a0fafe7847 | ||
|
|
daeaf1b231 | ||
|
|
fbc0a2775f | ||
|
|
d3c89a3f63 | ||
|
|
cd43a0d12d | ||
|
|
f06df71bfc | ||
|
|
eab2472dd0 | ||
|
|
87a2f3585c | ||
|
|
c257a9aa98 | ||
|
|
43aebe2d66 | ||
|
|
309115d611 | ||
|
|
5881d41b2b | ||
|
|
9fe4b7b14a | ||
|
|
930c19210a | ||
|
|
5beb170cfd | ||
|
|
a13103d851 | ||
|
|
bc5a86694f | ||
|
|
812685096b | ||
|
|
f70c070a0f | ||
|
|
accf622ffc | ||
|
|
04173869ee | ||
|
|
509a3c5cd4 | ||
|
|
81ad3a916d | ||
|
|
3f93a0b8e4 | ||
|
|
4408b655a4 | ||
|
|
71a6b8a304 | ||
|
|
7e9069eabf | ||
|
|
6c77dd0e38 | ||
|
|
27e506c72a | ||
|
|
bea68191e3 | ||
|
|
9b207d8a62 | ||
|
|
68d5b2de3b | ||
|
|
3a62573005 | ||
|
|
1c6dd42318 | ||
|
|
73ad0677bd | ||
|
|
15b2cf0712 | ||
|
|
0da0fa211a | ||
|
|
a8ecd71ffd | ||
|
|
ea0a95a441 | ||
|
|
6ac6e58bf7 | ||
|
|
f2c7addb73 | ||
|
|
fff5fa536b | ||
|
|
95825c9b99 | ||
|
|
1e84fcf880 | ||
|
|
0f742a72bf | ||
|
|
fd96a02576 | ||
|
|
77ca76428d | ||
|
|
9ea8f4f07c | ||
|
|
9ffc311177 | ||
|
|
4f89a350aa | ||
|
|
8f18c77587 | ||
|
|
371cafef94 | ||
|
|
89c31e9280 | ||
|
|
418d784148 | ||
|
|
c146275e9b | ||
|
|
eff23382c2 | ||
|
|
d566469c63 | ||
|
|
e008ce5d56 | ||
|
|
9d21c99183 | ||
|
|
7e80927317 | ||
|
|
6664e7120b | ||
|
|
687aabd30b | ||
|
|
fab656c635 | ||
|
|
72c31dab7a | ||
|
|
f19a301b73 | ||
|
|
19a19a8a67 | ||
|
|
d9c9f41624 | ||
|
|
dc97853f9f | ||
|
|
b089774c36 | ||
|
|
f8a271a027 | ||
|
|
ef12aaf13c | ||
|
|
a559361a30 | ||
|
|
6aad281441 | ||
|
|
7604c67018 | ||
|
|
afc962709f | ||
|
|
c11e0654a0 | ||
|
|
6e4f47cc76 | ||
|
|
20c9f0ef40 | ||
|
|
ef3c8a5bd9 | ||
|
|
76d0438fee | ||
|
|
18fd338908 | ||
|
|
2b35e95706 | ||
|
|
4761146599 | ||
|
|
3924cc639e | ||
|
|
5f09de0469 | ||
|
|
4f0e3fb79f | ||
|
|
05b6baf173 | ||
|
|
149823aac4 | ||
|
|
85d86dc10e | ||
|
|
e97d921909 | ||
|
|
c5e20bf4da | ||
|
|
a09d25ccaa | ||
|
|
bf01cea062 | ||
|
|
b6459be3e4 | ||
|
|
d42788c17b | ||
|
|
872730c116 | ||
|
|
6fce0aee84 | ||
|
|
e3d8a02614 | ||
|
|
b58696399e | ||
|
|
519c9f58b3 | ||
|
|
2c77c5c639 | ||
|
|
fb9e5a1891 | ||
|
|
5aa7d1a79f | ||
|
|
bc3442ba29 | ||
|
|
3061e36089 | ||
|
|
4f8c41cf61 | ||
|
|
b0065c379e | ||
|
|
57f71c974d | ||
|
|
b820fefbbd | ||
|
|
5f759f0d26 | ||
|
|
f7eb9ed1cd | ||
|
|
3a82732b19 | ||
|
|
d74e826f71 | ||
|
|
c846a9b388 | ||
|
|
001e4b6e39 | ||
|
|
a51a396f47 | ||
|
|
17965ea870 | ||
|
|
8a032b41ec | ||
|
|
a489cfc2c1 | ||
|
|
3b32672ff9 | ||
|
|
858131ba57 | ||
|
|
8a8d2f8675 | ||
|
|
9d37725323 | ||
|
|
e973492267 | ||
|
|
105a68bce9 | ||
|
|
0587a0ca53 | ||
|
|
d4b259d5e0 | ||
|
|
9e591c587f | ||
|
|
e7cce7b785 | ||
|
|
3285b224c2 | ||
|
|
e4a4942980 | ||
|
|
6f671936fc | ||
|
|
7d1d992d58 | ||
|
|
2bba4cf15a | ||
|
|
930f71c562 | ||
|
|
959bb11f77 | ||
|
|
13d8505738 | ||
|
|
93fe463ca8 | ||
|
|
5c64c21745 | ||
|
|
f825ab542d | ||
|
|
e744aef144 | ||
|
|
4ded485a8e | ||
|
|
2ce5ec3986 | ||
|
|
af95f90fb0 | ||
|
|
7989dc748b | ||
|
|
f85f3e8178 | ||
|
|
97809192c8 | ||
|
|
5f74e6d964 | ||
|
|
ae87fdd0f7 | ||
|
|
36c44c83af | ||
|
|
48e13bfc65 | ||
|
|
16cd55637d | ||
|
|
39cf2887c4 | ||
|
|
671bf8a258 | ||
|
|
89a8ceea81 | ||
|
|
6699f4046e | ||
|
|
88474b3d96 | ||
|
|
32b6463d06 | ||
|
|
63cc29a61d | ||
|
|
d58f79eeab | ||
|
|
7b24d2f5de | ||
|
|
a93db73d0c | ||
|
|
c118c75bfe | ||
|
|
624631d443 | ||
|
|
b681eab385 | ||
|
|
91dfe779ff | ||
|
|
0ad50711c0 | ||
|
|
df6ed26479 | ||
|
|
d08778b39c | ||
|
|
0c8c2932cf | ||
|
|
131bd7da2f | ||
|
|
d247424442 | ||
|
|
332fab2150 | ||
|
|
62d74951db | ||
|
|
839638a0ad | ||
|
|
536ae8d013 | ||
|
|
367c4b9bab | ||
|
|
3965c01880 | ||
|
|
7e4341a7cd | ||
|
|
8c118c8f62 | ||
|
|
5d76b63fac | ||
|
|
b0159ea23b | ||
|
|
d3493df032 | ||
|
|
757c76b569 | ||
|
|
30eebfd335 | ||
|
|
c5d7d30439 | ||
|
|
04bc3e117d | ||
|
|
3480c30674 | ||
|
|
a7e6dfc469 | ||
|
|
5e276b43ad | ||
|
|
9e6a21602a | ||
|
|
952c4ce854 | ||
|
|
951f24e711 | ||
|
|
7bda4c9b63 | ||
|
|
1b25516ced | ||
|
|
b3020e60f9 | ||
|
|
808d37f33a | ||
|
|
8c8a7f77d1 | ||
|
|
3f601af740 | ||
|
|
7b901ab81e | ||
|
|
930eb1e6aa | ||
|
|
77e5931da7 | ||
|
|
3e6ddbb3d5 | ||
|
|
623bce274a | ||
|
|
6c986f8082 | ||
|
|
10a02064ba | ||
|
|
774f5a81a5 | ||
|
|
e270593cc0 | ||
|
|
b559354845 | ||
|
|
46a2fefb04 | ||
|
|
c6c9baa7b5 | ||
|
|
c37710f4c2 | ||
|
|
943c20b88c | ||
|
|
a442614db0 | ||
|
|
5830af37ba | ||
|
|
de4c563169 | ||
|
|
77f008e24c | ||
|
|
df0bd832b4 | ||
|
|
07c42c262f | ||
|
|
cb131836ae | ||
|
|
2c6855a969 | ||
|
|
79ca1940de | ||
|
|
d46879dca9 | ||
|
|
9b889f7b77 | ||
|
|
1128d09187 | ||
|
|
d3d4d04fac | ||
|
|
4a554db63b | ||
|
|
8b799b4f9f | ||
|
|
ef17013945 | ||
|
|
a225d53825 | ||
|
|
d4298469ba | ||
|
|
395de489b8 | ||
|
|
6e6efc5605 | ||
|
|
ce260ecbb6 | ||
|
|
e143e25b3c | ||
|
|
e9a58bac46 | ||
|
|
1448fbc5a3 | ||
|
|
b801f839fc | ||
|
|
bcb8321480 | ||
|
|
5cd9e64073 | ||
|
|
d878b65401 | ||
|
|
ded149fc80 | ||
|
|
f041d1095d | ||
|
|
886842de12 | ||
|
|
b4915f778e | ||
|
|
a25e02bbb3 | ||
|
|
16aec7c44b | ||
|
|
42dfa20f27 | ||
|
|
2092050f00 | ||
|
|
b5a0434710 | ||
|
|
2737cd5c35 | ||
|
|
7a29d9649c | ||
|
|
27cc164ebe | ||
|
|
40be8fc916 | ||
|
|
f219afc6e0 | ||
|
|
f20f72ceb1 | ||
|
|
6555c2804c | ||
|
|
c05082a8e4 | ||
|
|
62dab40a22 | ||
|
|
02e68ae578 | ||
|
|
ba1fb72427 | ||
|
|
df9a76a171 | ||
|
|
98e7e0845d | ||
|
|
6c9f73ae7f | ||
|
|
b12658102d | ||
|
|
c51b74a32b | ||
|
|
b0e6d19d5c | ||
|
|
7ff3584ad7 | ||
|
|
57b6d1f51b | ||
|
|
1646f9c199 | ||
|
|
260b49c3f6 | ||
|
|
58af067bef | ||
|
|
d1285c6dc4 | ||
|
|
d4e9f3a2d4 | ||
|
|
a15de85811 | ||
|
|
4b09ead07d | ||
|
|
338aca9da5 | ||
|
|
3f0b9390d9 | ||
|
|
e14b189c77 | ||
|
|
cabb179a84 | ||
|
|
ad9b48b69e | ||
|
|
08443d5463 | ||
|
|
5d11a5cd77 | ||
|
|
3aba97745c | ||
|
|
0b596bdf42 | ||
|
|
4c4b08c36f | ||
|
|
1f0827abc8 | ||
|
|
2ea67c67df | ||
|
|
8eebc9f400 | ||
|
|
2ad6a1c8e8 | ||
|
|
d39d0e8403 | ||
|
|
2838fffbde | ||
|
|
45bc51541a | ||
|
|
3427a17191 | ||
|
|
0cf61abf9d | ||
|
|
53fde5fcdd | ||
|
|
e81f068e4b | ||
|
|
aaee226183 | ||
|
|
d7bba38d7a | ||
|
|
18fa1172db | ||
|
|
9e95312169 | ||
|
|
216aff3820 | ||
|
|
eae335a43e | ||
|
|
e0cf245a0e | ||
|
|
d463f9e7d9 | ||
|
|
06c62033dd | ||
|
|
72ea5ab54a | ||
|
|
843a3b18ad | ||
|
|
37acca060b | ||
|
|
a0ff5b91b8 | ||
|
|
ea19e1e67b | ||
|
|
c20e3fb1a8 | ||
|
|
a57c2997f4 | ||
|
|
3d051e5d79 | ||
|
|
3b0d18c1ec | ||
|
|
89e04c5d17 | ||
|
|
84ea262203 | ||
|
|
15fa2be4ee | ||
|
|
f18ceea9bf | ||
|
|
e4a993ac31 | ||
|
|
cf2c20418c | ||
|
|
d155197d98 | ||
|
|
fbc1551112 | ||
|
|
b3bba48d1a | ||
|
|
18972d95a8 | ||
|
|
8aa8d6070b | ||
|
|
3f0e9f899a | ||
|
|
00bf0aa713 | ||
|
|
60675724d3 | ||
|
|
b45deb780d | ||
|
|
24e144268b | ||
|
|
b870b8c6d8 | ||
|
|
62be7482d4 | ||
|
|
0c8f473e6f | ||
|
|
8b19fd3f94 | ||
|
|
7553ce3a48 | ||
|
|
9ff67391c0 | ||
|
|
4f4f9b93aa | ||
|
|
51a8f31f17 | ||
|
|
32b7126836 | ||
|
|
4d43a66581 | ||
|
|
0f95ef6d5a | ||
|
|
c0c43a7d47 | ||
|
|
4361ef2dc6 | ||
|
|
b7298aba85 | ||
|
|
0d4172a271 | ||
|
|
e842a181aa | ||
|
|
1ba0935579 | ||
|
|
920d1e5cfe | ||
|
|
473b4f1e57 | ||
|
|
b5c19bc1f8 | ||
|
|
79222adfe7 | ||
|
|
8b90efc567 | ||
|
|
4667eedc2b | ||
|
|
752252c9e4 | ||
|
|
6d91b7317d | ||
|
|
cddd1148fd | ||
|
|
c2096e8373 | ||
|
|
4f57ef33af | ||
|
|
aa34beade1 | ||
|
|
1149e60125 | ||
|
|
7def85636e | ||
|
|
d44692b268 | ||
|
|
46322b84b4 | ||
|
|
5785c61a13 | ||
|
|
594880fb46 | ||
|
|
4373306f78 | ||
|
|
f3e164b397 | ||
|
|
a60bb56b18 | ||
|
|
d08d08f39b | ||
|
|
4c4c2bb0fe | ||
|
|
cf79ce40e4 | ||
|
|
c153c26c18 | ||
|
|
82f5d1f988 | ||
|
|
5de83201ea | ||
|
|
6d69c01651 | ||
|
|
61f3d162a4 | ||
|
|
0a025ef93a | ||
|
|
f0951d3f41 | ||
|
|
f2e4eabf42 | ||
|
|
4fc99b3a3e | ||
|
|
1efb3f4096 | ||
|
|
9c29d6899f | ||
|
|
9a7524b55d | ||
|
|
04dfc3ae19 | ||
|
|
fc10411adb | ||
|
|
2378db4520 | ||
|
|
bdbd484db5 | ||
|
|
a2f6dd4ee2 | ||
|
|
ac001beb41 | ||
|
|
05895c40f7 | ||
|
|
fbf9a5b27c | ||
|
|
9c84e9f6cc | ||
|
|
486796bdf9 | ||
|
|
e795cd8912 | ||
|
|
643fc3019b | ||
|
|
f409e8b501 | ||
|
|
361ec8bcd4 | ||
|
|
ba3ac9ad09 | ||
|
|
419f1801cd | ||
|
|
d3c5ccc061 | ||
|
|
be6f61aa1b | ||
|
|
eb6c35aa95 | ||
|
|
797b14b23e | ||
|
|
44e7be13e2 | ||
|
|
18f6660603 | ||
|
|
c3f64af2df | ||
|
|
2278f98318 | ||
|
|
b4ee27b524 | ||
|
|
85ee422dcb | ||
|
|
15f70b2444 | ||
|
|
b7b126e89f | ||
|
|
56e284e18a | ||
|
|
0d4f4a2411 | ||
|
|
68049a5177 | ||
|
|
fc2355e5be | ||
|
|
49925e95d4 | ||
|
|
bee171e5da | ||
|
|
df809c8e34 | ||
|
|
3b64838324 | ||
|
|
f1f51948eb | ||
|
|
906da5cb9a | ||
|
|
dacad8d9b9 | ||
|
|
39fbea6d48 | ||
|
|
4796f85277 | ||
|
|
01ee66d1f6 | ||
|
|
6c61ac9c7e | ||
|
|
77c279b3a9 | ||
|
|
34430ceac4 | ||
|
|
fd1f79d154 | ||
|
|
56f7d09b2b | ||
|
|
479df7c2cc | ||
|
|
69c41026a4 | ||
|
|
7a305704f1 | ||
|
|
8d44dff97e | ||
|
|
c9324c06ca | ||
|
|
3446c2d322 | ||
|
|
6704d1a95a | ||
|
|
0e539f25cd | ||
|
|
00eb37f724 | ||
|
|
30c6ac8cb8 | ||
|
|
faa13228a5 | ||
|
|
e1941a49b8 | ||
|
|
d32f7b997d | ||
|
|
972333941d | ||
|
|
1691263744 | ||
|
|
debfe5b2b9 | ||
|
|
d2ce28f441 | ||
|
|
b9170b2c85 | ||
|
|
33a6195e44 | ||
|
|
933ef85cf2 | ||
|
|
0b27d41712 | ||
|
|
2124b930fd | ||
|
|
b5a2a89630 | ||
|
|
22bf9b33b0 | ||
|
|
b44c2208d9 | ||
|
|
44136aa572 | ||
|
|
5dd62ef909 | ||
|
|
5ea95c9e89 | ||
|
|
8095a9108c | ||
|
|
1cbc423afc | ||
|
|
4e260fa8a1 | ||
|
|
bb4be12fda | ||
|
|
672fb0eaa6 | ||
|
|
def274f28c | ||
|
|
be9f1578cc | ||
|
|
8d8f3bdc51 | ||
|
|
4d9720e4b5 | ||
|
|
6e2adf9cf3 | ||
|
|
7f004c5d6d | ||
|
|
13e7b53c54 | ||
|
|
1c89522519 |
@@ -7,6 +7,7 @@
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
/core/config_py.c
|
||||
|
||||
/t/ring/target
|
||||
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
- this is a incomplete list of all the contributors of the project -
|
||||
|
||||
Roberto De Ioris, Unbit, <roberto@unbit.it>
|
||||
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
|
||||
Riccardo Magliocchetti
|
||||
Yann Malet, Lincoln Loop
|
||||
Simon Litchfield
|
||||
Masahiro Honma, <hiratara@cpan.org>
|
||||
@@ -25,3 +25,7 @@ Mingli Yuan
|
||||
Natanael Copa
|
||||
Roberto Leandrini
|
||||
Ryan Petrello
|
||||
Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
|
||||
+71
-11
@@ -2,7 +2,7 @@
|
||||
|
||||
*** mod_proxy_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -67,14 +67,19 @@ static int uwsgi_canon(request_rec *r, char *url)
|
||||
}
|
||||
url += sizeof(UWSGI_SCHEME); /* Keep slashes */
|
||||
|
||||
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
|
||||
if (err) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
// is it a unix socket ?
|
||||
if (strlen(url) == 2) {
|
||||
*sport = 0;
|
||||
}
|
||||
else {
|
||||
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
|
||||
if (err) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"error parsing URL %s: %s", url, err);
|
||||
return HTTP_BAD_REQUEST;
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
apr_snprintf(sport, sizeof(sport), ":%u", port);
|
||||
}
|
||||
|
||||
apr_snprintf(sport, sizeof(sport), ":%u", port);
|
||||
|
||||
if (ap_strchr(host, ':')) { /* if literal IPv6 address */
|
||||
host = apr_pstrcat(r->pool, "[", host, "]", NULL);
|
||||
@@ -253,6 +258,43 @@ static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
static apr_status_t ap_proxy_buckets_lifetime_transform(request_rec *r,
|
||||
apr_bucket_brigade *from, apr_bucket_brigade *to)
|
||||
{
|
||||
apr_bucket *e;
|
||||
apr_bucket *new;
|
||||
const char *data;
|
||||
apr_size_t bytes;
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
|
||||
apr_brigade_cleanup(to);
|
||||
for (e = APR_BRIGADE_FIRST(from);
|
||||
e != APR_BRIGADE_SENTINEL(from);
|
||||
e = APR_BUCKET_NEXT(e)) {
|
||||
if (!APR_BUCKET_IS_METADATA(e)) {
|
||||
apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ);
|
||||
new = apr_bucket_transient_create(data, bytes, r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else if (APR_BUCKET_IS_FLUSH(e)) {
|
||||
new = apr_bucket_flush_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else if (APR_BUCKET_IS_EOS(e)) {
|
||||
new = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00964)
|
||||
"Unhandled bucket type of type %s in"
|
||||
" proxy_buckets_lifetime_transform", e->type->name);
|
||||
apr_bucket_delete(e);
|
||||
rv = APR_EGENERAL;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -263,6 +305,7 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
const char *buf;
|
||||
char *value, *end;
|
||||
int len;
|
||||
int backend_broke = 1;
|
||||
apr_status_t rc;
|
||||
conn_rec *c = r->connection;
|
||||
apr_off_t readbytes;
|
||||
@@ -274,6 +317,7 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
rp->proxyreq = PROXYREQ_RESPONSE;
|
||||
|
||||
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
apr_bucket_brigade *pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
|
||||
len = ap_getline(buffer, sizeof(buffer), rp, 1);
|
||||
|
||||
@@ -325,8 +369,8 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
rv = ap_get_brigade(rp->input_filters, bb,
|
||||
AP_MODE_READBYTES, mode,
|
||||
conf->io_buffer_size);
|
||||
if (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {
|
||||
if (mode == APR_NONBLOCK_READ && (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
|
||||
e = apr_bucket_flush_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
|
||||
@@ -342,21 +386,37 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
else if (rv != APR_SUCCESS) {
|
||||
ap_proxy_backend_broke(r, bb);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
backend_broke = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
mode = APR_NONBLOCK_READ;
|
||||
apr_brigade_length(bb, 0, &readbytes);
|
||||
backend->worker->s->read += readbytes;
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
if (APR_BRIGADE_EMPTY(bb)) {
|
||||
apr_brigade_cleanup(bb);
|
||||
break;
|
||||
}
|
||||
|
||||
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
|
||||
|
||||
ap_pass_brigade(r->output_filters, pass_bb);
|
||||
apr_brigade_cleanup(bb);
|
||||
apr_brigade_cleanup(pass_bb);
|
||||
}
|
||||
|
||||
e = apr_bucket_eos_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
|
||||
return OK;
|
||||
if (c->aborted || backend_broke) {
|
||||
return DONE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,441 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include "erlang.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_erlang uerl;
|
||||
|
||||
struct uwsgi_option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
|
||||
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
void dump_eterm(ei_x_buff *x) {
|
||||
|
||||
int etype, esize, arity;
|
||||
long long num;
|
||||
char *atom;
|
||||
int i;
|
||||
char *binary;
|
||||
long bin_size;
|
||||
double fnum;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize);
|
||||
|
||||
switch(etype) {
|
||||
case ERL_SMALL_INTEGER_EXT:
|
||||
case ERL_INTEGER_EXT:
|
||||
case ERL_SMALL_BIG_EXT:
|
||||
case ERL_LARGE_BIG_EXT:
|
||||
ei_decode_longlong(x->buff, &x->index, &num);
|
||||
uwsgi_log("num: %lu\n", num);
|
||||
break;
|
||||
case ERL_FLOAT_EXT:
|
||||
ei_decode_double(x->buff, &x->index, &fnum);
|
||||
uwsgi_log("float: %f\n", fnum);
|
||||
break;
|
||||
case ERL_STRING_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, atom);
|
||||
uwsgi_log("string: %s\n", atom);
|
||||
free(atom);
|
||||
break;
|
||||
case ERL_ATOM_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, atom);
|
||||
uwsgi_log("atom: %s\n", atom);
|
||||
free(atom);
|
||||
break;
|
||||
case ERL_SMALL_TUPLE_EXT:
|
||||
case ERL_LARGE_TUPLE_EXT:
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
for(i=0;i<arity;i++) {
|
||||
dump_eterm(x);
|
||||
}
|
||||
break;
|
||||
case ERL_LIST_EXT:
|
||||
case ERL_NIL_EXT:
|
||||
ei_decode_list_header(x->buff, &x->index, &arity);
|
||||
if (arity == 0) {
|
||||
uwsgi_log("nil value\n");
|
||||
break;
|
||||
}
|
||||
for(i=0;i<arity+1;i++) {
|
||||
dump_eterm(x);
|
||||
}
|
||||
break;
|
||||
case ERL_BINARY_EXT:
|
||||
binary = uwsgi_malloc(esize);
|
||||
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
|
||||
uwsgi_log("binary data of %d bytes\n", bin_size);
|
||||
free(binary);
|
||||
break;
|
||||
default:
|
||||
uwsgi_log("ignored...\n");
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
int etype, esize;
|
||||
int arity;
|
||||
|
||||
char *gen_call;
|
||||
char *module;
|
||||
char *call;
|
||||
char buffer[0xffff];
|
||||
|
||||
char *argv[256] ;
|
||||
uint16_t argvs[256] ;
|
||||
int argc = 0;
|
||||
uint16_t ret;
|
||||
ei_x_buff xr;
|
||||
|
||||
erlang_ref eref;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
|
||||
#endif
|
||||
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("rpc arity %d\n", arity);
|
||||
#endif
|
||||
if (arity != 3) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
gen_call = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, gen_call);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, gen_call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("gen call = %s\n", gen_call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
if (arity != 2) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_decode_ref(x->buff, &x->index, &eref);
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, module);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, module);
|
||||
}
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arity: %d\n", arity);
|
||||
#endif
|
||||
if (arity != 5) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
char *method = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, method);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, method);
|
||||
}
|
||||
|
||||
if (strcmp(method, "call")) return;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, module);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, module);
|
||||
}
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
call = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, call);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("RPC %s %s\n", module, call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
else if (etype == ERL_STRING_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
|
||||
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("buffer: %.*s\n", ret, buffer);
|
||||
#endif
|
||||
|
||||
ei_x_new_with_version(&xr);
|
||||
|
||||
ei_x_encode_tuple_header(&xr, 2);
|
||||
//ei_x_encode_atom(&xr, "rex");
|
||||
ei_x_encode_ref(&xr, &eref);
|
||||
ei_x_encode_string_len(&xr, buffer, ret);
|
||||
|
||||
uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index));
|
||||
//uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void erlang_loop(int id, void *data) {
|
||||
|
||||
ErlConnect econn;
|
||||
//ErlMessage em;
|
||||
erlang_msg em;
|
||||
int fd;
|
||||
|
||||
int eversion;
|
||||
|
||||
ei_x_buff x, xr;
|
||||
|
||||
ei_x_new(&x);
|
||||
ei_x_new(&xr);
|
||||
|
||||
|
||||
/*
|
||||
int fd0 = ei_connect(&uerl.cnode, "anothernode@maverick64");
|
||||
uwsgi_log("fd0: %d\n", fd0);
|
||||
|
||||
ei_x_encode_list_header(&x, 0);
|
||||
|
||||
ei_rpc_to(&uerl.cnode, fd0, "erlang", "node", x.buff, x.index);
|
||||
|
||||
ei_rpc_from(&uerl.cnode, fd0, 10000, &em, &xr);
|
||||
|
||||
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
|
||||
|
||||
xr.index = 0;
|
||||
ei_decode_version(xr.buff, &xr.index, &eversion);
|
||||
uwsgi_log("eversion: %d\n", eversion);
|
||||
|
||||
dump_eterm(&xr);
|
||||
*/
|
||||
|
||||
for(;;) {
|
||||
|
||||
fd = ei_accept(&uerl.cnode, uerl.fd, &econn);
|
||||
|
||||
if (fd >= 0) {
|
||||
|
||||
for (;;) {
|
||||
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
|
||||
|
||||
if (em.msgtype == ERL_TICK)
|
||||
continue;
|
||||
|
||||
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
|
||||
|
||||
|
||||
|
||||
x.index = 0;
|
||||
ei_decode_version(x.buff, &x.index, &eversion);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("eversion: %d\n", eversion);
|
||||
#endif
|
||||
|
||||
if (!strcmp(em.toname, "rex")) {
|
||||
uwsgi_erlang_rpc(fd, &em.from, &x);
|
||||
}
|
||||
else {
|
||||
struct uwsgi_erlang_process *uep = uerl.uep;
|
||||
while(uep) {
|
||||
if (!strcmp(uep->name, em.toname)) {
|
||||
if (uep->plugin) {
|
||||
uep->plugin(uep->func, &x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
if (!uep) {
|
||||
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
|
||||
dump_eterm(&x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
if (em.msgtype) {
|
||||
dump_erl_obj(em.msg);
|
||||
erl_free_compound(em.msg);
|
||||
}
|
||||
if (em.to) {
|
||||
uwsgi_log("*** TO ***\n");
|
||||
dump_erl_obj(em.to);
|
||||
erl_free_compound(em.to);
|
||||
}
|
||||
|
||||
if (em.from) {
|
||||
uwsgi_log("*** FROM ***\n");
|
||||
dump_erl_obj(em.from);
|
||||
erl_free_compound(em.from);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int erlang_init() {
|
||||
|
||||
char *host;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t slen = sizeof(struct sockaddr_in);
|
||||
char *ip = NULL;
|
||||
char *nodename;
|
||||
struct in_addr addr;
|
||||
|
||||
uerl.lock = uwsgi_lock_init("erlang");
|
||||
|
||||
if (uerl.name) {
|
||||
|
||||
|
||||
host = strchr(uerl.name, '@');
|
||||
|
||||
if (!host) {
|
||||
if (ei_connect_init(&uerl.cnode, uerl.name, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0);
|
||||
ip = uwsgi_resolve_ip(host+1);
|
||||
if (ip) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("ip: %s\n", ip);
|
||||
#endif
|
||||
addr.s_addr = inet_addr(ip);
|
||||
if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
free(nodename);
|
||||
}
|
||||
|
||||
if (ip) {
|
||||
uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL);
|
||||
}
|
||||
else {
|
||||
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
|
||||
}
|
||||
|
||||
if (uerl.fd < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (getsockname(uerl.fd, (struct sockaddr *) &sin, &slen)) {
|
||||
uwsgi_error("getsockname()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ei_publish(&uerl.cnode, ntohs(sin.sin_port)) < 0) {
|
||||
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin erlang_plugin = {
|
||||
|
||||
.name = "erlang",
|
||||
.options = erlang_options,
|
||||
.init = erlang_init,
|
||||
};
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#include <ei.h>
|
||||
|
||||
struct uwsgi_erlang_process {
|
||||
|
||||
char name[0xff];
|
||||
void (*plugin)(void *, ei_x_buff *);
|
||||
void *func;
|
||||
|
||||
struct uwsgi_erlang_process *next;
|
||||
};
|
||||
|
||||
struct uwsgi_erlang {
|
||||
|
||||
ei_cnode cnode;
|
||||
char *name;
|
||||
char *cookie;
|
||||
|
||||
int fd;
|
||||
|
||||
void *lock;
|
||||
|
||||
struct uwsgi_erlang_process *uep;
|
||||
};
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import os
|
||||
|
||||
NAME='erlang'
|
||||
|
||||
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
|
||||
|
||||
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
|
||||
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
|
||||
|
||||
CFLAGS = [ '-I' + includedir ]
|
||||
LDFLAGS = [ '-L' + libpath ]
|
||||
|
||||
LIBS = ['-lei']
|
||||
|
||||
GCC_LIST = ['erlang']
|
||||
@@ -1,116 +0,0 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void (*uwsgi_go_helper_post_fork_c)();
|
||||
void (*uwsgi_go_helper_post_init_c)();
|
||||
void * (*uwsgi_go_helper_env_new_c)(struct wsgi_request *);
|
||||
void (*uwsgi_go_helper_env_add_c)(void *, char *, int, char *, int);
|
||||
void (*uwsgi_go_helper_request_c)(void *, struct wsgi_request *);
|
||||
int (*uwsgi_go_helper_signal_handler_c)(int, void *);
|
||||
void (*uwsgi_go_helper_run_core_c)(int);
|
||||
char *(*uwsgi_go_helper_version_c)();
|
||||
|
||||
void uwsgi_go_post_fork() {
|
||||
uwsgi_go_helper_post_fork_c();
|
||||
}
|
||||
|
||||
void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_go_options[] = {
|
||||
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
#define uwsgi_go_get_symbol(x) x ## _c = dlsym(RTLD_DEFAULT, #x);\
|
||||
if (!x ## _c) {\
|
||||
uwsgi_log("[uwsgi-go] unable to load " #x " function\n"); exit(1);\
|
||||
}
|
||||
|
||||
static int uwsgi_go_init() {
|
||||
|
||||
// build the functions table
|
||||
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_post_fork)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_post_init)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_env_new)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_env_add)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_request)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_signal_handler)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_run_core)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_version)
|
||||
|
||||
uwsgi_log("Go version \"%s\" initialized\n", uwsgi_go_helper_version_c());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_go_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->async_environ = uwsgi_go_helper_env_new_c(wsgi_req);
|
||||
int i;
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
uwsgi_go_helper_env_add_c(wsgi_req->async_environ, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len,
|
||||
wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
uwsgi_go_helper_request_c(wsgi_req->async_environ, wsgi_req);
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
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) {
|
||||
return uwsgi_go_helper_signal_handler_c((int)signum, handler);
|
||||
}
|
||||
|
||||
static void goroutines_loop() {
|
||||
int i;
|
||||
for (i = 1; i < uwsgi.async; i++) {
|
||||
uwsgi_go_helper_run_core_c(i);
|
||||
}
|
||||
simple_loop_run_int(0);
|
||||
}
|
||||
|
||||
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,
|
||||
.on_load = uwsgi_go_on_load,
|
||||
.options = uwsgi_go_options,
|
||||
};
|
||||
@@ -1,420 +0,0 @@
|
||||
/*
|
||||
uWSGI go integration package
|
||||
*/
|
||||
|
||||
package uwsgi
|
||||
|
||||
/*
|
||||
#include <uwsgi.h>
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// commodity functions to simulate argc/argv
|
||||
|
||||
static char ** uwsgi_go_helper_create_argv(int len) {
|
||||
return uwsgi_calloc(sizeof(char *) * len);
|
||||
}
|
||||
|
||||
static void uwsgi_go_helper_set_argv(char **argv, int pos, char *item) {
|
||||
argv[pos] = item;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"unsafe"
|
||||
"strings"
|
||||
"strconv"
|
||||
"io"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// this stores the modifier used by the go plugin (default 11)
|
||||
var uwsgi_modifier1 int = -1;
|
||||
// the following to objects are used to implement a sort of GC to avoid request environ and
|
||||
// signal handlers to be garbage collected
|
||||
var uwsgi_env_gc = make(map[*C.struct_wsgi_request](*map[string]string))
|
||||
var uwsgi_signals_gc = make([]*func(int), 256)
|
||||
|
||||
var uwsgi_default_request_handler func(http.ResponseWriter, *http.Request) = nil
|
||||
var uwsgi_default_handler http.Handler = nil
|
||||
var uwsgi_post_fork_hook func() = nil
|
||||
var uwsgi_post_init_hook func() = nil
|
||||
|
||||
|
||||
/*
|
||||
|
||||
uWSGI api functions
|
||||
|
||||
*/
|
||||
|
||||
// raise a uWSGI signal
|
||||
func Signal(signum int) {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return
|
||||
}
|
||||
C.uwsgi_signal_send(C.uwsgi.signal_socket, C.uint8_t(signum))
|
||||
}
|
||||
|
||||
// set a user lock
|
||||
func Lock(num int) {
|
||||
C.uwsgi_user_lock(C.int(num));
|
||||
}
|
||||
|
||||
// unset a user lock
|
||||
func Unlock(num int) {
|
||||
C.uwsgi_user_unlock(C.int(num));
|
||||
}
|
||||
|
||||
// add a timer
|
||||
func AddTimer(signum int, seconds int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_add_timer(C.uint8_t(signum), C.int(seconds))) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// add a red black timer
|
||||
func AddRbTimer(signum int, seconds int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_signal_add_rb_timer(C.uint8_t(signum), C.int(seconds), C.int(0))) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// check if a signal is registered
|
||||
func SignalRegistered(signum int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_signal_registered(C.uint8_t(signum))) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// register a signal
|
||||
func RegisterSignal(signum int, who string, handler func(int)) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if uwsgi_modifier1 == -1 {
|
||||
c_go := C.CString("go")
|
||||
defer C.free(unsafe.Pointer(c_go))
|
||||
uwsgi_modifier1 = int(C.uwsgi_plugin_modifier1(c_go))
|
||||
if uwsgi_modifier1 == -1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
c_who := C.CString(who)
|
||||
defer C.free(unsafe.Pointer(c_who))
|
||||
if int(C.uwsgi_register_signal(C.uint8_t(signum), c_who, unsafe.Pointer(&handler), C.uint8_t(uwsgi_modifier1))) == 0 {
|
||||
uwsgi_signals_gc[signum] = &handler
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Alarm(alarm string, msg string) {
|
||||
a := C.CString(alarm)
|
||||
defer C.free(unsafe.Pointer(a))
|
||||
m := C.CString(msg)
|
||||
defer C.free(unsafe.Pointer(m))
|
||||
ml := len(msg)
|
||||
C.uwsgi_alarm_trigger(a, m, C.size_t(ml))
|
||||
}
|
||||
|
||||
// get an item from the cache
|
||||
func CacheGet(key string, cache string) []byte {
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
var vl C.uint64_t = C.uint64_t(0)
|
||||
|
||||
|
||||
c := (*C.char)(nil)
|
||||
if len(cache) > 0 {
|
||||
c = C.CString(cache)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
}
|
||||
|
||||
var p []byte
|
||||
|
||||
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))
|
||||
} else {
|
||||
p = nil
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// remove an intem from the cache
|
||||
func CacheDel(key string, cache string) bool {
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
|
||||
c := (*C.char)(nil)
|
||||
if len(cache) > 0 {
|
||||
c = C.CString(cache)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
}
|
||||
|
||||
if int(C.uwsgi_cache_magic_del(k, C.uint16_t(kl), c)) < 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// check if an item exists in the cache
|
||||
func CacheExists(key string, cache string) bool {
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
|
||||
c := (*C.char)(nil)
|
||||
if len(cache) > 0 {
|
||||
c = C.CString(cache)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
}
|
||||
|
||||
if int(C.uwsgi_cache_magic_exists(k, C.uint16_t(kl), c)) == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// put an item in the cache
|
||||
func CacheSetFlags(key string, p []byte, expires uint64, flags int, cache string) bool {
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
v := unsafe.Pointer(&p[0])
|
||||
vl := len(p)
|
||||
|
||||
c := (*C.char)(nil)
|
||||
if len(cache) > 0 {
|
||||
c = C.CString(cache)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
}
|
||||
|
||||
if int(C.uwsgi_cache_magic_set(k, C.uint16_t(kl), (*C.char)(v), C.uint64_t(vl), C.uint64_t(expires), C.uint64_t(flags), c)) < 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func CacheSet(key string, p []byte, expires uint64, cache string) bool {
|
||||
return CacheSetFlags(key, p, expires, 0, cache);
|
||||
}
|
||||
|
||||
func CacheUpdate(key string, p []byte, expires uint64, cache string) bool {
|
||||
return CacheSetFlags(key, p, expires, 2, cache);
|
||||
}
|
||||
|
||||
// get the current worker id
|
||||
func WorkerId() int {
|
||||
return int(C.uwsgi.mywid)
|
||||
}
|
||||
|
||||
// get the current mule id
|
||||
func MuleId() int {
|
||||
return int(C.uwsgi.muleid)
|
||||
}
|
||||
|
||||
// get the current logsize (if available)
|
||||
func LogSize() int64 {
|
||||
return int64(C.uwsgi.shared.logsize)
|
||||
}
|
||||
|
||||
func PostFork(hook func()) {
|
||||
uwsgi_post_fork_hook = hook
|
||||
}
|
||||
|
||||
func PostInit(hook func()) {
|
||||
uwsgi_post_init_hook = hook
|
||||
}
|
||||
|
||||
func RequestHandler(hook func(http.ResponseWriter, *http.Request)) {
|
||||
uwsgi_default_request_handler = hook
|
||||
}
|
||||
|
||||
func Handler(handler http.Handler) {
|
||||
uwsgi_default_handler = handler
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
C -> go and go -> C bridges
|
||||
|
||||
*/
|
||||
|
||||
//export uwsgi_go_helper_post_fork
|
||||
func uwsgi_go_helper_post_fork() {
|
||||
if uwsgi_post_fork_hook != nil {
|
||||
uwsgi_post_fork_hook()
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_post_init
|
||||
func uwsgi_go_helper_post_init() {
|
||||
if uwsgi_post_init_hook != nil {
|
||||
uwsgi_post_init_hook()
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_env_new
|
||||
func uwsgi_go_helper_env_new(wsgi_req *C.struct_wsgi_request) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
// track env to avoid it being garbage collected...
|
||||
uwsgi_env_gc[wsgi_req] = &env
|
||||
return &env
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_env_add
|
||||
func uwsgi_go_helper_env_add(env *map[string]string, k *C.char, kl C.int, v *C.char, vl C.int) {
|
||||
var mk string = C.GoStringN(k, kl)
|
||||
var mv string = C.GoStringN(v, vl)
|
||||
(*env)[mk] = mv
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
http.* implementations
|
||||
|
||||
*/
|
||||
|
||||
type ResponseWriter struct {
|
||||
r *http.Request
|
||||
wsgi_req *C.struct_wsgi_request
|
||||
headers http.Header
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
m := len(p)
|
||||
C.uwsgi_response_write_body_do(w.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m))
|
||||
return m+n, err
|
||||
}
|
||||
|
||||
// TODO fix it !!!
|
||||
func (w *ResponseWriter) WriteHeader(status int) {
|
||||
codestring := http.StatusText(status)
|
||||
var tmp_buf string = strconv.Itoa(status) + " " + codestring
|
||||
c_status := C.CString(tmp_buf)
|
||||
defer C.free(unsafe.Pointer(c_status))
|
||||
C.uwsgi_response_prepare_headers(w.wsgi_req, c_status, C.uint16_t(len(tmp_buf)) )
|
||||
if w.headers.Get("Content-Type") == "" {
|
||||
w.headers.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
for k := range w.headers {
|
||||
hk_c := C.CString(k)
|
||||
defer C.free(unsafe.Pointer(hk_c))
|
||||
for _, v := range w.headers[k] {
|
||||
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
|
||||
v = strings.TrimSpace(v)
|
||||
hv_c := C.CString(v)
|
||||
defer C.free(unsafe.Pointer(hv_c))
|
||||
C.uwsgi_response_add_header(w.wsgi_req, hk_c, C.uint16_t(len(k)), hv_c, C.uint16_t(len(v)))
|
||||
}
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Header() http.Header {
|
||||
return w.headers
|
||||
}
|
||||
|
||||
|
||||
type BodyReader struct {
|
||||
wsgi_req *C.struct_wsgi_request
|
||||
}
|
||||
|
||||
// there is no close in request body
|
||||
func (br *BodyReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *BodyReader) Read(p []byte) (n int, err error) {
|
||||
m := len(p)
|
||||
var rlen C.ssize_t = C.ssize_t(0)
|
||||
c_body := C.uwsgi_request_body_read(br.wsgi_req, C.ssize_t(m), &rlen)
|
||||
if (c_body == C.uwsgi.empty) {
|
||||
err = io.EOF;
|
||||
return 0, err
|
||||
} else if (c_body != nil) {
|
||||
C.memcpy(unsafe.Pointer(&p[0]), unsafe.Pointer(c_body), C.size_t(rlen))
|
||||
return int(rlen), err
|
||||
}
|
||||
err = io.ErrUnexpectedEOF
|
||||
rlen = 0
|
||||
return int(rlen), err
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_request
|
||||
func uwsgi_go_helper_request(env *map[string]string, wsgi_req *C.struct_wsgi_request) {
|
||||
httpReq, err := cgi.RequestFromMap(*env)
|
||||
if err != nil {
|
||||
} else {
|
||||
httpReq.Body = &BodyReader{wsgi_req}
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
if uwsgi_default_request_handler != nil {
|
||||
uwsgi_default_request_handler(&w, httpReq)
|
||||
} else if uwsgi_default_handler != nil {
|
||||
uwsgi_default_handler.ServeHTTP(&w, httpReq)
|
||||
} else {
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_version
|
||||
func uwsgi_go_helper_version() *C.char {
|
||||
return C.CString(runtime.Version())
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_signal_handler
|
||||
func uwsgi_go_helper_signal_handler(signum int, handler *func(int)) int {
|
||||
(*handler)(signum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_run_core
|
||||
func uwsgi_go_helper_run_core(core_id int) {
|
||||
go C.simple_loop_run_int(C.int(core_id))
|
||||
}
|
||||
|
||||
/*
|
||||
the main function, running the uWSGI server via libuwsgi.so
|
||||
*/
|
||||
func Run() {
|
||||
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-1), argv, nil)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import os
|
||||
NAME='go'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['go_plugin']
|
||||
|
||||
def post_build(config):
|
||||
os.environ['GOPATH'] = 'plugins/go'
|
||||
cflags = ['-I'+os.getcwd()]
|
||||
for c in config.cflags:
|
||||
if not c.startswith('-DUWSGI_BUILD_DATE') and not c.startswith('-DUWSGI_CFLAGS'):
|
||||
cflags.append(c)
|
||||
|
||||
cflags.append('-Wno-implicit-function-declaration')
|
||||
cflags.append('-Wno-implicit-int')
|
||||
cflags.append('-Wno-unused-function')
|
||||
cflags.append('-Wno-unused-variable')
|
||||
|
||||
os.environ['CGO_CFLAGS'] = ' '.join(cflags).replace('\\"', '')
|
||||
base = os.path.dirname(config.get('bin_name'))
|
||||
if not base:
|
||||
base = "."
|
||||
os.environ['CGO_LDFLAGS'] = '-L' + base + ' -L'+os.getcwd() + ' -luwsgi'
|
||||
if os.system("go install uwsgi") != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi go module available in $GOPATH %s/plugins/go ***" % os.getcwd())
|
||||
@@ -1,543 +0,0 @@
|
||||
#include "../erlang/erlang.h"
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_erlang uerl;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
ei_cnode *pyerl_cnode;
|
||||
|
||||
PyObject *pyerl_close(PyObject * self, PyObject * args) {
|
||||
|
||||
int fd;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:erlang_close", &fd)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *pyerl_connect(PyObject * self, PyObject * args) {
|
||||
|
||||
char *node = NULL;
|
||||
int fd;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:erlang_connect", &node)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = ei_connect(pyerl_cnode, node);
|
||||
|
||||
if (fd < 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(fd);
|
||||
|
||||
}
|
||||
|
||||
int py_to_erl(PyObject *, ei_x_buff*);
|
||||
|
||||
PyObject *erl_to_py(ei_x_buff* x) {
|
||||
|
||||
int etype, esize, arity;
|
||||
long long num;
|
||||
double fnum;
|
||||
char *atom, *binary;
|
||||
long bin_size;
|
||||
PyObject *pobj;
|
||||
PyObject *zero;
|
||||
erlang_pid epid;
|
||||
int i;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
switch(etype) {
|
||||
case ERL_SMALL_INTEGER_EXT:
|
||||
case ERL_INTEGER_EXT:
|
||||
case ERL_SMALL_BIG_EXT:
|
||||
case ERL_LARGE_BIG_EXT:
|
||||
ei_decode_longlong(x->buff, &x->index, &num);
|
||||
return PyLong_FromLong(num);
|
||||
case ERL_FLOAT_EXT:
|
||||
ei_decode_double(x->buff, &x->index, &fnum);
|
||||
return PyFloat_FromDouble(fnum);
|
||||
case ERL_STRING_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, atom);
|
||||
pobj = PyString_FromString(atom);
|
||||
free(atom);
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
case ERL_ATOM_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, atom);
|
||||
#ifndef PyUnicode_FromString
|
||||
zero = PyString_FromString(atom);
|
||||
pobj = PyUnicode_FromObject(zero);
|
||||
Py_DECREF(zero);
|
||||
#else
|
||||
pobj = PyUnicode_FromString(atom);
|
||||
#endif
|
||||
free(atom);
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
case ERL_SMALL_TUPLE_EXT:
|
||||
case ERL_LARGE_TUPLE_EXT:
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
pobj = PyTuple_New(arity);
|
||||
for(i=0;i<arity;i++) {
|
||||
zero = erl_to_py(x);
|
||||
PyTuple_SetItem(pobj, i, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
case ERL_LIST_EXT:
|
||||
case ERL_NIL_EXT:
|
||||
ei_decode_list_header(x->buff, &x->index, &arity);
|
||||
if (!arity) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
pobj = PyList_New(0);
|
||||
for(i=0;i<arity+1;i++) {
|
||||
zero = erl_to_py(x);
|
||||
PyList_Append(pobj, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
case ERL_BINARY_EXT:
|
||||
binary = uwsgi_malloc(esize);
|
||||
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
|
||||
pobj = PyString_FromStringAndSize(binary, bin_size);
|
||||
free(binary);
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
case ERL_PID_EXT:
|
||||
ei_decode_pid(x->buff, &x->index, &epid);
|
||||
pobj = PyTuple_New(3);
|
||||
PyTuple_SetItem(pobj, 0, PyInt_FromLong(epid.num));
|
||||
PyTuple_SetItem(pobj, 1, PyInt_FromLong(epid.serial));
|
||||
PyTuple_SetItem(pobj, 2, PyInt_FromLong(epid.creation));
|
||||
Py_INCREF(pobj);
|
||||
return pobj;
|
||||
default:
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *pyerl_lock(PyObject * self, PyObject * args) {
|
||||
|
||||
uwsgi_lock(uerl.lock);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *pyerl_unlock(PyObject * self, PyObject * args) {
|
||||
|
||||
uwsgi_unlock(uerl.lock);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *pyerl_send(PyObject * self, PyObject * args) {
|
||||
PyObject *node;
|
||||
PyObject *reg;
|
||||
char *cnode;
|
||||
PyObject *pobj;
|
||||
ei_x_buff x;
|
||||
int fd;
|
||||
int close_fd = 0;
|
||||
erlang_pid epid;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OOO:erlang_send", &node, ®, &pobj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyString_Check(node)) {
|
||||
cnode = PyString_AsString(node);
|
||||
fd = ei_connect(pyerl_cnode, cnode);
|
||||
close_fd = 1;
|
||||
}
|
||||
else if (PyInt_Check(node)) {
|
||||
fd = PyInt_AsLong(node);
|
||||
}
|
||||
else {
|
||||
return PyErr_Format(PyExc_ValueError, "invalid erlang node/descriptor");
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
|
||||
}
|
||||
|
||||
|
||||
ei_x_new_with_version(&x);
|
||||
|
||||
if (py_to_erl(pobj, &x) < 0) {
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation");
|
||||
}
|
||||
|
||||
|
||||
if (PyTuple_Check(reg) && PyTuple_Size(reg) == 3) {
|
||||
epid.num = PyInt_AsLong( PyTuple_GetItem(reg, 0) );
|
||||
epid.serial = PyInt_AsLong( PyTuple_GetItem(reg, 1) );
|
||||
epid.creation = PyInt_AsLong( PyTuple_GetItem(reg, 2) );
|
||||
ei_send(fd, &epid, x.buff, x.index);
|
||||
}
|
||||
else if (PyString_Check(reg)) {
|
||||
ei_reg_send(pyerl_cnode, fd, PyString_AsString(reg), x.buff, x.index);
|
||||
}
|
||||
else {
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid Erlang process");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(fd);
|
||||
}
|
||||
|
||||
PyObject *pyerl_sr(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *node;
|
||||
PyObject *reg;
|
||||
char *cnode;
|
||||
PyObject *pobj;
|
||||
ei_x_buff x;
|
||||
int fd;
|
||||
int close_fd = 0;
|
||||
erlang_msg em;
|
||||
erlang_pid epid;
|
||||
int eversion;
|
||||
PyObject *res;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OOO:erlang_sr", &node, ®, &pobj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyString_Check(node)) {
|
||||
cnode = PyString_AsString(node);
|
||||
fd = ei_connect(pyerl_cnode, cnode);
|
||||
close_fd = 1;
|
||||
}
|
||||
else if (PyInt_Check(node)) {
|
||||
fd = PyInt_AsLong(node);
|
||||
}
|
||||
else {
|
||||
return PyErr_Format(PyExc_ValueError, "invalid erlang node/descriptor");
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
|
||||
}
|
||||
|
||||
|
||||
|
||||
ei_x_new_with_version(&x);
|
||||
|
||||
if (py_to_erl(pobj, &x) < 0) {
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation");
|
||||
}
|
||||
|
||||
|
||||
if (PyTuple_Check(reg) && PyTuple_Size(reg) == 3) {
|
||||
epid.num = PyInt_AsLong( PyTuple_GetItem(reg, 0) );
|
||||
epid.serial = PyInt_AsLong( PyTuple_GetItem(reg, 1) );
|
||||
epid.creation = PyInt_AsLong( PyTuple_GetItem(reg, 2) );
|
||||
ei_send(fd, &epid, x.buff, x.index);
|
||||
}
|
||||
else if (PyString_Check(reg)) {
|
||||
ei_reg_send(pyerl_cnode, fd, PyString_AsString(reg), x.buff, x.index);
|
||||
}
|
||||
else {
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid Erlang process");
|
||||
}
|
||||
|
||||
recv:
|
||||
ei_x_free(&x);
|
||||
|
||||
ei_x_new(&x);
|
||||
|
||||
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
|
||||
|
||||
if (em.msgtype == ERL_TICK) {
|
||||
goto recv;
|
||||
}
|
||||
x.index = 0;
|
||||
ei_decode_version(x.buff, &x.index, &eversion);
|
||||
res = erl_to_py(&x);
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
void pyerl_call_registered(void *func, ei_x_buff *x) {
|
||||
|
||||
PyObject *pyargs = PyTuple_New(1);
|
||||
|
||||
PyTuple_SetItem(pyargs, 0, erl_to_py(x));
|
||||
|
||||
python_call((PyObject *) func, pyargs, 0, NULL);
|
||||
}
|
||||
|
||||
PyObject *pyerl_register_process(PyObject * self, PyObject * args) {
|
||||
|
||||
char *name;
|
||||
PyObject *callable;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "sO:erlang_register_process", &name, &callable)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(name) > 0xff-1)
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid erlang process name");
|
||||
|
||||
struct uwsgi_erlang_process *uep = uerl.uep, *old_uep;
|
||||
|
||||
if (!uep) {
|
||||
uerl.uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
|
||||
uep = uerl.uep;
|
||||
}
|
||||
else {
|
||||
while(uep) {
|
||||
old_uep = uep;
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
|
||||
old_uep->next = uep;
|
||||
}
|
||||
|
||||
strcpy(uep->name, name);
|
||||
uep->plugin = pyerl_call_registered;
|
||||
uep->func = callable;
|
||||
uep->next = NULL;
|
||||
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *pyerl_recv(PyObject * self, PyObject * args) {
|
||||
|
||||
ei_x_buff x;
|
||||
erlang_msg em;
|
||||
PyObject *res;
|
||||
int eversion;
|
||||
int fd;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:erlang_recv", &fd)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
recv:
|
||||
ei_x_new(&x);
|
||||
|
||||
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
|
||||
|
||||
if (em.msgtype == ERL_TICK) {
|
||||
ei_x_free(&x);
|
||||
goto recv;
|
||||
}
|
||||
x.index = 0;
|
||||
ei_decode_version(x.buff, &x.index, &eversion);
|
||||
res = erl_to_py(&x);
|
||||
ei_x_free(&x);
|
||||
return res;
|
||||
}
|
||||
|
||||
ei_x_free(&x);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *pyerl_rpc(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *node;
|
||||
char *mod, *fun;
|
||||
char *cnode;
|
||||
PyObject *pobj;
|
||||
ei_x_buff x;
|
||||
ei_x_buff xr;
|
||||
int fd;
|
||||
int close_fd = 0;
|
||||
int eversion;
|
||||
PyObject *res;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OssO:erlang_rpc", &node, &mod, &fun, &pobj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyString_Check(node)) {
|
||||
cnode = PyString_AsString(node);
|
||||
fd = ei_connect(pyerl_cnode, cnode);
|
||||
close_fd = 1;
|
||||
}
|
||||
else if (PyInt_Check(node)) {
|
||||
fd = PyInt_AsLong(node);
|
||||
}
|
||||
else {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid erlang node/descriptor");
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
|
||||
}
|
||||
|
||||
ei_x_new(&x);
|
||||
|
||||
if (py_to_erl(pobj, &x) < 0) {
|
||||
ei_x_free(&x);
|
||||
if (close_fd) close(fd);
|
||||
return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation");
|
||||
}
|
||||
|
||||
|
||||
ei_x_new(&xr);
|
||||
if (ei_rpc(pyerl_cnode, fd, mod, fun, x.buff, x.index, &xr) < 0) {
|
||||
if (close_fd) close(fd);
|
||||
ei_x_free(&x);
|
||||
ei_x_free(&xr);
|
||||
return PyErr_Format(PyExc_ValueError, "Error in Erlang rpc");
|
||||
}
|
||||
|
||||
xr.index = 0;
|
||||
ei_decode_version(xr.buff, &xr.index, &eversion);
|
||||
|
||||
res = erl_to_py(&xr);
|
||||
|
||||
if (close_fd) close(fd);
|
||||
ei_x_free(&x);
|
||||
ei_x_free(&xr);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_pyerl_methods[] = {
|
||||
{"erlang_connect", pyerl_connect, METH_VARARGS, ""},
|
||||
{"erlang_close", pyerl_close, METH_VARARGS, ""},
|
||||
{"erlang_send_message", pyerl_send, METH_VARARGS, ""},
|
||||
{"erlang_send", pyerl_send, METH_VARARGS, ""},
|
||||
{"erlang_recv_message", pyerl_recv, METH_VARARGS, ""},
|
||||
{"erlang_recv", pyerl_recv, METH_VARARGS, ""},
|
||||
{"erlang_sr", pyerl_sr, METH_VARARGS, ""},
|
||||
{"erlang_rpc", pyerl_rpc, METH_VARARGS, ""},
|
||||
{"erlang_lock", pyerl_lock, METH_VARARGS, ""},
|
||||
{"erlang_unlock", pyerl_unlock, METH_VARARGS, ""},
|
||||
{"erlang_register_process", pyerl_register_process, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
void py_erl_init_functions() {
|
||||
|
||||
PyMethodDef *uwsgi_function;
|
||||
|
||||
PyDict_SetItemString(up.embedded_dict, "erlang_node", PyString_FromString(ei_thisnodename(pyerl_cnode)));
|
||||
|
||||
for (uwsgi_function = uwsgi_pyerl_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
|
||||
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
|
||||
PyDict_SetItemString(up.embedded_dict, uwsgi_function->ml_name, func);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int py_to_erl(PyObject *pobj, ei_x_buff *x) {
|
||||
int i;
|
||||
PyObject *pobj2;
|
||||
|
||||
if (pobj == NULL || pobj == Py_None) {
|
||||
ei_x_encode_empty_list(x);
|
||||
}
|
||||
else if (PyString_Check(pobj)) {
|
||||
ei_x_encode_binary(x, PyString_AsString(pobj), PyString_Size(pobj));
|
||||
}
|
||||
else if (PyUnicode_Check(pobj)) {
|
||||
ei_x_encode_atom(x, PyString_AsString(pobj));
|
||||
}
|
||||
else if (PyInt_Check(pobj)) {
|
||||
ei_x_encode_long(x, PyInt_AsLong(pobj));
|
||||
}
|
||||
else if (PyList_Check(pobj)) {
|
||||
if (PyList_Size(pobj) > 0) {
|
||||
ei_x_encode_list_header(x, PyList_Size(pobj));
|
||||
for (i = 0; i < PyList_Size(pobj); i++) {
|
||||
pobj2 = PyList_GetItem(pobj, i);
|
||||
if (py_to_erl(pobj2, x) < 0) return -1;
|
||||
}
|
||||
}
|
||||
ei_x_encode_empty_list(x);
|
||||
}
|
||||
else if (PyTuple_Check(pobj)) {
|
||||
ei_x_encode_tuple_header(x, PyTuple_Size(pobj));
|
||||
for (i = 0; i < PyTuple_Size(pobj); i++) {
|
||||
pobj2 = PyTuple_GetItem(pobj, i);
|
||||
if (py_to_erl(pobj2, x) < 0) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return x->index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pyerl_init() {
|
||||
|
||||
up.extension = py_erl_init_functions;
|
||||
|
||||
if (!uerl.name) {
|
||||
pyerl_cnode = uwsgi_malloc(sizeof(ei_cnode));
|
||||
memset(pyerl_cnode, 0, sizeof(ei_cnode));
|
||||
if (ei_connect_init(pyerl_cnode, "uwsgi", NULL, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("Erlang C-Node name: %s\n",ei_thisnodename(pyerl_cnode));
|
||||
}
|
||||
else {
|
||||
pyerl_cnode = &uerl.cnode;
|
||||
}
|
||||
|
||||
uwsgi_log("enabled Python<->Erlang bridge\n");
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_plugin pyerl_plugin = {
|
||||
|
||||
.post_init = pyerl_init,
|
||||
};
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import os
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='pyerl'
|
||||
|
||||
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
|
||||
|
||||
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
|
||||
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
|
||||
|
||||
CFLAGS = [ '-I' + includedir, '-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = [ '-L' + libpath ]
|
||||
|
||||
LIBS = ['-lei']
|
||||
|
||||
GCC_LIST = ['pyerl']
|
||||
+1
-1
@@ -1,3 +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
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,zabbix,curl_cron,tornado,tuntap,pty,mongrel2,alarm_curl,router_radius,airbrake
|
||||
inherit = base
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,asyncio,greenlet
|
||||
inherit = base
|
||||
@@ -7,8 +7,6 @@ pcre = auto
|
||||
routing = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -7,8 +7,6 @@ pcre = false
|
||||
routing = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = none
|
||||
yaml_implementation = none
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
xml = libxml2
|
||||
yaml = libyaml
|
||||
json = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = libyaml
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
xml = expat
|
||||
yaml = embedded
|
||||
json = false
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
[uwsgi]
|
||||
xml = expat
|
||||
yaml = embedded
|
||||
json = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = /opt/unbit/uwsgi/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
Binary file not shown.
+26
-27
@@ -18,18 +18,18 @@ void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
|
||||
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
if (msg[len-1] != '\n') {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
|
||||
uwsgi_log_verbose("ALARM: %s %.*s\n", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s\n", len, msg);
|
||||
uwsgi_log_verbose("ALARM: %.*s\n", len, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
|
||||
uwsgi_log_verbose("ALARM: %s %.*s", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s", len, msg);
|
||||
uwsgi_log_verbose("ALARM: %.*s", len, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,6 +363,19 @@ void uwsgi_alarm_thread_start() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_alarm_trigger_uai(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// check if a log should raise an alarm
|
||||
void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
@@ -372,7 +385,14 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
while (ual) {
|
||||
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
|
||||
if (!ual->negate) {
|
||||
uwsgi_alarm_log_run(ual, msg, len);
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_trigger_uai(uall->alarm, msg, len);
|
||||
else
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
@@ -397,18 +417,6 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uai->last_msg_size = len;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// call the alarms mapped to a log line
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// this is the api function workers,mules and whatever you want can call from code
|
||||
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
if (!uwsgi.alarm_thread) return;
|
||||
@@ -416,16 +424,7 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
|
||||
if (!uai) return;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
uwsgi_alarm_trigger_uai(uai, msg, len);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
|
||||
+21
-2
@@ -360,7 +360,8 @@ void async_schedule_to_req_green(void) {
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
@@ -386,6 +387,23 @@ end:
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_async_wait_milliseconds_hook(int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
timeout = timeout / 1000;
|
||||
if (!timeout) timeout = 1;
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
wsgi_req->async_force_again = 1;
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
@@ -413,6 +431,7 @@ void async_loop() {
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
uwsgi.wait_read2_hook = async_wait_fd_read2;
|
||||
uwsgi.wait_milliseconds_hook = uwsgi_async_wait_milliseconds_hook;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
@@ -532,7 +551,7 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
// re-add timer
|
||||
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
async_add_timeout(uwsgi.wsgi_req, uwsgi.socket_timeout);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+16
-7
@@ -64,7 +64,7 @@ int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len)
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
if (ret <= 0 || ret >= 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_insert(ub, pos, chunked, ret);
|
||||
@@ -74,7 +74,7 @@ int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
if (ret <= 0 || ret >= 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, chunked, ret);
|
||||
@@ -128,7 +128,16 @@ int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
// need to escape \ and "
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == '"') {
|
||||
if (buf[i] == '\t') {
|
||||
if (uwsgi_buffer_append(ub, "\\t", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\n') {
|
||||
if (uwsgi_buffer_append(ub, "\\n", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\r') {
|
||||
if (uwsgi_buffer_append(ub, "\\r", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '"') {
|
||||
if (uwsgi_buffer_append(ub, "\\\"", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\\') {
|
||||
@@ -245,7 +254,7 @@ int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, buf, ret);
|
||||
@@ -268,7 +277,7 @@ int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t ke
|
||||
int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keylen, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
|
||||
@@ -280,7 +289,7 @@ int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keyl
|
||||
int uwsgi_buffer_append_valnum(struct uwsgi_buffer *ub, int64_t num) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi_buffer_u16le(ub, ret)) return -1;
|
||||
@@ -340,7 +349,7 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
|
||||
char *ptr = ub->buf;
|
||||
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(fd, uwsgi.socket_timeout);
|
||||
if (ret > 0) {
|
||||
ssize_t len = write(fd, ptr, remains);
|
||||
if (len > 0) {
|
||||
|
||||
+282
-131
@@ -32,7 +32,7 @@ static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t ne
|
||||
// which is the first free bit?
|
||||
uint64_t bitmap_byte = 0;
|
||||
uint8_t bitmap_bit = 0;
|
||||
|
||||
|
||||
if (uc->blocks_bitmap_pos > 0) {
|
||||
bitmap_byte = uc->blocks_bitmap_pos/8;
|
||||
bitmap_bit = uc->blocks_bitmap_pos % 8;
|
||||
@@ -45,6 +45,8 @@ static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t ne
|
||||
uint64_t j;
|
||||
uint64_t found = 0;
|
||||
uint64_t need_to_scan = uc->blocks_bitmap_size;
|
||||
// we make an addition round for the corner case of a single byte map not starting from 0
|
||||
if (bitmap_bit > 0) need_to_scan++;
|
||||
j = bitmap_byte;
|
||||
//uwsgi_log("start scanning %llu bytes starting from %llu need: %llu\n", (unsigned long long) need_to_scan, (unsigned long long) bitmap_byte, (unsigned long long) needed_blocks);
|
||||
while(need_to_scan) {
|
||||
@@ -73,7 +75,9 @@ static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t ne
|
||||
}
|
||||
found++;
|
||||
if (found == needed_blocks) {
|
||||
//printf("found %llu consecutive bit starting from byte %llu\n", found, base);
|
||||
#ifdef UWSGI_DEBUG
|
||||
printf("found %llu consecutive bit starting from byte %llu\n", (unsigned long long) found, (unsigned long long) base);
|
||||
#endif
|
||||
return ((base*8) + base_bit);
|
||||
}
|
||||
}
|
||||
@@ -82,12 +86,14 @@ static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t ne
|
||||
}
|
||||
j++;
|
||||
need_to_scan--;
|
||||
// check for overlap
|
||||
if (j >= need_to_scan) {
|
||||
// check for overlap (that is not supported)
|
||||
if (j >= uc->blocks_bitmap_size) {
|
||||
j = 0;
|
||||
found = 0;
|
||||
base = 0xffffffffffffffffLLU;
|
||||
base_bit = 0;
|
||||
// we use bitmap_bit only at the first round
|
||||
bitmap_bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,19 +108,27 @@ static uint64_t cache_mark_blocks(struct uwsgi_cache *uc, uint64_t index, uint64
|
||||
|
||||
uint64_t first_byte = index/8;
|
||||
uint8_t first_byte_bit = index % 8;
|
||||
uint64_t last_byte = (index+needed_blocks)/8;
|
||||
uint8_t last_byte_bit = (index+needed_blocks) % 8;
|
||||
// offset starts with 0, so actual last bit is index + needed_blocks - 1
|
||||
uint64_t last_byte = (index + needed_blocks - 1) / 8;
|
||||
uint8_t last_byte_bit = (index + needed_blocks - 1) % 8;
|
||||
|
||||
uint64_t needed_bytes = (last_byte - first_byte) + 1;
|
||||
|
||||
//uwsgi_log("%llu %u %llu %u\n", first_byte, first_byte_bit, last_byte, last_byte_bit);
|
||||
|
||||
uint8_t mask = 0xff >> first_byte_bit;
|
||||
|
||||
if (needed_bytes == 1) {
|
||||
// kinda hacky, but it does the job
|
||||
mask >>= (7 - last_byte_bit);
|
||||
mask <<= (7 - last_byte_bit);
|
||||
}
|
||||
|
||||
uc->blocks_bitmap[first_byte] |= mask;
|
||||
|
||||
uint64_t needed_bytes = (last_byte - first_byte)+1;
|
||||
|
||||
if (needed_bytes > 1) {
|
||||
mask = 0xff << (8 - last_byte_bit);
|
||||
uc->blocks_bitmap[last_byte-1] |= mask;
|
||||
mask = 0xff << (7 - last_byte_bit);
|
||||
uc->blocks_bitmap[last_byte] |= mask;
|
||||
}
|
||||
|
||||
if (needed_bytes > 2) {
|
||||
@@ -130,19 +144,28 @@ static void cache_unmark_blocks(struct uwsgi_cache *uc, uint64_t index, uint64_t
|
||||
|
||||
uint64_t first_byte = index/8;
|
||||
uint8_t first_byte_bit = index % 8;
|
||||
uint64_t last_byte = (index+needed_blocks)/8;
|
||||
uint8_t last_byte_bit = (index+needed_blocks) % 8;
|
||||
// offset starts with 0, so actual last bit is index + needed_blocks - 1
|
||||
uint64_t last_byte = (index + needed_blocks - 1)/8;
|
||||
uint8_t last_byte_bit = (index + needed_blocks - 1) % 8;
|
||||
|
||||
// here we use XOR (0+0 = 0 | 1+0 = 1 | 0+1 = 1| 1+1 = 0|
|
||||
uint64_t needed_bytes = (last_byte - first_byte) + 1;
|
||||
|
||||
uint8_t mask = 0xff >> first_byte_bit;
|
||||
uc->blocks_bitmap[first_byte] ^= mask;
|
||||
uint8_t mask = 0xff >> first_byte_bit;
|
||||
|
||||
uint64_t needed_bytes = (last_byte - first_byte)+1;
|
||||
if (needed_bytes == 1) {
|
||||
// kinda hacky, but it does the job
|
||||
mask >>= (7 - last_byte_bit);
|
||||
mask <<= (7 - last_byte_bit);
|
||||
}
|
||||
|
||||
// here we use AND (0+0 = 0 | 1+0 = 0 | 0+1 = 0| 1+1 = 1)
|
||||
// 0 in mask means "unmark", 1 in mask means "do not change"
|
||||
// so we need to invert the mask
|
||||
uc->blocks_bitmap[first_byte] &= ~mask;
|
||||
|
||||
if (needed_bytes > 1) {
|
||||
mask = 0xff << (8 - last_byte_bit);
|
||||
uc->blocks_bitmap[last_byte-1] ^= mask;
|
||||
mask = 0xff << (7 - last_byte_bit);
|
||||
uc->blocks_bitmap[last_byte] &= ~mask;
|
||||
}
|
||||
|
||||
if (needed_bytes > 2) {
|
||||
@@ -283,16 +306,24 @@ next2:
|
||||
void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
|
||||
uc->hashtable = uwsgi_calloc_shared(sizeof(uint64_t) * uc->hashsize);
|
||||
uc->unused_blocks_stack = uwsgi_calloc_shared(sizeof(uint64_t) * uc->blocks);
|
||||
// the first cache item is always zero
|
||||
uc->first_available_block = 1;
|
||||
uc->unused_blocks_stack = uwsgi_calloc_shared(sizeof(uint64_t) * uc->max_items);
|
||||
uc->unused_blocks_stack_ptr = 0;
|
||||
uc->filesize = ( (sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items) + (uc->blocksize * uc->blocks);
|
||||
|
||||
uint64_t i;
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
uc->unused_blocks_stack[uc->unused_blocks_stack_ptr] = i;
|
||||
}
|
||||
|
||||
if (uc->use_blocks_bitmap) {
|
||||
uc->blocks_bitmap_size = uc->blocks/8;
|
||||
if (uc->blocks % 8 > 0) uc->blocks_bitmap_size++;
|
||||
uint8_t m = uc->blocks % 8;
|
||||
if (m > 0) uc->blocks_bitmap_size++;
|
||||
uc->blocks_bitmap = uwsgi_calloc_shared(uc->blocks_bitmap_size);
|
||||
if (m > 0) {
|
||||
uc->blocks_bitmap[uc->blocks_bitmap_size-1] = 0xff >> m;
|
||||
}
|
||||
}
|
||||
|
||||
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
@@ -300,6 +331,14 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
int cache_fd;
|
||||
struct stat cst;
|
||||
|
||||
if (uc->store_delete && !stat(uc->store, &cst) && ((size_t) cst.st_size != uc->filesize || !S_ISREG(cst.st_mode))) {
|
||||
uwsgi_log("Removing invalid cache store file: %s\n", uc->store);
|
||||
if (unlink(uc->store) != 0) {
|
||||
uwsgi_log("Cannot remove invalid cache store file: %s\n", uc->store);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (stat(uc->store, &cst)) {
|
||||
uwsgi_log("creating a new cache store file: %s\n", uc->store);
|
||||
cache_fd = open(uc->store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
@@ -361,7 +400,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
uc->name,
|
||||
(unsigned long long) uc->filesize / (1024 * 1024),
|
||||
(unsigned long long) sizeof(struct uwsgi_cache_item)+uc->keysize,
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->blocks),
|
||||
(unsigned long long) uc->blocks_bitmap_size);
|
||||
|
||||
uwsgi_cache_setup_nodes(uc);
|
||||
@@ -441,6 +480,38 @@ uint32_t uwsgi_cache_exists2(struct uwsgi_cache *uc, char *key, uint16_t keylen)
|
||||
return uwsgi_cache_get_index(uc, key, keylen);
|
||||
}
|
||||
|
||||
static void lru_remove_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
{
|
||||
struct uwsgi_cache_item *prev, *next, *curr = cache_item(index);
|
||||
|
||||
if (curr->lru_next) {
|
||||
next = cache_item(curr->lru_next);
|
||||
next->lru_prev = curr->lru_prev;
|
||||
} else
|
||||
uc->lru_tail = curr->lru_prev;
|
||||
|
||||
if (curr->lru_prev) {
|
||||
prev = cache_item(curr->lru_prev);
|
||||
prev->lru_next = curr->lru_next;
|
||||
} else
|
||||
uc->lru_head = curr->lru_next;
|
||||
}
|
||||
|
||||
static void lru_add_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
{
|
||||
struct uwsgi_cache_item *prev, *curr = cache_item(index);
|
||||
|
||||
if (uc->lru_tail) {
|
||||
prev = cache_item(uc->lru_tail);
|
||||
prev->lru_next = index;
|
||||
} else
|
||||
uc->lru_head = index;
|
||||
|
||||
curr->lru_next = 0;
|
||||
curr->lru_prev = uc->lru_tail;
|
||||
uc->lru_tail = index;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
@@ -450,6 +521,10 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return NULL;
|
||||
*valsize = uci->valsize;
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
}
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
@@ -489,6 +564,10 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
*valsize = uci->valsize;
|
||||
if (expires)
|
||||
*expires = uci->expires;
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
}
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
@@ -523,50 +602,56 @@ char *uwsgi_cache_get4(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
|
||||
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
|
||||
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
int ret = -1;
|
||||
|
||||
if (!index)
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
|
||||
if (index) {
|
||||
uci = cache_item(index);
|
||||
if (uci->keysize > 0) {
|
||||
// unmark blocks
|
||||
if (uc->blocks_bitmap) cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
// put back the block in unused stack
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
uc->unused_blocks_stack[uc->unused_blocks_stack_ptr] = index;
|
||||
|
||||
// unlink prev and next (if any)
|
||||
if (uci->prev) {
|
||||
struct uwsgi_cache_item *ucii = cache_item(uci->prev);
|
||||
ucii->next = uci->next;
|
||||
}
|
||||
else {
|
||||
// set next as the new entry point (could be 0)
|
||||
uc->hashtable[uci->hash % uc->hashsize] = uci->next;
|
||||
}
|
||||
|
||||
if (uci->next) {
|
||||
struct uwsgi_cache_item *ucii = cache_item(uci->next);
|
||||
ucii->prev = uci->prev;
|
||||
}
|
||||
|
||||
if (!uci->prev && !uci->next) {
|
||||
// reset hashtable entry
|
||||
uc->hashtable[uci->hash % uc->hashsize] = 0;
|
||||
}
|
||||
|
||||
if (uc->purge_lru)
|
||||
lru_remove_item(uc, index);
|
||||
|
||||
uc->n_items--;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
uci->keysize = 0;
|
||||
uci->valsize = 0;
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
uc->unused_blocks_stack[uc->unused_blocks_stack_ptr] = index;
|
||||
// unmark blocks
|
||||
if (uc->blocks_bitmap) {
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
}
|
||||
ret = 0;
|
||||
// relink collisioned entry
|
||||
if (uci->prev) {
|
||||
struct uwsgi_cache_item *ucii = cache_item(uci->prev);
|
||||
ucii->next = uci->next;
|
||||
}
|
||||
else {
|
||||
// set next as the new entry point (could be 0)
|
||||
uc->hashtable[uci->hash % uc->hashsize] = uci->next;
|
||||
}
|
||||
|
||||
if (uci->next) {
|
||||
struct uwsgi_cache_item *ucii = cache_item(uci->next);
|
||||
ucii->prev = uci->prev;
|
||||
}
|
||||
|
||||
if (!uci->prev && !uci->next) {
|
||||
// reset hashtable entry
|
||||
//uwsgi_log("!!! resetted hashtable entry !!!\n");
|
||||
uc->hashtable[uci->hash % uc->hashsize] = 0;
|
||||
}
|
||||
uci->hash = 0;
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
uci->expires = 0;
|
||||
|
||||
uc->n_items--;
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = uwsgi_now();
|
||||
}
|
||||
@@ -584,7 +669,10 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
unsigned long long restored = 0;
|
||||
|
||||
for (i = 0; i < uc->max_items; i++) {
|
||||
// reset unused blocks
|
||||
uc->unused_blocks_stack_ptr = 0;
|
||||
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
// valid record ?
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
if (uci->keysize) {
|
||||
@@ -596,7 +684,6 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
}
|
||||
else {
|
||||
// put this record in unused stack
|
||||
uc->first_available_block = i;
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
uc->unused_blocks_stack[uc->unused_blocks_stack_ptr] = i;
|
||||
}
|
||||
@@ -613,7 +700,6 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
struct uwsgi_cache_item *uci, *ucii;
|
||||
|
||||
// used to reset key allocation in bitmap mode
|
||||
uint8_t rollback_mode = 0;
|
||||
|
||||
int ret = -1;
|
||||
time_t now = 0;
|
||||
@@ -631,56 +717,59 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) {
|
||||
if (uc->first_available_block >= uc->max_items && !uc->unused_blocks_stack_ptr) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
goto end;
|
||||
}
|
||||
if (uc->unused_blocks_stack_ptr) {
|
||||
//uwsgi_log("!!! REUSING CACHE SLOT !!! (faci: %llu)\n", (unsigned long long) uwsgi.shared->cache_first_available_block);
|
||||
index = uc->unused_blocks_stack[uc->unused_blocks_stack_ptr];
|
||||
uc->unused_blocks_stack_ptr--;
|
||||
}
|
||||
else {
|
||||
rollback_mode = 1;
|
||||
index = uc->first_available_block;
|
||||
if (uc->first_available_block < uc->max_items) {
|
||||
rollback_mode = 2;
|
||||
uc->first_available_block++;
|
||||
if (!uc->unused_blocks_stack_ptr) {
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
uc->full++;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
if (!uc->unused_blocks_stack_ptr)
|
||||
goto end;
|
||||
}
|
||||
|
||||
index = uc->unused_blocks_stack[uc->unused_blocks_stack_ptr];
|
||||
uc->unused_blocks_stack_ptr--;
|
||||
|
||||
uci = cache_item(index);
|
||||
if (!uc->blocks_bitmap) {
|
||||
uci->first_block = index;
|
||||
}
|
||||
else {
|
||||
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
|
||||
//uwsgi_log("first block = %llu\n", uci->first_block);
|
||||
if (uci->first_block == 0xffffffffffffffffLLU) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
uc->full++;
|
||||
if (rollback_mode == 0) {
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
}
|
||||
else if (rollback_mode == 2) {
|
||||
uc->first_available_block--;
|
||||
}
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
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) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks;
|
||||
}
|
||||
}
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
if (uc->purge_lru)
|
||||
lru_add_item(uc, index);
|
||||
else if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!uc->next_scan || uc->next_scan > expires)
|
||||
uc->next_scan = expires;
|
||||
}
|
||||
uci->expires = expires;
|
||||
uci->hash = uc->hash->func(key, keylen);
|
||||
@@ -745,9 +834,16 @@ 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) && !(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
} else if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!uc->next_scan || uc->next_scan > expires)
|
||||
uc->next_scan = expires;
|
||||
}
|
||||
uci->expires = expires;
|
||||
}
|
||||
if (uc->blocks_bitmap) {
|
||||
@@ -755,22 +851,29 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uint64_t old_first_block = uci->first_block;
|
||||
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
|
||||
if (uci->first_block == 0xffffffffffffffffLLU) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
uc->full++;
|
||||
uci->first_block = old_first_block;
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
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) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks;
|
||||
}
|
||||
// unmark the old blocks
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
cache_unmark_blocks(uc, old_first_block, uci->valsize);
|
||||
}
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
@@ -965,39 +1068,66 @@ void *cache_udp_server_loop(void *ucache) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint64_t cache_sweeper_free_items(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
uint64_t freed_items = 0;
|
||||
|
||||
if (uc->no_expire || uc->purge_lru)
|
||||
return 0;
|
||||
|
||||
uwsgi_rlock(uc->lock);
|
||||
if (!uc->next_scan || uc->next_scan > (uint64_t)uwsgi.current_time) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
|
||||
// skip the first slot
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
|
||||
uwsgi_wlock(uc->lock);
|
||||
// we reset next scan time first, then we find the least
|
||||
// expiration time from those that are NOT expired yet.
|
||||
if (i == 1)
|
||||
uc->next_scan = 0;
|
||||
|
||||
if (uci->expires) {
|
||||
if (uci->expires <= (uint64_t)uwsgi.current_time) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, UWSGI_CACHE_FLAG_LOCAL);
|
||||
freed_items++;
|
||||
} else if (!uc->next_scan || uc->next_scan > uci->expires) {
|
||||
uc->next_scan = uci->expires;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
}
|
||||
|
||||
return freed_items;
|
||||
}
|
||||
|
||||
static void *cache_sweeper_loop(void *ucache) {
|
||||
|
||||
uint64_t i;
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
struct uwsgi_cache *uc = (struct uwsgi_cache *) ucache;
|
||||
|
||||
if (!uwsgi.cache_expire_freq)
|
||||
uwsgi.cache_expire_freq = 3;
|
||||
|
||||
// remove expired cache items TODO use rb_tree timeouts
|
||||
for (;;) {
|
||||
struct uwsgi_cache *uc;
|
||||
|
||||
for (uc = (struct uwsgi_cache *)ucache; uc; uc = uc->next) {
|
||||
uint64_t freed_items = cache_sweeper_free_items(uc);
|
||||
if (uwsgi.cache_report_freed_items && freed_items)
|
||||
uwsgi_log("freed %llu items for cache \"%s\"\n", (unsigned long long)freed_items, uc->name);
|
||||
}
|
||||
|
||||
sleep(uwsgi.cache_expire_freq);
|
||||
uint64_t freed_items = 0;
|
||||
// skip the first slot
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
if (uci->expires) {
|
||||
if (uci->expires < (uint64_t) uwsgi.current_time) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, UWSGI_CACHE_FLAG_LOCAL);
|
||||
freed_items++;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
}
|
||||
if (uwsgi.cache_report_freed_items && freed_items > 0) {
|
||||
uwsgi_log("freed %llu items for cache \"%s\"\n", (unsigned long long) freed_items, uc->name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1017,16 +1147,21 @@ void uwsgi_cache_sync_all() {
|
||||
|
||||
void uwsgi_cache_start_sweepers() {
|
||||
struct uwsgi_cache *uc = uwsgi.caches;
|
||||
|
||||
if (uwsgi.cache_no_expire)
|
||||
return;
|
||||
|
||||
while(uc) {
|
||||
pthread_t cache_sweeper;
|
||||
if (!uwsgi.cache_no_expire && !uc->no_expire) {
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, (void *) uc)) {
|
||||
if (!uc->no_expire && !uc->purge_lru) {
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("unable to run the sweeper for cache \"%s\" !!!\n", uc->name);
|
||||
uwsgi_log("unable to run the sweeper!!!\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("sweeper thread enabled for cache \"%s\"\n", uc->name);
|
||||
uwsgi_log("sweeper thread enabled\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
@@ -1097,12 +1232,15 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_keysize = NULL;
|
||||
char *c_store = NULL;
|
||||
char *c_store_sync = NULL;
|
||||
char *c_store_delete = NULL;
|
||||
char *c_nodes = NULL;
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
char *c_bitmap = NULL;
|
||||
char *c_use_last_modified = NULL;
|
||||
char *c_math_initial = NULL;
|
||||
char *c_ignore_full = NULL;
|
||||
char *c_purge_lru = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -1119,6 +1257,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"store", &c_store,
|
||||
"store_sync", &c_store_sync,
|
||||
"storesync", &c_store_sync,
|
||||
"store_delete", &c_store_delete,
|
||||
"storedelete", &c_store_delete,
|
||||
"node", &c_nodes,
|
||||
"nodes", &c_nodes,
|
||||
"sync", &c_sync,
|
||||
@@ -1130,6 +1270,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"bitmap", &c_bitmap,
|
||||
"lastmod", &c_use_last_modified,
|
||||
"math_initial", &c_math_initial,
|
||||
"ignore_full", &c_ignore_full,
|
||||
"purge_lru", &c_purge_lru,
|
||||
"lru", &c_purge_lru,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -1177,6 +1320,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->max_item_size = uc->blocksize * uc->blocks;
|
||||
}
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
if (c_ignore_full) uc->ignore_full = 1;
|
||||
|
||||
if (c_store_delete) uc->store_delete = 1;
|
||||
|
||||
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
|
||||
|
||||
@@ -1211,6 +1357,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
if (c_purge_lru)
|
||||
uc->purge_lru = 1;
|
||||
}
|
||||
|
||||
uwsgi_cache_init(uc);
|
||||
@@ -1466,7 +1614,10 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
|
||||
// we have a local cache !!!
|
||||
if (uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
if (uc->purge_lru)
|
||||
uwsgi_wlock(uc->lock);
|
||||
else
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
@@ -1483,7 +1634,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return NULL;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
@@ -1495,7 +1646,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
@@ -1526,7 +1677,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
}
|
||||
|
||||
// read the raw value from the socket
|
||||
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.socket_timeout)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
@@ -1585,7 +1736,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return 0;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
@@ -1597,7 +1748,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
@@ -1652,7 +1803,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1670,7 +1821,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1730,7 +1881,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1742,7 +1893,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1788,7 +1939,7 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
if (uc) {
|
||||
uint64_t i;
|
||||
uwsgi_wlock(uc->lock);
|
||||
for (i = 1; i < uwsgi.caches->max_items; i++) {
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
if (uwsgi_cache_del2(uc, NULL, 0, i, 0)) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return -1;
|
||||
@@ -1803,7 +1954,7 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1815,7 +1966,7 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1859,7 +2010,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.socket_timeout)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
@@ -1867,7 +2018,7 @@ 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], NULL, NULL)) {
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.socket_timeout, NULL, NULL)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
@@ -1876,7 +2027,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *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])) {
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.socket_timeout)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ extern struct uwsgi_server uwsgi;
|
||||
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];
|
||||
if (timeout == 0) timeout = uwsgi.socket_timeout;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
|
||||
+54
-1
@@ -81,6 +81,22 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_readline(char *key, char *value) {
|
||||
|
||||
char line[1024];
|
||||
|
||||
FILE *fh = fopen(uwsgi.logic_opt_data, "r");
|
||||
if (fh) {
|
||||
while (fgets(line, 1024, fh)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi_chomp(uwsgi_str(line))), 0);
|
||||
}
|
||||
fclose(fh);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_error_open(uwsgi.logic_opt_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
@@ -278,6 +294,26 @@ int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_hostname(char *key, char *value) {
|
||||
|
||||
if (!strcmp(uwsgi.hostname, 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_hostname(char *key, char *value) {
|
||||
|
||||
if (strcmp(uwsgi.hostname, 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;
|
||||
@@ -384,7 +420,8 @@ void add_exported_option_do(char *key, char *value, int configured, int placehol
|
||||
if (uwsgi.logic_opt_running)
|
||||
goto add;
|
||||
|
||||
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
|
||||
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")
|
||||
|| !strcmp(key, "end-if") || !strcmp(key, "end-for")) {
|
||||
if (uwsgi.logic_opt_data) {
|
||||
free(uwsgi.logic_opt_data);
|
||||
}
|
||||
@@ -799,3 +836,19 @@ char *uwsgi_manage_placeholder(char *key) {
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_resolve(char *opt, char *value, void *foo) {
|
||||
char *equal = strchr(value, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid resolve syntax, must be placeholder=domain\n");
|
||||
exit(1);
|
||||
}
|
||||
char *ip = uwsgi_resolve_ip(equal+1);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve name %s\n", equal+1);
|
||||
uwsgi_error("uwsgi_resolve_ip()");
|
||||
exit(1);
|
||||
}
|
||||
char *new_opt = uwsgi_concat2n(value, (equal-value)+1, ip, strlen(ip));
|
||||
uwsgi_opt_set_placeholder(opt, new_opt, (void *) 1);
|
||||
}
|
||||
|
||||
+191
-19
@@ -55,7 +55,7 @@ void uwsgi_daemons_smart_check() {
|
||||
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);
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
@@ -237,12 +237,12 @@ void uwsgi_detach_daemons() {
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, SIGTERM);
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
sleep(1);
|
||||
waitpid(-ud->pid, &waitpid_status, WNOHANG);
|
||||
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);
|
||||
kill(-(ud->pid), SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -253,18 +253,19 @@ void uwsgi_detach_daemons() {
|
||||
}
|
||||
}
|
||||
|
||||
static int daemon_spawn(void *);
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int throttle = 0;
|
||||
ud->throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
ud->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;
|
||||
if (ud->throttle <= 0) ud->throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -291,9 +292,74 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_close_all_sockets();
|
||||
uwsgi_close_all_fds();
|
||||
|
||||
if (ud->chdir) {
|
||||
if (chdir(ud->chdir)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && defined(CLONE_NEWPID)
|
||||
if (ud->ns_pid) {
|
||||
// we need to create a new session
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/setsid()");
|
||||
exit(1);
|
||||
}
|
||||
// avoid the need to set stop_signal in attach-daemon2
|
||||
signal(SIGTERM, end_me);
|
||||
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
pid_t pid = clone((int (*)(void *))daemon_spawn, stack + PTHREAD_STACK_MIN, SIGCHLD | CLONE_NEWPID, (void *) ud);
|
||||
if (pid > 0) {
|
||||
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/prctl()");
|
||||
}
|
||||
#endif
|
||||
// block all signals except SIGTERM
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
sigdelset(&smask, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &smask, NULL);
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/waitpid()");
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
uwsgi_error("uwsgi_spawn_daemon()/clone()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
daemon_spawn((void *) ud);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int daemon_spawn(void *arg) {
|
||||
|
||||
struct uwsgi_daemon *ud = (struct uwsgi_daemon *) arg;
|
||||
|
||||
if (ud->gid) {
|
||||
if (setgid(ud->gid)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ud->uid) {
|
||||
if (setuid(ud->uid)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ud->daemonize) {
|
||||
/* refork... */
|
||||
pid = fork();
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
@@ -304,7 +370,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
@@ -315,7 +381,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (!ud->pidfile) {
|
||||
#ifdef __linux__
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
@@ -323,20 +389,17 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep((unsigned int) throttle);
|
||||
if (ud->throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, ud->throttle);
|
||||
sleep((unsigned int) ud->throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
|
||||
uwsgi_exec_command_with_args(ud->command);
|
||||
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
|
||||
|
||||
// never here;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -347,6 +410,8 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
char *space = NULL;
|
||||
int stop_signal = SIGTERM;
|
||||
int reload_signal = 0;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
@@ -385,7 +450,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
}
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi.daemons;
|
||||
}
|
||||
else {
|
||||
@@ -394,7 +459,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud = uwsgi_ud->next;
|
||||
}
|
||||
|
||||
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
old_ud->next = uwsgi_ud;
|
||||
}
|
||||
|
||||
@@ -409,6 +474,8 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
uwsgi_ud->control = 0;
|
||||
uwsgi_ud->stop_signal = stop_signal;
|
||||
uwsgi_ud->reload_signal = reload_signal;
|
||||
if (!strcmp(opt, "attach-control-daemon")) {
|
||||
uwsgi_ud->control = 1;
|
||||
}
|
||||
@@ -419,3 +486,108 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
|
||||
|
||||
char *d_command = NULL;
|
||||
char *d_freq = NULL;
|
||||
char *d_pidfile = NULL;
|
||||
char *d_control = NULL;
|
||||
char *d_legion = NULL;
|
||||
char *d_daemonize = NULL;
|
||||
char *d_touch = NULL;
|
||||
char *d_stopsignal = NULL;
|
||||
char *d_reloadsignal = NULL;
|
||||
char *d_stdin = NULL;
|
||||
char *d_uid = NULL;
|
||||
char *d_gid = NULL;
|
||||
char *d_ns_pid = NULL;
|
||||
char *d_chdir = NULL;
|
||||
|
||||
char *arg = uwsgi_str(value);
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"command", &d_command,
|
||||
"cmd", &d_command,
|
||||
"exec", &d_command,
|
||||
"freq", &d_freq,
|
||||
"pidfile", &d_pidfile,
|
||||
"control", &d_control,
|
||||
"daemonize", &d_daemonize,
|
||||
"daemon", &d_daemonize,
|
||||
"touch", &d_touch,
|
||||
"stopsignal", &d_stopsignal,
|
||||
"stop_signal", &d_stopsignal,
|
||||
"reloadsignal", &d_reloadsignal,
|
||||
"reload_signal", &d_reloadsignal,
|
||||
"stdin", &d_stdin,
|
||||
"uid", &d_uid,
|
||||
"gid", &d_gid,
|
||||
"ns_pid", &d_ns_pid,
|
||||
"chdir", &d_chdir,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid --%s keyval syntax\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!d_command) {
|
||||
uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifndef UWSGI_SSL
|
||||
if (d_legion) {
|
||||
uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi.daemons;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_ud) {
|
||||
old_ud = uwsgi_ud;
|
||||
uwsgi_ud = uwsgi_ud->next;
|
||||
}
|
||||
|
||||
uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
old_ud->next = uwsgi_ud;
|
||||
}
|
||||
uwsgi_ud->command = d_command;
|
||||
uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
|
||||
uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
|
||||
uwsgi_ud->pidfile = d_pidfile;
|
||||
uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
|
||||
uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
|
||||
uwsgi_ud->control = d_control ? 1 : 0;
|
||||
uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
|
||||
uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
|
||||
uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = d_legion;
|
||||
#endif
|
||||
uwsgi_ud->ns_pid = d_ns_pid ? 1 : 0;
|
||||
|
||||
uwsgi_ud->chdir = d_chdir;
|
||||
|
||||
if (d_touch) {
|
||||
size_t i,rlen = 0;
|
||||
char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
|
||||
for(i=0;i<rlen;i++) {
|
||||
uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
|
||||
}
|
||||
if (argv) free(argv);
|
||||
}
|
||||
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
free(arg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+899
-572
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,14 @@ void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
void uwsgi_405(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "405 Method Not Allowed", 22)) 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, "Method Not Allowed", 18);
|
||||
}
|
||||
|
||||
void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *redirect = NULL;
|
||||
|
||||
+6
-5
@@ -414,11 +414,11 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
uwsgi_error("port_getn()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_getn()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint_t i;
|
||||
@@ -452,6 +452,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
else {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
|
||||
+11
@@ -48,6 +48,14 @@ static void subscriptions_blocker() {
|
||||
}
|
||||
}
|
||||
|
||||
static void emperor_rescan() {
|
||||
if (uwsgi.emperor_pid > 0) {
|
||||
if (kill(uwsgi.emperor_pid, SIGWINCH)) {
|
||||
uwsgi_error("emperor_rescan()/kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
this is called as soon as possibile allowing plugins (or hooks) to override it
|
||||
@@ -72,8 +80,10 @@ void uwsgi_master_fifo_prepare() {
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['B'] = vassal_sos;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['E'] = emperor_rescan;
|
||||
uwsgi_fifo_table['f'] = uwsgi_refork_master;
|
||||
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
|
||||
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
|
||||
@@ -122,6 +132,7 @@ int uwsgi_master_fifo_manage(int fd) {
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
event_queue_del_fd(uwsgi.master_queue, uwsgi.master_fifo_fd, event_queue_read());
|
||||
close(fd);
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
|
||||
+137
-162
@@ -8,207 +8,182 @@ extern struct uwsgi_server uwsgi;
|
||||
#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) {
|
||||
static int fsmon_add(struct uwsgi_fsmon *fs) {
|
||||
#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()");
|
||||
uwsgi_error("fsmon_add()/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()");
|
||||
uwsgi_error("fsmon_add()/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);
|
||||
int wd = inotify_add_watch(inotify_fd, fs->path, 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()");
|
||||
uwsgi_error("fsmon_add()/inotify_add_watch()");
|
||||
return -1;
|
||||
}
|
||||
usl->custom = inotify_fd;
|
||||
usl->custom2 = wd;
|
||||
fs->fd = inotify_fd;
|
||||
fs->id = 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;
|
||||
}
|
||||
struct kevent kev;
|
||||
int fd = open(fs->path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(fs->path);
|
||||
uwsgi_error("fsmon_add()/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;
|
||||
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("fsmon_add()/kevent()");
|
||||
return -1;
|
||||
}
|
||||
fs->fd = 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;
|
||||
static void fsmon_reload(struct uwsgi_fsmon *fs) {
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
static void fsmon_brutal_reload(struct uwsgi_fsmon *fs) {
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
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;
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
static void fsmon_signal(struct uwsgi_fsmon *fs) {
|
||||
uwsgi_route_signal(atoi((char *) fs->data));
|
||||
}
|
||||
|
||||
void uwsgi_fsmon_setup() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.fs_reload) {
|
||||
uwsgi_register_fsmon(usl->value, fsmon_reload, NULL);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.fs_brutal_reload) {
|
||||
uwsgi_register_fsmon(usl->value, fsmon_brutal_reload, NULL);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.fs_signal) {
|
||||
char *copy = uwsgi_str(usl->value);
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
free(copy);
|
||||
continue;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_register_fsmon(copy, fsmon_signal, space + 1);
|
||||
}
|
||||
|
||||
struct uwsgi_fsmon *fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fsmon_add(fs)) {
|
||||
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", fs->path);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", fs->path);
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_fsmon *uwsgi_register_fsmon(char *path, void (*func) (struct uwsgi_fsmon *), void *data) {
|
||||
struct uwsgi_fsmon *old_fs = NULL, *fs = uwsgi.fsmon;
|
||||
while(fs) {
|
||||
old_fs = fs;
|
||||
fs = fs->next;
|
||||
}
|
||||
|
||||
fs = uwsgi_calloc(sizeof(struct uwsgi_fsmon));
|
||||
fs->path = path;
|
||||
fs->func = func;
|
||||
fs->data = data;
|
||||
|
||||
if (old_fs) {
|
||||
old_fs->next = fs;
|
||||
}
|
||||
else {
|
||||
uwsgi.fsmon = fs;
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
static struct uwsgi_fsmon *uwsgi_fsmon_ack(int interesting_fd) {
|
||||
struct uwsgi_fsmon *found_fs = NULL;
|
||||
struct uwsgi_fsmon *fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fs->fd == interesting_fd) {
|
||||
found_fs = fs;
|
||||
break;
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
if (!found_fs)
|
||||
return NULL;
|
||||
found_fs = NULL;
|
||||
unsigned int isize = 0;
|
||||
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
|
||||
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
|
||||
return 0;
|
||||
}
|
||||
if (isize == 0) return NULL;
|
||||
if (ioctl(interesting_fd, FIONREAD, &isize) < 0) {
|
||||
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
|
||||
return NULL;
|
||||
}
|
||||
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;
|
||||
ssize_t len = read(interesting_fd, ie, isize);
|
||||
if (len < 0) {
|
||||
free(ie);
|
||||
uwsgi_error("uwsgi_fsmon_ack()/read()");
|
||||
return NULL;
|
||||
}
|
||||
fs = uwsgi.fsmon;
|
||||
while (fs) {
|
||||
if (fs->fd == interesting_fd && fs->id == ie->wd) {
|
||||
found_fs = fs;
|
||||
break;
|
||||
}
|
||||
fs = fs->next;
|
||||
}
|
||||
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;
|
||||
return found_fs;
|
||||
}
|
||||
|
||||
int uwsgi_fsmon_event(int interesting_fd) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
|
||||
struct uwsgi_fsmon *fs = uwsgi_fsmon_ack(interesting_fd);
|
||||
if (!fs)
|
||||
return 0;
|
||||
|
||||
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));
|
||||
uwsgi_log_verbose("[uwsgi-fsmon] detected event on \"%s\"\n", fs->path);
|
||||
fs->func(fs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
ug->num = num;
|
||||
ug->fullname = fullname;
|
||||
ug->data = data;
|
||||
ug->uid = 0;
|
||||
ug->gid = 0;
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
||||
@@ -90,6 +92,24 @@ void gateway_respawn(int id) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_gateway, "as-gateway", 1);
|
||||
|
||||
if (ug->gid) {
|
||||
uwsgi_log("%s %d setgid() to %d\n", ug->name, ug->num, (int) ug->gid);
|
||||
if (setgid(ug->gid)) {
|
||||
uwsgi_error("gateway_respawn()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ug->uid) {
|
||||
uwsgi_log("%s %d setuid() to %d\n", ug->name, ug->num, (int) ug->uid);
|
||||
if (setuid(ug->uid)) {
|
||||
uwsgi_error("gateway_respawn()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ug->loop(id, ug->data);
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
|
||||
+362
-4
@@ -47,6 +47,18 @@ void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_alarm(char *arg) {
|
||||
char *space = strchr(arg,' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid alarm hook syntax, must be: <alarm> <msg>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
|
||||
*space = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chdir(char *arg) {
|
||||
int ret = chdir(arg);
|
||||
if (ret) {
|
||||
@@ -55,6 +67,22 @@ static int uwsgi_hook_chdir(char *arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_mkdir(char *arg) {
|
||||
int ret = mkdir(arg, 0777);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_mkdir()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_putenv(char *arg) {
|
||||
int ret = putenv(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_putenv()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
@@ -121,7 +149,7 @@ static int uwsgi_hook_write(char *arg) {
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY);
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
@@ -138,6 +166,230 @@ static int uwsgi_hook_write(char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_creat(char *arg) {
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_append(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook append syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
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_append()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_writen(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook writen syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
memcpy(buf, space+1, l);
|
||||
buf[l] = '\n';
|
||||
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
|
||||
uwsgi_error("uwsgi_hook_writen()/write()");
|
||||
free(buf);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
free(buf);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_appendn(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
memcpy(buf, space+1, l);
|
||||
buf[l] = '\n';
|
||||
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
|
||||
uwsgi_error("uwsgi_hook_appendn()/write()");
|
||||
free(buf);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
free(buf);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int uwsgi_hook_chmod(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook chmod syntax, must be: <file> <mode>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int error = 0;
|
||||
mode_t mask = uwsgi_mode_t(space+1, &error);
|
||||
if (error) {
|
||||
uwsgi_log("invalid hook chmod mask: %s\n", space+1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = chmod(arg, mask);
|
||||
*space = ' ';
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chmod()/chmod()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_sticky(char *arg) {
|
||||
struct stat st;
|
||||
if (stat(arg, &st)) {
|
||||
uwsgi_error("uwsgi_hook_sticky()/stat()");
|
||||
return -1;
|
||||
}
|
||||
if (chmod(arg, st.st_mode | S_ISVTX)) {
|
||||
uwsgi_error("uwsgi_hook_sticky()/chmod()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_chown(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
char *space2 = strchr(space+1, ' ');
|
||||
if (!space2) {
|
||||
*space = ' ';
|
||||
uwsgi_log("invalid hook chown syntax, must be: <file> <uid> <gid>\n");
|
||||
return -1;
|
||||
}
|
||||
*space2 = 0;
|
||||
|
||||
struct passwd *pw = getpwnam(space+1);
|
||||
if (!pw) {
|
||||
uwsgi_log("unable to find uid %s\n", space+1);
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct group *gr = getgrnam(space2+1);
|
||||
if (!gr) {
|
||||
uwsgi_log("unable to find gid %s\n", space2+1);
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
return -1;
|
||||
}
|
||||
int ret = chown(arg, pw->pw_uid, gr->gr_gid);
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chown()/chown)");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chown2(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
char *space2 = strchr(space+1, ' ');
|
||||
if (!space2) {
|
||||
*space = ' ';
|
||||
uwsgi_log("invalid hook chown2 syntax, must be: <file> <uid> <gid>\n");
|
||||
return -1;
|
||||
}
|
||||
*space2 = 0;
|
||||
|
||||
if (!is_a_number(space+1)) {
|
||||
uwsgi_log("invalid hook chown2 syntax, uid must be a number\n");
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_a_number(space2+1)) {
|
||||
uwsgi_log("invalid hook chown2 syntax, gid must be a number\n");
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = chown(arg, atoi(space+1), atoi(space2+1));
|
||||
*space = ' ';
|
||||
*space2 = ' ';
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chown2()/chown)");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __sun__
|
||||
extern int sethostname(char *, int);
|
||||
#endif
|
||||
static int uwsgi_hook_hostname(char *arg) {
|
||||
#ifdef __CYGWIN__
|
||||
return -1;
|
||||
#else
|
||||
return sethostname(arg, strlen(arg));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callint(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
@@ -233,12 +485,82 @@ static int uwsgi_hook_callret(char *arg) {
|
||||
return func();
|
||||
}
|
||||
|
||||
static int uwsgi_hook_rpc(char *arg) {
|
||||
|
||||
int ret = -1;
|
||||
size_t i, argc = 0;
|
||||
char **rargv = uwsgi_split_quoted(arg, strlen(arg), " \t", &argc);
|
||||
if (!argc) goto end;
|
||||
if (argc > 256) goto destroy;
|
||||
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
|
||||
char *node = NULL;
|
||||
char *func = rargv[0];
|
||||
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
node = at + 1;
|
||||
}
|
||||
|
||||
for(i=0;i<(argc-1);i++) {
|
||||
size_t a_len = strlen(rargv[i+1]);
|
||||
if (a_len > 0xffff) goto destroy;
|
||||
argv[i] = rargv[i+1] ;
|
||||
argvs[i] = a_len;
|
||||
}
|
||||
|
||||
uint64_t size = 0;
|
||||
// response must be always freed
|
||||
char *response = uwsgi_do_rpc(node, func, argc-1, argv, argvs, &size);
|
||||
if (response) {
|
||||
if (at) *at = '@';
|
||||
uwsgi_log("[rpc result from \"%s\"] %.*s\n", rargv[0], size, response);
|
||||
free(response);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
destroy:
|
||||
for(i=0;i<argc;i++) {
|
||||
free(rargv[i]);
|
||||
}
|
||||
end:
|
||||
free(rargv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_retryrpc(char *arg) {
|
||||
for(;;) {
|
||||
int ret = uwsgi_hook_rpc(arg);
|
||||
if (!ret) break;
|
||||
sleep(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
uwsgi_register_hook("chdir", uwsgi_hook_chdir);
|
||||
|
||||
uwsgi_register_hook("mkdir", uwsgi_hook_mkdir);
|
||||
uwsgi_register_hook("putenv", uwsgi_hook_putenv);
|
||||
uwsgi_register_hook("chmod", uwsgi_hook_chmod);
|
||||
uwsgi_register_hook("chown", uwsgi_hook_chown);
|
||||
uwsgi_register_hook("chown2", uwsgi_hook_chown2);
|
||||
|
||||
uwsgi_register_hook("sticky", uwsgi_hook_sticky);
|
||||
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("create", uwsgi_hook_creat);
|
||||
uwsgi_register_hook("creat", uwsgi_hook_creat);
|
||||
|
||||
uwsgi_register_hook("write", uwsgi_hook_write);
|
||||
uwsgi_register_hook("writen", uwsgi_hook_writen);
|
||||
uwsgi_register_hook("append", uwsgi_hook_append);
|
||||
uwsgi_register_hook("appendn", uwsgi_hook_appendn);
|
||||
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
|
||||
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
|
||||
|
||||
@@ -251,9 +573,17 @@ void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
uwsgi_register_hook("hostname", uwsgi_hook_hostname);
|
||||
|
||||
uwsgi_register_hook("alarm", uwsgi_hook_alarm);
|
||||
|
||||
uwsgi_register_hook("rpc", uwsgi_hook_rpc);
|
||||
uwsgi_register_hook("retryrpc", uwsgi_hook_retryrpc);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
uwsgi_register_hook("log", uwsgi_hook_print);
|
||||
}
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
@@ -265,17 +595,45 @@ void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
|
||||
int private = 0;
|
||||
char *action = usl->value;
|
||||
// private hook ?
|
||||
if (action[0] == '!') {
|
||||
action++;
|
||||
private = 1;
|
||||
}
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
|
||||
if (!uh) {
|
||||
uwsgi_log("hook not found: %s\n", usl->value);
|
||||
uwsgi_log("hook action not found: %s\n", action);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
if (private) {
|
||||
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
}
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
uwsgi_log_verbose("FATAL hook failed, destroying instance\n");
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.workers) {
|
||||
if (uwsgi.workers[0].pid == getpid()) {
|
||||
kill_them_all(0);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (kill(uwsgi.workers[0].pid, SIGINT)) {
|
||||
uwsgi_error("uwsgi_hooks_run()/kill()");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-13
@@ -3,9 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct http_status_codes {
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
};
|
||||
|
||||
/* statistically ordered */
|
||||
@@ -73,7 +73,7 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.stats_pusher_default_freq = 3;
|
||||
|
||||
uwsgi.original_log_fd = -1;
|
||||
uwsgi.original_log_fd = 2;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
@@ -113,17 +113,18 @@ void uwsgi_init_default() {
|
||||
uwsgi.log_master_bufsize = 8192;
|
||||
|
||||
uwsgi.worker_reload_mercy = 60;
|
||||
uwsgi.mule_reload_mercy = 60;
|
||||
|
||||
uwsgi.max_vars = MAX_VARS;
|
||||
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
|
||||
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
|
||||
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
|
||||
uwsgi.socket_timeout = 4;
|
||||
uwsgi.logging_options.enabled = 1;
|
||||
|
||||
// a workers hould be running for at least 10 seconds
|
||||
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
|
||||
uwsgi.min_worker_lifetime = 10;
|
||||
|
||||
uwsgi.shared->spooler_frequency = 30;
|
||||
uwsgi.spooler_frequency = 30;
|
||||
|
||||
uwsgi.shared->spooler_signal_pipe[0] = -1;
|
||||
uwsgi.shared->spooler_signal_pipe[1] = -1;
|
||||
@@ -183,6 +184,8 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.master_fifo_fd = -1;
|
||||
uwsgi_master_fifo_prepare();
|
||||
|
||||
uwsgi.notify_socket_fd = -1;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -196,7 +199,7 @@ void uwsgi_setup_reload() {
|
||||
uwsgi.reloads++;
|
||||
//convert reloads to string
|
||||
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
|
||||
if (rlen > 0) {
|
||||
if (rlen > 0 && rlen < 10) {
|
||||
env_reload_buf[rlen] = 0;
|
||||
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
@@ -413,7 +416,7 @@ void sanitize_args() {
|
||||
uwsgi.cores = uwsgi.threads;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
if (!uwsgi.post_buffering) {
|
||||
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
|
||||
}
|
||||
@@ -449,13 +452,13 @@ void sanitize_args() {
|
||||
}
|
||||
}
|
||||
|
||||
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]) {
|
||||
if (uwsgi.max_worker_lifetime > 0 && uwsgi.min_worker_lifetime >= uwsgi.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]);
|
||||
uwsgi.min_worker_lifetime, uwsgi.max_worker_lifetime);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.logging_options.memory_report != 1 && uwsgi.force_get_memusage != 1) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ int uwsgi_waitfd_event(int fd, int timeout, int event) {
|
||||
struct pollfd upoll;
|
||||
|
||||
if (!timeout)
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
timeout = uwsgi.socket_timeout;
|
||||
|
||||
timeout = timeout * 1000;
|
||||
if (timeout < 0)
|
||||
@@ -392,6 +392,26 @@ static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_callint(char *url, size_t *size, int add_zero) {
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, url);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *s = uwsgi_num2str(func());
|
||||
*size = strlen(s);
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, s, strlen(s));
|
||||
free(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;
|
||||
@@ -517,12 +537,28 @@ fallback:
|
||||
goto end;
|
||||
}
|
||||
|
||||
// is it a potential virtual file (/proc, /sys...) ?
|
||||
int is_virtual = 0;
|
||||
if (sb.st_size == 0) {
|
||||
is_virtual = 1;
|
||||
sb.st_size = 4096;
|
||||
}
|
||||
|
||||
buffer = uwsgi_malloc(sb.st_size + add_zero);
|
||||
|
||||
len = read(fd, buffer, sb.st_size);
|
||||
if (len != sb.st_size) {
|
||||
uwsgi_error("read()");
|
||||
exit(1);
|
||||
if (!is_virtual) {
|
||||
if (len != sb.st_size) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (len >= 0) {
|
||||
sb.st_size = len;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("read()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
@@ -535,7 +571,46 @@ fallback:
|
||||
end:
|
||||
|
||||
if (magic_table) {
|
||||
|
||||
// here we inject blobs
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
if (uwsgi.inject_before || uwsgi.inject_after) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
uwsgi_foreach(usl, uwsgi.inject_before) {
|
||||
size_t rlen = 0;
|
||||
char *before = uwsgi_open_and_read(usl->value, &rlen, 0, NULL);
|
||||
if (uwsgi_buffer_append(ub, before, rlen)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
free(before);
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, buffer, *size - add_zero)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.inject_after) {
|
||||
size_t rlen = 0;
|
||||
char *after = uwsgi_open_and_read(usl->value, &rlen, 0, NULL);
|
||||
if (uwsgi_buffer_append(ub, after, rlen)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
free(after);
|
||||
}
|
||||
if (add_zero) {
|
||||
if (uwsgi_buffer_append(ub, "\0", 1)) {
|
||||
uwsgi_log("unable to inject data in the config file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
*size = ub->pos;
|
||||
// free resources
|
||||
free(buffer);
|
||||
buffer = ub->buf;
|
||||
// aboid destroying buffer
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
magic_buf = magic_sub(buffer, *size, size, magic_table);
|
||||
free(buffer);
|
||||
return magic_buf;
|
||||
@@ -586,11 +661,13 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
|
||||
len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recvmsg()");
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (code && code_len > 0) {
|
||||
if (uwsgi_strncmp(id, code_len, code, code_len)) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -606,15 +683,19 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
|
||||
}
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg)
|
||||
if (!cmsg) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((size_t) (cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) > (size_t) (sizeof(int) * (count + 1))) {
|
||||
uwsgi_log("not enough space for sockets data, consider increasing it\n");
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -906,6 +987,7 @@ int uwsgi_read_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
|
||||
int ret;
|
||||
|
||||
errno = 0;
|
||||
ssize_t rlen = read(fd, buf, len);
|
||||
if (rlen > 0) {
|
||||
return rlen;
|
||||
@@ -916,8 +998,10 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
|
||||
}
|
||||
return -1;
|
||||
wait:
|
||||
errno = 0;
|
||||
ret = uwsgi.wait_read_hook(fd, timeout);
|
||||
if (ret > 0) {
|
||||
errno = 0;
|
||||
rlen = read(fd, buf, len);
|
||||
if (rlen > 0) {
|
||||
return rlen;
|
||||
@@ -1185,6 +1269,7 @@ void uwsgi_setup_schemes() {
|
||||
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
|
||||
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
|
||||
uwsgi_register_scheme("call", uwsgi_scheme_call);
|
||||
uwsgi_register_scheme("callint", uwsgi_scheme_callint);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
|
||||
@@ -1216,3 +1301,204 @@ void uwsgi_remap_fd(int fd, char *filename) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_is_connected(int fd) {
|
||||
int soopt;
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
return 0;
|
||||
}
|
||||
/* is something bad ? */
|
||||
if (soopt) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_pass_cred(int fd, char *code, size_t code_len) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct msghdr cr_msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec cr_iov;
|
||||
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
cr_iov.iov_base = code;
|
||||
cr_iov.iov_len = code_len;
|
||||
|
||||
cr_msg.msg_name = NULL;
|
||||
cr_msg.msg_namelen = 0;
|
||||
|
||||
cr_msg.msg_iov = &cr_iov;
|
||||
cr_msg.msg_iovlen = 1;
|
||||
|
||||
cr_msg.msg_flags = 0;
|
||||
cr_msg.msg_control = cr_msg_control;
|
||||
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&cr_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_CREDENTIALS;
|
||||
|
||||
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
|
||||
u->pid = getpid();
|
||||
u->uid = getuid();
|
||||
u->gid = getgid();
|
||||
|
||||
if (sendmsg(fd, &cr_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_pass_cred()/sendmsg()");
|
||||
free(cr_msg_control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cr_msg_control);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_pass_cred2(int fd, char *code, size_t code_len, struct sockaddr *addr, size_t addr_len) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct msghdr cr_msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec cr_iov;
|
||||
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
cr_iov.iov_base = code;
|
||||
cr_iov.iov_len = code_len;
|
||||
|
||||
cr_msg.msg_name = addr;
|
||||
cr_msg.msg_namelen = addr_len;
|
||||
|
||||
cr_msg.msg_iov = &cr_iov;
|
||||
cr_msg.msg_iovlen = 1;
|
||||
|
||||
cr_msg.msg_flags = 0;
|
||||
cr_msg.msg_control = cr_msg_control;
|
||||
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&cr_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_CREDENTIALS;
|
||||
|
||||
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
|
||||
u->pid = getpid();
|
||||
u->uid = getuid();
|
||||
u->gid = getgid();
|
||||
|
||||
if (sendmsg(fd, &cr_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_pass_cred2()/sendmsg()");
|
||||
free(cr_msg_control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cr_msg_control);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_recv_cred(int fd, char *code, size_t code_len, pid_t *pid, uid_t *uid, gid_t *gid) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct iovec iov;
|
||||
int ret = -1;
|
||||
|
||||
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
iov.iov_base = uwsgi_malloc(code_len);
|
||||
iov.iov_len = code_len;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
ssize_t len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("uwsgi_recv_cred()/recvmsg()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg) goto clear;
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(code, code_len, iov.iov_base, iov.iov_len)) goto clear;
|
||||
|
||||
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
|
||||
*pid = u->pid;
|
||||
*uid = u->uid;
|
||||
*gid = u->gid;
|
||||
ret = 0;
|
||||
|
||||
clear:
|
||||
free(msg_control);
|
||||
free(iov.iov_base);
|
||||
return ret;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t uwsgi_recv_cred2(int fd, char *buf, size_t buf_len, pid_t *pid, uid_t *uid, gid_t *gid) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct iovec iov;
|
||||
ssize_t ret = -1;
|
||||
|
||||
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = buf_len;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
ssize_t len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("uwsgi_recv_cred2()/recvmsg()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg) goto clear;
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
|
||||
*pid = u->pid;
|
||||
*uid = u->uid;
|
||||
*gid = u->gid;
|
||||
ret = len;
|
||||
|
||||
clear:
|
||||
free(msg_control);
|
||||
return ret;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+199
-4
@@ -4,13 +4,207 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#if defined(UWSGI_JSON_YAJL_OLD)
|
||||
#include <yajl/yajl_parse.h>
|
||||
|
||||
struct uwsgi_yajl_old_state {
|
||||
char *object;
|
||||
char *key;
|
||||
int in_object;
|
||||
int is_array;
|
||||
};
|
||||
|
||||
static int uwsgi_yajl_cb_null(void *ctx) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, strdup("0"), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_boolean(void *ctx, int b) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
if (b) {
|
||||
add_exported_option(uyos->key, strdup("1"), 0);
|
||||
}
|
||||
else {
|
||||
add_exported_option(uyos->key, strdup("0"), 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_integer(void *ctx, long n) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, uwsgi_64bit2str((int64_t) n), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_double(void *ctx, double n) {
|
||||
return uwsgi_yajl_cb_integer(ctx, (long) n);
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_string(void *ctx, const unsigned char *s, unsigned int s_len) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->key) return 1;
|
||||
add_exported_option(uyos->key, uwsgi_concat2n((char *)s, (size_t)s_len, "", 0), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_number(void *ctx, const char *n, unsigned int n_len) {
|
||||
return uwsgi_yajl_cb_string(ctx, (const unsigned char *)n, n_len);
|
||||
}
|
||||
|
||||
static int uwsgi_yajl_cb_map_key(void *ctx, const unsigned char *s, unsigned int s_len) {
|
||||
struct uwsgi_yajl_old_state *uyos = (struct uwsgi_yajl_old_state *) ctx;
|
||||
if (!uyos->in_object) {
|
||||
if (!uwsgi_strncmp(uyos->object, strlen(uyos->object), (char *)s, (size_t)s_len)) {
|
||||
uyos->in_object = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uyos->key = uwsgi_concat2n((char *)s, (size_t)s_len, "", 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static yajl_callbacks callbacks = {
|
||||
.yajl_null = uwsgi_yajl_cb_null,
|
||||
.yajl_boolean = uwsgi_yajl_cb_boolean,
|
||||
.yajl_integer = uwsgi_yajl_cb_integer,
|
||||
.yajl_double = uwsgi_yajl_cb_double,
|
||||
.yajl_number = uwsgi_yajl_cb_number,
|
||||
.yajl_string = uwsgi_yajl_cb_string,
|
||||
.yajl_start_map = NULL,
|
||||
.yajl_map_key = uwsgi_yajl_cb_map_key,
|
||||
.yajl_end_map = NULL,
|
||||
.yajl_start_array = NULL,
|
||||
.yajl_end_array = NULL,
|
||||
};
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
|
||||
char *object_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
else {
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
object_asked = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_yajl_old_state uyos;
|
||||
memset(&uyos, 0, sizeof(struct uwsgi_yajl_old_state));
|
||||
uyos.object = object_asked;
|
||||
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
|
||||
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
yajl_handle hand = yajl_alloc(&callbacks, NULL, NULL, &uyos);
|
||||
|
||||
yajl_status s = yajl_parse(hand, (const unsigned char *)json_data, len);
|
||||
if (s != yajl_status_ok) {
|
||||
uwsgi_log("%s\n", yajl_get_error(hand, 1, (const unsigned char *)json_data, len));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined(UWSGI_JSON_YAJL)
|
||||
#include <yajl/yajl_tree.h>
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
size_t len = 0;
|
||||
|
||||
char *object_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
else {
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
object_asked = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
|
||||
char *json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
char errbuf[1024];
|
||||
yajl_val node = yajl_tree_parse((const char *)json_data, errbuf, sizeof(errbuf));
|
||||
|
||||
if (!node) {
|
||||
uwsgi_log("error parsing JSON data: %s\n", errbuf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char * path[] = { object_asked, NULL };
|
||||
yajl_val v = yajl_tree_get(node, path, yajl_t_any);
|
||||
if (!YAJL_IS_OBJECT(v)) {
|
||||
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for(i=0;i<v->u.object.len;i++) {
|
||||
char *key = (char *) v->u.object.keys[i];
|
||||
yajl_val o = v->u.object.values[i];
|
||||
if (YAJL_IS_STRING(o)) {
|
||||
add_exported_option(key, YAJL_GET_STRING(o) , 0);
|
||||
}
|
||||
else if (YAJL_IS_TRUE(o)) {
|
||||
add_exported_option(key, strdup("1"), 0);
|
||||
}
|
||||
else if (YAJL_IS_FALSE(o) || YAJL_IS_NULL(o)) {
|
||||
add_exported_option(key, strdup("0"), 0);
|
||||
}
|
||||
else if (YAJL_IS_NUMBER(o) || YAJL_IS_INTEGER(o)) {
|
||||
add_exported_option(key, YAJL_GET_NUMBER(o), 0);
|
||||
}
|
||||
else if (YAJL_IS_ARRAY(o)) {
|
||||
size_t j;
|
||||
for(j=0;j<o->u.array.len;j++) {
|
||||
yajl_val a_o = o->u.array.values[j];
|
||||
if (YAJL_IS_STRING(a_o)) {
|
||||
add_exported_option(key, YAJL_GET_STRING(a_o) , 0);
|
||||
}
|
||||
else if (YAJL_IS_TRUE(a_o)) {
|
||||
add_exported_option(key, strdup("1"), 0);
|
||||
}
|
||||
else if (YAJL_IS_FALSE(a_o) || YAJL_IS_NULL(a_o)) {
|
||||
add_exported_option(key, strdup("0"), 0);
|
||||
}
|
||||
else if (YAJL_IS_NUMBER(a_o) || YAJL_IS_INTEGER(a_o)) {
|
||||
add_exported_option(key, YAJL_GET_NUMBER(a_o), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
|
||||
/*
|
||||
I really love the jansson library...
|
||||
*/
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
|
||||
size_t len = 0;
|
||||
@@ -111,3 +305,4 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+61
-11
@@ -279,9 +279,12 @@ static void legions_check_nodes_step2() {
|
||||
// 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;
|
||||
// but only if i am not suspended...
|
||||
if (uwsgi_now() > ul->suspended_til) {
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
@@ -337,13 +340,20 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
if (i_am_the_best) {
|
||||
if (!ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
|
||||
// triggering lord hooks
|
||||
uwsgi_log("[uwsgi-legion] attempting to become the Lord of the Legion %s\n", ul->legion);
|
||||
struct uwsgi_string_list *usl = ul->lord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("lord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, lord hook returned: %d\n", ret);
|
||||
if (uwsgi.legion_death_on_lord_error) {
|
||||
ul->dead = 1;
|
||||
uwsgi_legion_announce(ul);
|
||||
ul->suspended_til = uwsgi_now() + uwsgi.legion_death_on_lord_error;
|
||||
uwsgi_log("[uwsgi-legion] suspending myself from Legion \"%s\" for %d seconds\n", ul->legion, uwsgi.legion_death_on_lord_error);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -356,6 +366,7 @@ static void legions_check_nodes_step2() {
|
||||
else {
|
||||
ul->lord_scroll_len = 0;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
|
||||
ul->i_am_the_lord = uwsgi_now();
|
||||
// trick: reduce the time needed by the old lord to unlord itself
|
||||
uwsgi_legion_announce(ul);
|
||||
@@ -400,7 +411,7 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
}
|
||||
@@ -496,8 +507,15 @@ static void *legion_loop(void *foobar) {
|
||||
last_round = now;
|
||||
// wait for event
|
||||
int interesting_fd = -1;
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
|
||||
int rlen = event_queue_wait(uwsgi.legion_queue, timeout, &interesting_fd);
|
||||
|
||||
if (rlen < 0 && errno != EINTR) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) return NULL;
|
||||
uwsgi_nuclear_blast();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
now = uwsgi_now();
|
||||
if (timeout == 0 || rlen == 0 || (now - last_round) >= timeout) {
|
||||
struct uwsgi_legion *legions = uwsgi.legions;
|
||||
@@ -591,6 +609,8 @@ static void *legion_loop(void *foobar) {
|
||||
// check if the node is already accounted
|
||||
struct uwsgi_legion_node *node = uwsgi_legion_get_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
if (!node) {
|
||||
// if a lord hook election fails, a node can announce itself as dead for long time...
|
||||
if (legion_msg.dead) continue;
|
||||
// add the new node
|
||||
uwsgi_wlock(ul->lock);
|
||||
node = uwsgi_legion_add_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
@@ -648,7 +668,12 @@ int uwsgi_legion_action_call(char *phase, struct uwsgi_legion *ul, struct uwsgi_
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
|
||||
if (ula->log_msg) {
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) %s\n", phase, ul->legion, ula->log_msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] (phase: %s legion: %s) calling %s\n", phase, ul->legion, usl->value);
|
||||
}
|
||||
return ula->func(ul, usl->value + usl->custom);
|
||||
}
|
||||
|
||||
@@ -667,6 +692,18 @@ static int legion_action_log(struct uwsgi_legion *ul, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int legion_action_alarm(struct uwsgi_legion *ul, char *arg) {
|
||||
char *space = strchr(arg,' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid alarm action syntax, must be: <alarm> <msg>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_alarm_trigger(arg, space+1, strlen(space+1));
|
||||
*space = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_start_legions() {
|
||||
pthread_t legion_loop_t;
|
||||
|
||||
@@ -675,8 +712,10 @@ void uwsgi_start_legions() {
|
||||
|
||||
// register embedded actions
|
||||
uwsgi_legion_action_register("cmd", legion_action_cmd);
|
||||
uwsgi_legion_action_register("exec", legion_action_cmd);
|
||||
uwsgi_legion_action_register("signal", legion_action_signal);
|
||||
uwsgi_legion_action_register("log", legion_action_log);
|
||||
uwsgi_legion_action_register("alarm", legion_action_alarm);
|
||||
|
||||
uwsgi.legion_queue = event_queue_init();
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
@@ -736,13 +775,19 @@ void uwsgi_legion_add(struct uwsgi_legion *ul) {
|
||||
}
|
||||
|
||||
int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
if (now <= ul->suspended_til) return 0;
|
||||
ul->suspended_til = 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
unsigned char *encrypted = NULL;
|
||||
|
||||
if (uwsgi_buffer_append_keyval(ub, "legion", 6, ul->legion, ul->legion_len))
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "valor", 5, ul->valor))
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now()))
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, now))
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keynum(ub, "lord", 4, ul->i_am_the_lord ? ul->i_am_the_lord : 0))
|
||||
goto err;
|
||||
@@ -769,7 +814,7 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
|
||||
uwsgi_error("[uwsgi-legion] EVP_EncryptInit_ex()");
|
||||
goto err;
|
||||
@@ -808,6 +853,7 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
return 0;
|
||||
err:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
free(encrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -824,6 +870,7 @@ void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
free(legion);
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
@@ -1112,10 +1159,11 @@ struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
|
||||
if (uwsgi_legion_action_get(name)) {
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *, char *)) {
|
||||
struct uwsgi_legion_action *found_ula = uwsgi_legion_action_get(name);
|
||||
if (found_ula) {
|
||||
uwsgi_log("[uwsgi-legion] action \"%s\" is already registered !!!\n", name);
|
||||
return;
|
||||
return found_ula;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *old_ula = NULL, *ula = uwsgi.legion_actions;
|
||||
@@ -1134,6 +1182,8 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
|
||||
else {
|
||||
uwsgi.legion_actions = ula;
|
||||
}
|
||||
|
||||
return ula;
|
||||
}
|
||||
|
||||
void uwsgi_legion_announce_death(void) {
|
||||
|
||||
+150
-104
@@ -119,6 +119,36 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
commodity function mainly useful in log rotation
|
||||
*/
|
||||
void uwsgi_logfile_write(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char logpkt[4096];
|
||||
|
||||
struct timeval tv;
|
||||
char ctime_storage[26];
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
|
||||
#endif
|
||||
memcpy(logpkt, ctime_storage, 24);
|
||||
memcpy(logpkt + 24, " - ", 3);
|
||||
|
||||
int rlen = 24 + 3;
|
||||
|
||||
va_start(ap, fmt);
|
||||
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
// do not check for errors
|
||||
rlen = write(uwsgi.original_log_fd, logpkt, rlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fix_logpipe_buf(int *fd) {
|
||||
int so_bufsize;
|
||||
@@ -271,19 +301,27 @@ void logto(char *logfile) {
|
||||
}
|
||||
|
||||
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
// if the log-master is already active, just re-set the original_log_fd
|
||||
if (uwsgi.shared->worker_log_pipe[0] == -1) {
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
uwsgi.original_log_fd = 2;
|
||||
}
|
||||
else {
|
||||
uwsgi.original_log_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,51 +354,51 @@ void uwsgi_setup_log() {
|
||||
|
||||
static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
char *name = usl->value;
|
||||
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_master(void) {
|
||||
@@ -447,13 +485,19 @@ void uwsgi_check_logrotate(void) {
|
||||
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
off_t logsize;
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
if (logsize < 0) {
|
||||
uwsgi_error("uwsgi_check_logrotate()/lseek()");
|
||||
return;
|
||||
}
|
||||
uwsgi.shared->logsize = logsize;
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
@@ -475,51 +519,53 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int log_fd) {
|
||||
int need_free = 0;
|
||||
char *rot_name = rotatedfile;
|
||||
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) logsize, rot_name);
|
||||
if (rename(logfile, rot_name) == 0) {
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(logfile);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, log_fd) < 0) {
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_do_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
if (!uwsgi.logfile)
|
||||
return;
|
||||
uwsgi_log_do_rotate(uwsgi.logfile, uwsgi.log_backupname, uwsgi.shared->logsize, uwsgi.original_log_fd);
|
||||
}
|
||||
|
||||
void uwsgi_log_reopen() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (ret > 0 && ret < 1024) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
@@ -535,7 +581,7 @@ void uwsgi_log_reopen() {
|
||||
return;
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (ret > 0 && ret < 1024) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
@@ -547,7 +593,7 @@ void uwsgi_log_reopen() {
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int log_it = uwsgi.shared->options[UWSGI_OPTION_LOGGING];
|
||||
int log_it = uwsgi.logging_options.enabled;
|
||||
|
||||
if (wsgi_req->do_not_log)
|
||||
return;
|
||||
@@ -557,25 +603,25 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
/* conditional logging */
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_ZERO] && wsgi_req->response_size == 0) {
|
||||
if (uwsgi.logging_options.zero && wsgi_req->response_size == 0) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW] && (uint32_t) wsgi_req_time >= uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW]) {
|
||||
if (uwsgi.logging_options.slow && (uint32_t) wsgi_req_time >= uwsgi.logging_options.slow) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_4xx] && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
|
||||
if (uwsgi.logging_options._4xx && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_5xx] && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
|
||||
if (uwsgi.logging_options._5xx && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG] && (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG])) {
|
||||
if (uwsgi.logging_options.big && (wsgi_req->response_size >= uwsgi.logging_options.big)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
if (uwsgi.logging_options.sendfile && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_IOERROR] && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
|
||||
if (uwsgi.logging_options.ioerror && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
|
||||
goto logit;
|
||||
}
|
||||
|
||||
@@ -660,7 +706,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
logvecpos++;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
if (uwsgi.logging_options.memory_report == 1) {
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
@@ -891,7 +937,7 @@ struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
|
||||
while (ul) {
|
||||
if (!strcmp(ul->id, id)) {
|
||||
if (ul->id && !strcmp(ul->id, id)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
@@ -1090,7 +1136,7 @@ static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
if (!uwsgi.log_strftime) {
|
||||
if (!uwsgi.logformat_strftime || !uwsgi.log_strftime) {
|
||||
return uwsgi_lf_ltime(wsgi_req, buf);
|
||||
}
|
||||
*buf = uwsgi_malloc(64);
|
||||
@@ -1813,7 +1859,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
size_t msg_len = len;
|
||||
if (msg[len-1] == '\n') msg_len--;
|
||||
char *e_json = uwsgi_malloc(msg_len * 2);
|
||||
char *e_json = uwsgi_malloc((msg_len * 2)+1);
|
||||
escape_json(msg, msg_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1822,7 +1868,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
char *e_json = uwsgi_malloc(len * 2);
|
||||
char *e_json = uwsgi_malloc((len * 2)+1);
|
||||
escape_json(msg, len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1843,7 +1889,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
char *e_json = uwsgi_malloc(strftime_len * 2);
|
||||
char *e_json = uwsgi_malloc((strftime_len * 2)+1);
|
||||
escape_json(sftime, strftime_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
|
||||
+179
-73
@@ -7,6 +7,7 @@ void uwsgi_update_load_counters() {
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
static time_t last_sos = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
@@ -21,6 +22,15 @@ void uwsgi_update_load_counters() {
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
|
||||
if (uwsgi.vassal_sos) {
|
||||
if (uwsgi.current_time - last_sos > uwsgi.vassal_sos) {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (overload: %llu)...\n", (unsigned long long) ushared->overloaded);
|
||||
vassal_sos();
|
||||
last_sos = uwsgi.current_time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
@@ -135,6 +145,15 @@ void uwsgi_master_check_mercy() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0 && uwsgi.mules[i].cursed_at) {
|
||||
if (uwsgi_now() > uwsgi.mules[i].no_mercy_at) {
|
||||
uwsgi_log_verbose("mule %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i + 1, uwsgi.mules[i].pid);
|
||||
uwsgi_curse_mule(i, SIGKILL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,53 +187,34 @@ void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_get_tcp_info(int fd) {
|
||||
static void get_tcp_info(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
int fd = uwsgi_sock->fd;
|
||||
struct tcp_info ti;
|
||||
socklen_t tis = sizeof(struct tcp_info);
|
||||
|
||||
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &uwsgi.shared->ti, &tis)) {
|
||||
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &ti, &tis)) {
|
||||
|
||||
// checks for older kernels
|
||||
#if defined(__linux__)
|
||||
if (!uwsgi.shared->ti.tcpi_sacked) {
|
||||
if (!ti.tcpi_sacked) {
|
||||
#elif defined(__FreeBSD__)
|
||||
if (!uwsgi.shared->ti.__tcpi_sacked) {
|
||||
if (!ti.__tcpi_sacked) {
|
||||
#endif
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
|
||||
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.tcpi_sacked;
|
||||
uwsgi_sock->queue = (uint64_t) ti.tcpi_unacked;
|
||||
uwsgi_sock->max_queue = (uint64_t) ti.tcpi_sacked;
|
||||
#elif defined(__FreeBSD__)
|
||||
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.__tcpi_unacked;
|
||||
uwsgi.shared->max_load = (uint64_t) uwsgi.shared->ti.__tcpi_sacked;
|
||||
uwsgi_sock->queue = (uint64_t) ti.__tcpi_unacked;
|
||||
uwsgi_sock->max_queue = (uint64_t) ti.__tcpi_sacked;
|
||||
#endif
|
||||
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->load;
|
||||
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
|
||||
if (uwsgi.shared->load >= (uint64_t) uwsgi.vassal_sos_backlog) {
|
||||
// ask emperor for help
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
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.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
|
||||
return uwsgi.shared->load;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -227,25 +227,78 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
|
||||
#ifdef SIOBKLGQ
|
||||
|
||||
int get_linux_unbit_SIOBKLGQ(int fd) {
|
||||
static void get_linux_unbit_SIOBKLGQ(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
int fd = uwsgi_sock->fd;
|
||||
int queue = 0;
|
||||
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
|
||||
uwsgi.shared->load = queue;
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = queue;
|
||||
if (queue >= uwsgi.listen_queue) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
return queue;
|
||||
uwsgi_sock->queue = (uint64_t) queue;
|
||||
uwsgi_sock->max_queue = (uint64_t) uwsgi.listen_queue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void master_check_listen_queue() {
|
||||
|
||||
uint64_t backlog = 0;
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
get_tcp_info(uwsgi_sock);
|
||||
}
|
||||
#ifdef __linux__
|
||||
#ifdef SIOBKLGQ
|
||||
else if (uwsgi_sock->family == AF_UNIX) {
|
||||
get_linux_unbit_SIOBKLGQ(uwsgi_sock);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi_sock->queue > backlog) {
|
||||
backlog = uwsgi_sock->queue;
|
||||
}
|
||||
if (uwsgi_sock->queue > 0 && uwsgi_sock->queue >= uwsgi_sock->max_queue) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu) ***\n", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
|
||||
}
|
||||
|
||||
if (uwsgi.alarm_backlog) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "listen queue of socket \"%s\" (fd: %d) full !!! (%llu/%llu)", uwsgi_sock->name, uwsgi_sock->fd, (unsigned long long) uwsgi_sock->queue, (unsigned long long) uwsgi_sock->max_queue);
|
||||
if (ret > 0 && ret < 1024) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.alarm_backlog) {
|
||||
uwsgi_alarm_trigger(usl->value, buf, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
// TODO load should be something more advanced based on different values
|
||||
uwsgi.shared->load = backlog;
|
||||
|
||||
uwsgi.shared->backlog = backlog;
|
||||
|
||||
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
|
||||
if (uwsgi.shared->backlog >= (uint64_t) uwsgi.vassal_sos_backlog) {
|
||||
// ask emperor for help
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
vassal_sos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vassal_sos() {
|
||||
if (!uwsgi.has_emperor) {
|
||||
uwsgi_log("[broodlord] instance not governed by an Emperor !!!\n");
|
||||
return;
|
||||
}
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("vassal_sos()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
int master_loop(char **argv, char **environ) {
|
||||
|
||||
@@ -306,6 +359,12 @@ int master_loop(char **argv, char **environ) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.notify_socket) {
|
||||
uwsgi.notify_socket_fd = bind_to_unix_dgram(uwsgi.notify_socket);
|
||||
uwsgi_log("notification socket enabled on %s (fd: %d)\n", uwsgi.notify_socket, uwsgi.notify_socket_fd);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.notify_socket_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
@@ -358,6 +417,18 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi.setns_socket) {
|
||||
uwsgi.setns_socket_fd = bind_to_unix(uwsgi.setns_socket, uwsgi.listen_queue, 0, 0);
|
||||
if (uwsgi.setns_socket_fd < 0) exit(1);
|
||||
if (chmod(uwsgi.setns_socket, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("[setns-socket] chmod()");
|
||||
exit(1);
|
||||
}
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.setns_socket_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
|
||||
@@ -471,6 +542,24 @@ int master_loop(char **argv, char **environ) {
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
// daemon touches
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->touch) {
|
||||
uwsgi_check_touches(ud->touch);
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
// hook touches
|
||||
uwsgi_foreach(usl, uwsgi.hook_touch) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **)&usl->custom_ptr, space+1);
|
||||
}
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.hook_touch);
|
||||
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
@@ -518,6 +607,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// here really starts the master loop
|
||||
uwsgi_hooks_run(uwsgi.hook_master_start, "master-start", 1);
|
||||
|
||||
for (;;) {
|
||||
//uwsgi_log("uwsgi.ready_to_reload %d %d\n", uwsgi.ready_to_reload, uwsgi.numproc);
|
||||
@@ -578,10 +668,10 @@ int master_loop(char **argv, char **environ) {
|
||||
if (diedpid == 0) {
|
||||
|
||||
/* all processes ok, doing status scan after N seconds */
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
check_interval = uwsgi.master_interval;
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
uwsgi.master_interval = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -680,43 +770,25 @@ int master_loop(char **argv, char **environ) {
|
||||
// check for idle
|
||||
uwsgi_master_check_idle();
|
||||
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
check_interval = uwsgi.master_interval;
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
uwsgi.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);
|
||||
}
|
||||
#ifdef __linux__
|
||||
#ifdef SIOBKLGQ
|
||||
else if (uwsgi_sock->family == AF_UNIX) {
|
||||
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
|
||||
}
|
||||
#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 listen_queue status
|
||||
master_check_listen_queue();
|
||||
|
||||
int someone_killed = 0;
|
||||
// check if some worker has to die (harakiri, evil checks...)
|
||||
uwsgi_master_check_workers_deadline();
|
||||
if (uwsgi_master_check_workers_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_gateways_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_mules_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_spoolers_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_crons_deadline()) someone_killed++;
|
||||
|
||||
uwsgi_master_check_gateways_deadline();
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
uwsgi_master_check_crons_deadline();
|
||||
// this could trigger a complete exit...
|
||||
uwsgi_master_check_mountpoints();
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -780,8 +852,32 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
|
||||
// daemon touches
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && ud->touch) {
|
||||
touched = uwsgi_check_touches(ud->touch);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
|
||||
if (kill(-ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
|
||||
// hook touches
|
||||
touched = uwsgi_check_touches(uwsgi.hook_touch);
|
||||
if (touched) {
|
||||
uwsgi_hooks_run((struct uwsgi_string_list *) touched, "touch", 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// allows the KILL signal to be delivered;
|
||||
if (someone_killed > 0) sleep(1);
|
||||
continue;
|
||||
|
||||
}
|
||||
@@ -836,6 +932,7 @@ int master_loop(char **argv, char **environ) {
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("mule %d (pid: %d) annihilated\n", i + 1, (int) diedpid);
|
||||
uwsgi.mules[i].pid = 0;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
@@ -883,6 +980,11 @@ next:
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
if (uwsgi.lazy_apps && uwsgi.need_app) {
|
||||
uwsgi_log_verbose("need-app requested, destroying the instance...\n");
|
||||
kill_them_all(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
@@ -898,6 +1000,10 @@ next:
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_GO_CHEAP_CODE) {
|
||||
uwsgi_log("worker %d asked for cheap mode (pid: %d)...\n", thewid, (int) diedpid);
|
||||
uwsgi.workers[thewid].cheaped = 1;
|
||||
}
|
||||
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));
|
||||
|
||||
+71
-27
@@ -25,6 +25,11 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
@@ -35,26 +40,44 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
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");
|
||||
}
|
||||
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;
|
||||
|
||||
// we need to ensure the previous worker (if alive) is accepting new requests
|
||||
// before going on
|
||||
if (uwsgi.status.chain_reloading > 1) {
|
||||
struct uwsgi_worker *previous_worker = &uwsgi.workers[uwsgi.status.chain_reloading-1];
|
||||
// is the previous worker alive ?
|
||||
if (previous_worker->pid > 0 && !previous_worker->cheaped) {
|
||||
// the worker has been respawned but it is still not ready
|
||||
if (previous_worker->accepting == 0) {
|
||||
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if all the processes are recycled, the chain is over
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
int i;
|
||||
for(i=uwsgi.status.chain_reloading;i<=uwsgi.numproc;i++) {
|
||||
struct uwsgi_worker *uw = &uwsgi.workers[i];
|
||||
if (uw->pid > 0 && !uw->cheaped && uw->accepting) {
|
||||
// the worker could have been already cursed
|
||||
if (uw->cursed_at == 0) {
|
||||
uwsgi_log_verbose("chain next victim is worker %d\n", i);
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
@@ -122,6 +145,8 @@ void uwsgi_master_check_idle() {
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
@@ -131,19 +156,22 @@ void uwsgi_master_check_idle() {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_check_workers_deadline() {
|
||||
int uwsgi_master_check_workers_deadline() {
|
||||
int i;
|
||||
int ret = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
/* first check for harakiri */
|
||||
if (uwsgi.workers[i].harakiri > 0) {
|
||||
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
|
||||
trigger_harakiri(i);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
/* then user-defined harakiri */
|
||||
if (uwsgi.workers[i].user_harakiri > 0) {
|
||||
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
trigger_harakiri(i);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
// then for evil memory checkers
|
||||
@@ -152,6 +180,7 @@ void uwsgi_master_check_workers_deadline() {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.evil_reload_on_rss) {
|
||||
@@ -159,15 +188,17 @@ void uwsgi_master_check_workers_deadline() {
|
||||
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
// check if worker was running longer than allowed lifetime
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.max_worker_lifetime > 0) {
|
||||
uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn;
|
||||
if (lifetime > uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] && uwsgi.workers[i].manage_next_request == 1) {
|
||||
if (lifetime > uwsgi.max_worker_lifetime && uwsgi.workers[i].manage_next_request == 1) {
|
||||
uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime);
|
||||
uwsgi.workers[i].manage_next_request = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGWINCH);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,29 +207,32 @@ void uwsgi_master_check_workers_deadline() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_check_gateways_deadline() {
|
||||
int uwsgi_master_check_gateways_deadline() {
|
||||
|
||||
int i;
|
||||
|
||||
int ret = 0;
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways_harakiri[i] > 0) {
|
||||
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
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);
|
||||
ret = 1;
|
||||
}
|
||||
ushared->gateways_harakiri[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mules_deadline() {
|
||||
int uwsgi_master_check_mules_deadline() {
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].harakiri > 0) {
|
||||
@@ -206,6 +240,7 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
// user harakiri
|
||||
@@ -214,26 +249,32 @@ void uwsgi_master_check_mules_deadline() {
|
||||
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;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_spoolers_deadline() {
|
||||
int uwsgi_master_check_spoolers_deadline() {
|
||||
int ret = 0;
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
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;
|
||||
ret = 1;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -316,15 +357,18 @@ int uwsgi_master_check_cron_death(int diedpid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_crons_deadline() {
|
||||
int uwsgi_master_check_crons_deadline() {
|
||||
int ret = 0;
|
||||
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);
|
||||
ret = 1;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mountpoints() {
|
||||
|
||||
@@ -22,6 +22,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.notify_socket_fd > -1 && interesting_fd == uwsgi.notify_socket_fd) {
|
||||
return uwsgi_notify_socket_manage(interesting_fd);
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
@@ -51,6 +55,12 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi.setns_socket && uwsgi.setns_socket_fd > -1 && interesting_fd == uwsgi.setns_socket_fd) {
|
||||
uwsgi_master_manage_setns(uwsgi.setns_socket_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi_fsmon_event(interesting_fd)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+233
-33
@@ -24,6 +24,15 @@ void uwsgi_curse(int wid, int sig) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_curse_mule(int mid, int sig) {
|
||||
uwsgi.mules[mid].cursed_at = uwsgi_now();
|
||||
uwsgi.mules[mid].no_mercy_at = uwsgi.mules[mid].cursed_at + uwsgi.mule_reload_mercy;
|
||||
|
||||
if (sig) {
|
||||
(void) kill(uwsgi.mules[mid].pid, sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_signal_spoolers(int signum) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
@@ -43,13 +52,6 @@ void uwsgi_destroy_processes() {
|
||||
|
||||
uwsgi_signal_spoolers(SIGKILL);
|
||||
|
||||
if (uwsgi.emperor_pid >= 0) {
|
||||
kill(uwsgi.emperor_pid, SIGKILL);
|
||||
waitpid(uwsgi.emperor_pid, &waitpid_status, 0);
|
||||
uwsgi_log("The Emperor has been buried (pid: %d)\n", (int) uwsgi.emperor_pid);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_detach_daemons();
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
@@ -60,14 +62,25 @@ void uwsgi_destroy_processes() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO mules can be programmed to be gracefully reloaded
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
waitpid(uwsgi.mules[i].pid, &waitpid_status, 0);
|
||||
uwsgi_log("mule %d has been buried (pid: %d)\n", i, (int) uwsgi.mules[i].pid);
|
||||
if (uwsgi.emperor_pid > 0) {
|
||||
kill(uwsgi.emperor_pid, SIGINT);
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
// increase timeout for being more tolerant
|
||||
timeout+=2;
|
||||
int waitpid_status;
|
||||
while (uwsgi_now() < timeout) {
|
||||
pid_t diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
|
||||
if (diedpid == uwsgi.emperor_pid) {
|
||||
goto nomoremperor;
|
||||
}
|
||||
uwsgi_log("waiting for Emperor death...\n");
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
kill(uwsgi.emperor_pid, SIGKILL);
|
||||
waitpid(uwsgi.emperor_pid, &waitpid_status, 0);
|
||||
nomoremperor:
|
||||
uwsgi_log("The Emperor has been buried (pid: %d)\n", (int) uwsgi.emperor_pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +114,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
static time_t last_check = 0;
|
||||
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
int check_interval = uwsgi.master_interval;
|
||||
|
||||
if (!last_check)
|
||||
last_check = uwsgi_now();
|
||||
@@ -186,6 +199,8 @@ int uwsgi_calc_cheaper(void) {
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].rss_size = 0;
|
||||
uwsgi.workers[oldest_worker].vsz_size = 0;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
uwsgi_curse(oldest_worker, SIGWINCH);
|
||||
}
|
||||
@@ -330,7 +345,7 @@ int uwsgi_cheaper_algo_backlog(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.shared->backlog;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
@@ -383,28 +398,37 @@ void uwsgi_reload(char **argv) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("fork()'ing uWSGI...\n");
|
||||
}
|
||||
|
||||
// ask for configuration (if needed)
|
||||
if (uwsgi.has_emperor && uwsgi.emperor_fd_config > -1) {
|
||||
char byte = 2;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("uwsgi_reload()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
uwsgi_error("uwsgi_reload()/chdir()");
|
||||
}
|
||||
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
if (uwsgi.close_on_exec2) fcntl(i, F_SETFD, 0);
|
||||
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
|
||||
@@ -543,9 +567,10 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
@@ -584,6 +609,21 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
|
||||
if (uwsgi.notify_socket_fd > -1) close(uwsgi.notify_socket_fd);
|
||||
|
||||
#ifdef __linux__
|
||||
for(i=0;i<uwsgi.setns_fds_count;i++) {
|
||||
close(uwsgi.setns_fds[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// fd alarms
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
close(uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -713,9 +753,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]))
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->backlog))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]))
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->backlog_errors))
|
||||
goto end;
|
||||
#endif
|
||||
|
||||
@@ -756,7 +796,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ud->command)*2)+1);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
@@ -873,7 +913,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi.has_metrics && !uwsgi.stats_no_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
@@ -957,6 +997,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "max_queue", (unsigned long long) uwsgi_sock->max_queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
|
||||
goto end;
|
||||
|
||||
@@ -1080,7 +1123,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
|
||||
goto end;
|
||||
|
||||
if (ua->chdir) {
|
||||
if (*ua->chdir) {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
|
||||
goto end;
|
||||
}
|
||||
@@ -1102,6 +1145,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.stats_no_cores) goto nocores;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
@@ -1163,9 +1208,12 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
nocores:
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
|
||||
if (i < uwsgi.numproc - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
@@ -1241,7 +1289,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ucron->command)*2)+1);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
@@ -1453,7 +1501,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
|
||||
|
||||
void trigger_harakiri(int i) {
|
||||
int j;
|
||||
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
|
||||
uwsgi_log_verbose("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
|
||||
if (uwsgi.harakiri_verbose) {
|
||||
#ifdef __linux__
|
||||
int proc_file;
|
||||
@@ -1501,15 +1549,12 @@ void trigger_harakiri(int i) {
|
||||
}
|
||||
}
|
||||
|
||||
kill(uwsgi.workers[i].pid, SIGUSR2);
|
||||
// allow SIGUSR2 to be delivered
|
||||
sleep(1);
|
||||
uwsgi_dump_worker(i, "HARAKIRI");
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (!uwsgi.workers[i].pending_harakiri)
|
||||
uwsgi.workers[i].harakiri_count++;
|
||||
uwsgi.workers[i].pending_harakiri++;
|
||||
}
|
||||
// to avoid races
|
||||
|
||||
}
|
||||
|
||||
@@ -1649,6 +1694,8 @@ void uwsgi_go_cheap() {
|
||||
uwsgi.status.is_cheap = 1;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
@@ -1661,3 +1708,156 @@ void uwsgi_go_cheap() {
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
void uwsgi_setns_preopen() {
|
||||
struct dirent *de;
|
||||
DIR *ns = opendir("/proc/self/ns");
|
||||
if (!ns) {
|
||||
uwsgi_error("uwsgi_setns_preopen()/opendir()");
|
||||
exit(1);
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
if (!strcmp(de->d_name, usl->value)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
|
||||
uwsgi.setns_fds[uwsgi.setns_fds_count] = open(filename, O_RDONLY);
|
||||
if (uwsgi.setns_fds[uwsgi.setns_fds_count] < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
exit(1);
|
||||
}
|
||||
free(filename);
|
||||
uwsgi.setns_fds_count++;
|
||||
}
|
||||
closedir(ns);
|
||||
}
|
||||
void uwsgi_master_manage_setns(int fd) {
|
||||
|
||||
struct sockaddr_un snsun;
|
||||
socklen_t snsun_len = sizeof(struct sockaddr_un);
|
||||
|
||||
int setns_client = accept(fd, (struct sockaddr *) &snsun, &snsun_len);
|
||||
if (setns_client < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_setns()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
int tmp_fds[64];
|
||||
int *fds = tmp_fds;
|
||||
int num_fds = 0;
|
||||
|
||||
struct msghdr sn_msg;
|
||||
void *sn_msg_control;
|
||||
struct iovec sn_iov[2];
|
||||
struct cmsghdr *cmsg;
|
||||
DIR *ns = NULL;
|
||||
|
||||
if (uwsgi.setns_fds_count) {
|
||||
fds = uwsgi.setns_fds;
|
||||
num_fds = uwsgi.setns_fds_count;
|
||||
goto send;
|
||||
}
|
||||
|
||||
struct dirent *de;
|
||||
ns = opendir("/proc/self/ns");
|
||||
if (!ns) {
|
||||
close(setns_client);
|
||||
uwsgi_error("uwsgi_master_manage_setns()/opendir()");
|
||||
return;
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
if (!strcmp(de->d_name, usl->value)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
|
||||
fds[num_fds] = open(filename, O_RDONLY);
|
||||
if (fds[num_fds] < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
goto clear;
|
||||
}
|
||||
free(filename);
|
||||
num_fds++;
|
||||
}
|
||||
|
||||
send:
|
||||
|
||||
sn_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
|
||||
|
||||
sn_iov[0].iov_base = "uwsgi-setns";
|
||||
sn_iov[0].iov_len = 11;
|
||||
sn_iov[1].iov_base = &num_fds;
|
||||
sn_iov[1].iov_len = sizeof(int);
|
||||
|
||||
sn_msg.msg_name = NULL;
|
||||
sn_msg.msg_namelen = 0;
|
||||
|
||||
sn_msg.msg_iov = sn_iov;
|
||||
sn_msg.msg_iovlen = 2;
|
||||
|
||||
sn_msg.msg_flags = 0;
|
||||
sn_msg.msg_control = sn_msg_control;
|
||||
sn_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&sn_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
int *sn_fd_ptr = (int *) CMSG_DATA(cmsg);
|
||||
for(i=0;i<num_fds;i++) {
|
||||
sn_fd_ptr[i] = fds[i];
|
||||
}
|
||||
|
||||
if (sendmsg(setns_client, &sn_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_setns()/sendmsg()");
|
||||
}
|
||||
|
||||
free(sn_msg_control);
|
||||
|
||||
clear:
|
||||
close(setns_client);
|
||||
if (ns) {
|
||||
closedir(ns);
|
||||
for(i=0;i<num_fds;i++) {
|
||||
close(fds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
this is racey, but the worst thing would be printing garbage in the logs...
|
||||
*/
|
||||
void uwsgi_dump_worker(int wid, char *msg) {
|
||||
int i;
|
||||
uwsgi_log_verbose("%s !!! worker %d status !!!\n", msg, wid);
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
struct uwsgi_core *uc = &uwsgi.workers[wid].cores[i];
|
||||
struct wsgi_request *wsgi_req = &uc->req;
|
||||
if (uc->in_request) {
|
||||
uwsgi_log_verbose("%s [core %d] %.*s - %.*s %.*s since %llu\n", msg, i, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) (wsgi_req->start_of_request/(1000*1000)));
|
||||
}
|
||||
}
|
||||
uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
|
||||
}
|
||||
|
||||
+43
-10
@@ -321,6 +321,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
char *m_initial_value = NULL;
|
||||
char *m_children = NULL;
|
||||
char *m_alias = NULL;
|
||||
char *m_reset_after_push = NULL;
|
||||
|
||||
if (!strchr(arg, '=')) {
|
||||
m_name = uwsgi_str(arg);
|
||||
@@ -340,6 +341,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
"arg3n", &m_arg3n,
|
||||
"children", &m_children,
|
||||
"alias", &m_alias,
|
||||
"reset_after_push", &m_reset_after_push,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid metric keyval syntax: %s\n", arg);
|
||||
exit(1);
|
||||
@@ -381,6 +383,10 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
struct uwsgi_metric* um = uwsgi_register_metric(m_name, m_oid, type, collector, NULL, freq, NULL);
|
||||
um->initial_value = initial_value;
|
||||
|
||||
if (m_reset_after_push){
|
||||
um->reset_after_push = 1;
|
||||
}
|
||||
|
||||
if (m_children) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(m_children, ";", p, ctx) {
|
||||
@@ -427,6 +433,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
if (m_initial_value) free(m_initial_value);
|
||||
if (m_children) free(m_children);
|
||||
if (m_alias) free(m_alias);
|
||||
if (m_reset_after_push) free(m_reset_after_push);
|
||||
return um;
|
||||
}
|
||||
|
||||
@@ -465,7 +472,7 @@ static void *uwsgi_metrics_loop(void *arg) {
|
||||
if (uwsgi.metrics_dir && metric->map) {
|
||||
if (value != new_value) {
|
||||
int ret = snprintf(metric->map, uwsgi.page_size, "%lld\n", (long long) new_value);
|
||||
if (ret > 0) {
|
||||
if (ret > 0 && ret < uwsgi.page_size) {
|
||||
memset(metric->map+ret, 0, 4096-ret);
|
||||
}
|
||||
}
|
||||
@@ -613,7 +620,7 @@ struct uwsgi_metric *uwsgi_metric_find_by_asn(char *asn, size_t len) {
|
||||
}\
|
||||
if (!um) return -1;\
|
||||
if (um->collector || um->type == UWSGI_METRIC_ALIAS) return -1;\
|
||||
uwsgi_rlock(uwsgi.metrics_lock)
|
||||
uwsgi_wlock(uwsgi.metrics_lock)
|
||||
|
||||
int uwsgi_metric_set(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
@@ -694,11 +701,27 @@ int64_t uwsgi_metric_getn(char *name, size_t nlen, char *oid, size_t olen) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define uwsgi_metric_name(f, n) if (snprintf(buf, 4096, f, n) <= 1) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_name2(f, n, n2) if (snprintf(buf, 4096, f, n, n2) <= 1) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
int uwsgi_metric_set_max(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if (value > *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define uwsgi_metric_oid(f, n) if (snprintf(buf2, 4096, f, n) <= 1) { uwsgi_log("unable to register metric oid %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_oid2(f, n, n2) if (snprintf(buf2, 4096, f, n, n2) <= 1) { uwsgi_log("unable to register metric oid %s\n", f); exit(1);}
|
||||
int uwsgi_metric_set_min(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if ((value > um->initial_value || 0) && value < *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define uwsgi_metric_name(f, n) ret = snprintf(buf, 4096, f, n); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_name2(f, n, n2) ret = snprintf(buf, 4096, f, n, n2); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
|
||||
#define uwsgi_metric_oid(f, n) ret = snprintf(buf2, 4096, f, n); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric oid %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_oid2(f, n, n2) ret = snprintf(buf2, 4096, f, n, n2); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric oid %s\n", f); exit(1);}
|
||||
|
||||
void uwsgi_setup_metrics() {
|
||||
|
||||
@@ -732,6 +755,9 @@ void uwsgi_setup_metrics() {
|
||||
struct uwsgi_metric *total_tx = uwsgi_register_metric_do("core.total_tx", "5.100", UWSGI_METRIC_COUNTER, "sum", NULL, 0, NULL, 1);
|
||||
struct uwsgi_metric *total_rss = uwsgi_register_metric_do("core.total_rss", "5.101", UWSGI_METRIC_GAUGE, "sum", NULL, 0, NULL, 1);
|
||||
struct uwsgi_metric *total_vsz = uwsgi_register_metric_do("core.total_vsz", "5.102", UWSGI_METRIC_GAUGE, "sum", NULL, 0, NULL, 1);
|
||||
struct uwsgi_metric *total_avg_rt = uwsgi_register_metric_do("core.avg_response_time", "5.103", UWSGI_METRIC_GAUGE, "avg", NULL, 0, NULL, 1);
|
||||
|
||||
int ret;
|
||||
|
||||
// create the 'worker' namespace
|
||||
int i;
|
||||
@@ -750,19 +776,25 @@ void uwsgi_setup_metrics() {
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].respawn_count, 0, NULL);
|
||||
|
||||
uwsgi_metric_name("worker.%d.avg_response_time", i) ; uwsgi_metric_oid("3.%d.8", i);
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].avg_response_time, 0, NULL);
|
||||
struct uwsgi_metric *avg_rt = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].avg_response_time, 0, NULL);
|
||||
if (i > 0) uwsgi_metric_add_child(total_avg_rt, avg_rt);
|
||||
|
||||
uwsgi_metric_name("worker.%d.total_tx", i) ; uwsgi_metric_oid("3.%d.9", i);
|
||||
struct uwsgi_metric *tx = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].tx, 0, NULL);
|
||||
uwsgi_metric_add_child(total_tx, tx);
|
||||
if (i > 0) uwsgi_metric_add_child(total_tx, tx);
|
||||
|
||||
uwsgi_metric_name("worker.%d.rss_size", i) ; uwsgi_metric_oid("3.%d.11", i);
|
||||
struct uwsgi_metric *rss = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].rss_size, 0, NULL);
|
||||
uwsgi_metric_add_child(total_rss, rss);
|
||||
if (i > 0) uwsgi_metric_add_child(total_rss, rss);
|
||||
|
||||
uwsgi_metric_name("worker.%d.vsz_size", i) ; uwsgi_metric_oid("3.%d.12", i);
|
||||
struct uwsgi_metric *vsz = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].vsz_size, 0, NULL);
|
||||
uwsgi_metric_add_child(total_vsz, vsz);
|
||||
if (i > 0) uwsgi_metric_add_child(total_vsz, vsz);
|
||||
|
||||
// skip core metrics for worker 0
|
||||
if (i == 0) continue;
|
||||
|
||||
if (uwsgi.metrics_no_cores) continue;
|
||||
|
||||
int j;
|
||||
for(j=0;j<uwsgi.cores;j++) {
|
||||
@@ -794,6 +826,7 @@ void uwsgi_setup_metrics() {
|
||||
uwsgi_metric_append(total_tx);
|
||||
uwsgi_metric_append(total_rss);
|
||||
uwsgi_metric_append(total_vsz);
|
||||
uwsgi_metric_append(total_avg_rt);
|
||||
|
||||
// sockets
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
+11
-3
@@ -54,6 +54,9 @@ static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_NOSUID
|
||||
{"nosuid", MS_NOSUID},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
@@ -102,7 +105,7 @@ uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags, char *data) {
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
@@ -121,7 +124,7 @@ int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
return mount(what, where, fs, mountflags, data);
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
@@ -197,6 +200,7 @@ unmountable:
|
||||
}
|
||||
|
||||
int uwsgi_mount_hook(char *arg) {
|
||||
char *data = NULL;
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *fs = tmp_arg;
|
||||
char *what = strchr(fs, ' ');
|
||||
@@ -208,8 +212,12 @@ int uwsgi_mount_hook(char *arg) {
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
data = strchr(flags, ' ');
|
||||
if (data) {
|
||||
*data = 0; data++;
|
||||
}
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags)) {
|
||||
if (uwsgi_mount(fs, what, where, flags, data)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
|
||||
+9
-6
@@ -43,7 +43,7 @@ void uwsgi_mule(int id) {
|
||||
#endif
|
||||
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGHUP, end_me);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
@@ -329,11 +329,13 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count + farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
int ret = -1;
|
||||
retry:
|
||||
ret = poll(mulepoll, count + farms_count, timeout);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_mule_get_msg()/poll()");
|
||||
}
|
||||
else {
|
||||
else if (ret > 0 ) {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
@@ -353,7 +355,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -380,6 +382,7 @@ next:
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -75,3 +75,39 @@ void uwsgi_systemd_init(char *systemd_socket) {
|
||||
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_notify_socket_manage(int fd) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = read(fd, buf, 8192);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_notify_socket_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("[notify-socket] %.*s\n", rlen, buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_notify_msg(char *dst, char *msg, size_t len) {
|
||||
static int notify_fd = -1;
|
||||
if (notify_fd < 0) {
|
||||
notify_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (notify_fd < 0) {
|
||||
uwsgi_error("uwsgi_notify_msg()/socket()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
struct sockaddr_un un_addr;
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, dst, 102);
|
||||
if (sendto(notify_fd, msg, len, 0, (struct sockaddr *) &un_addr, sizeof(un_addr)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(uwsgi.offload_threads_events);
|
||||
|
||||
for (;;) {
|
||||
// TODO make timeout tunable
|
||||
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.offload_threads_events);
|
||||
for (i = 0; i < nevents; i++) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
@@ -456,6 +457,13 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
// write event (or just connected)
|
||||
case 1:
|
||||
if (fd == uor->fd) {
|
||||
// maybe we want only a connection...
|
||||
if (uor->ubuf->pos == 0) {
|
||||
uor->status = 2;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
|
||||
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
|
||||
return 0;
|
||||
}
|
||||
rlen = write(uor->fd, uor->ubuf->buf + uor->written, uor->ubuf->pos-uor->written);
|
||||
if (rlen > 0) {
|
||||
uor->written += rlen;
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t r
|
||||
char buf[4096];
|
||||
|
||||
int ret = snprintf(buf, 4096, "{ \"state\" : \"uploading\", \"received\" : %llu, \"size\" : %llu }\r\n", (unsigned long long) (wsgi_req->post_cl - remains), (unsigned long long) wsgi_req->post_cl);
|
||||
if (ret < 0) {
|
||||
if (ret <= 0 || ret >= 4096) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+27
-76
@@ -18,81 +18,6 @@ static size_t get_content_length(char *buf, uint16_t size) {
|
||||
}
|
||||
|
||||
|
||||
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
int fd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
char *udp_port;
|
||||
ssize_t ret;
|
||||
|
||||
struct uwsgi_header *uh;
|
||||
|
||||
udp_port = strchr(host, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
}
|
||||
else {
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, host, 102);
|
||||
|
||||
}
|
||||
|
||||
if (message) {
|
||||
uh = (struct uwsgi_header *) message;
|
||||
}
|
||||
else {
|
||||
uh = (struct uwsgi_header *) uwsgi_malloc(4);
|
||||
}
|
||||
|
||||
uh->modifier1 = modifier1;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(message_size);
|
||||
#else
|
||||
uh->pktsize = message_size;
|
||||
#endif
|
||||
uh->modifier2 = modifier2;
|
||||
|
||||
if (udp_port) {
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if ((char *) uh != message) {
|
||||
free(uh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
|
||||
|
||||
char *ptr = (char *) uh;
|
||||
@@ -412,6 +337,12 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_ORIGIN", 11)) {
|
||||
wsgi_req->http_origin = buf;
|
||||
wsgi_req->http_origin_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,7 +494,7 @@ static int uwsgi_proto_check_18(struct wsgi_request *wsgi_req, char *key, char *
|
||||
|
||||
|
||||
static int uwsgi_proto_check_20(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
if (uwsgi.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
|
||||
if (uwsgi.logging_options.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
|
||||
wsgi_req->remote_addr = buf;
|
||||
wsgi_req->remote_addr_len = len;
|
||||
return 0;
|
||||
@@ -589,9 +520,28 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
|
||||
wsgi_req->if_modified_since_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_KEY", 22)) {
|
||||
wsgi_req->http_sec_websocket_key = buf;
|
||||
wsgi_req->http_sec_websocket_key_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_27(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_PROTOCOL", 27)) {
|
||||
wsgi_req->http_sec_websocket_protocol = buf;
|
||||
wsgi_req->http_sec_websocket_protocol_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_proto_hooks_setup() {
|
||||
int i = 0;
|
||||
for(i=0;i<UWSGI_PROTO_MAX_CHECK;i++) {
|
||||
@@ -609,6 +559,7 @@ void uwsgi_proto_hooks_setup() {
|
||||
uwsgi.proto_hooks[18] = uwsgi_proto_check_18;
|
||||
uwsgi.proto_hooks[20] = uwsgi_proto_check_20;
|
||||
uwsgi.proto_hooks[22] = uwsgi_proto_check_22;
|
||||
uwsgi.proto_hooks[27] = uwsgi_proto_check_27;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-5
@@ -123,7 +123,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// allocate more memory if needed
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
|
||||
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
memmove(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
// still something to use ?
|
||||
@@ -476,8 +476,8 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
|
||||
char *ptr = wsgi_req->post_buffering_buf;
|
||||
|
||||
while (remains > 0) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
inc_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
|
||||
@@ -550,8 +550,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
while (post_remains > 0) {
|
||||
|
||||
// during post buffering we need to constantly reset the harakiri
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
inc_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
// we use the already available post buffering buffer to read chunks....
|
||||
|
||||
+108
-3
@@ -312,6 +312,7 @@ int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int uwsgi_apply_response_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (!uwsgi.response_routes) return 0;
|
||||
if (wsgi_req->response_routes_applied) return 0;
|
||||
|
||||
@@ -582,6 +583,39 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route)
|
||||
{
|
||||
|
||||
if (route->data_len < 3)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
uint16_t status_msg_len = 0;
|
||||
const char *status_msg = uwsgi_http_status_msg(route->data, &status_msg_len);
|
||||
|
||||
if (!status_msg)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
char *buf = uwsgi_concat3n(route->data, route->data_len, " ", 1, (char *) status_msg, status_msg_len);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, buf, route->data_len + 1 + status_msg_len))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, status_msg_len))
|
||||
goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) status_msg, status_msg_len);
|
||||
|
||||
end:
|
||||
free(buf);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return(struct uwsgi_route *ur, char *arg)
|
||||
{
|
||||
ur->func = uwsgi_router_return_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// simple math router
|
||||
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -705,7 +739,7 @@ static int uwsgi_router_flush(struct uwsgi_route *ur, char *arg) {
|
||||
static int transform_fixcl(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) ut->chunk->pos);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -942,6 +976,20 @@ static int uwsgi_router_clearheaders(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// disable headers
|
||||
static int uwsgi_router_disableheaders_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
wsgi_req->headers_sent = 1;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_disableheaders(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_disableheaders_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// signal route
|
||||
static int uwsgi_router_signal_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
@@ -1071,6 +1119,32 @@ static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setremoteaddr route
|
||||
static int uwsgi_router_setremoteaddr_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "REMOTE_ADDR", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->remote_addr = ptr;
|
||||
wsgi_req->remote_addr_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setremoteaddr(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setremoteaddr_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setdocroot route
|
||||
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -1144,6 +1218,26 @@ static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setmodifiers
|
||||
static int uwsgi_router_setmodifier1_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
wsgi_req->uh->modifier1 = ur->custom;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmodifier1(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmodifier1_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_setmodifier2_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
wsgi_req->uh->modifier2 = ur->custom;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmodifier2(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmodifier2_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setuser route
|
||||
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
@@ -1656,7 +1750,11 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
|
||||
ret = uwsgi_num2str(uwsgi.shared->load);
|
||||
ret = uwsgi_num2str(uwsgi.shared->backlog);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "rsize", 5)) {
|
||||
ret = uwsgi_64bit2str(wsgi_req->response_size);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
@@ -1669,7 +1767,7 @@ static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint
|
||||
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
|
||||
if (var_value) {
|
||||
size_t mime_type_len = 0;
|
||||
char *ret = uwsgi_get_mime_type(key, keylen, &mime_type_len);
|
||||
ret = uwsgi_get_mime_type(var_value, var_vallen, &mime_type_len);
|
||||
if (ret) *vallen = mime_type_len;
|
||||
}
|
||||
return ret;
|
||||
@@ -1726,6 +1824,8 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
uwsgi_register_router("last", uwsgi_router_continue);
|
||||
uwsgi_register_router("break", uwsgi_router_break);
|
||||
uwsgi_register_router("return", uwsgi_router_return);
|
||||
uwsgi_register_router("break-with-status", uwsgi_router_return);
|
||||
uwsgi_register_router("log", uwsgi_router_log);
|
||||
uwsgi_register_router("donotlog", uwsgi_router_donotlog);
|
||||
uwsgi_register_router("logvar", uwsgi_router_logvar);
|
||||
@@ -1736,6 +1836,7 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("remheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("clearheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("resetheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("disableheaders", uwsgi_router_disableheaders);
|
||||
uwsgi_register_router("signal", uwsgi_router_signal);
|
||||
uwsgi_register_router("send", uwsgi_router_send);
|
||||
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
|
||||
@@ -1747,12 +1848,16 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
|
||||
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
|
||||
uwsgi_register_router("seturi", uwsgi_router_seturi);
|
||||
uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr);
|
||||
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
|
||||
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
|
||||
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("setmodifier1", uwsgi_router_setmodifier1);
|
||||
uwsgi_register_router("setmodifier2", uwsgi_router_setmodifier2);
|
||||
|
||||
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
|
||||
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
|
||||
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
|
||||
|
||||
+11
-6
@@ -104,8 +104,12 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
if (!uwsgi.rpc_table) {
|
||||
uwsgi_log("local rpc subsystem is still not initialized !!!\n");
|
||||
return NULL;
|
||||
}
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
|
||||
if (*buffer)
|
||||
if (buffer)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
@@ -117,7 +121,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
return NULL;
|
||||
|
||||
// wait for connection;
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
@@ -156,14 +160,14 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
}
|
||||
|
||||
// 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])) {
|
||||
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.socket_timeout)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// ok time to wait for the response in non blocking way
|
||||
size_t rlen = buffer_size+4;
|
||||
uint8_t modifier2 = 0;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, &modifier2)) {
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.socket_timeout, NULL, &modifier2)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -181,7 +185,7 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
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])) {
|
||||
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.socket_timeout)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -189,12 +193,13 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
goto error;
|
||||
goto error2;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
error2:
|
||||
free(buffer);
|
||||
return NULL;
|
||||
|
||||
|
||||
+10
-1
@@ -20,9 +20,18 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t 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__) || defined(__GNU_kFreeBSD__)
|
||||
#elif defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#elif defined(__sun__)
|
||||
off_t off = pos;
|
||||
ssize_t wlen = sendfile(sockfd, filefd, &off, len);
|
||||
if (wlen < 0 && uwsgi_is_again()) {
|
||||
if (off - pos > 0) {
|
||||
return off-pos;
|
||||
}
|
||||
}
|
||||
return wlen;
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
|
||||
+63
-6
@@ -229,8 +229,11 @@ int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
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);
|
||||
while(timeout == 0 || waiting == 0 || (timeout > 0 && waiting > 0 && (waiting/1000) < timeout)) {
|
||||
if (uwsgi.wait_milliseconds_hook(freq)) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return -1;
|
||||
}
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
@@ -266,6 +269,27 @@ static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t offset) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (uwsgi.sharedareas[id]->area == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_sharedarea_init_fd()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = fd;
|
||||
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(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
@@ -301,24 +325,41 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
char *s_offset = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
"offset", &s_offset,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid sharedarea keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t len = 0;
|
||||
off_t offset = 0;
|
||||
int pages = 0;
|
||||
if (s_size) {
|
||||
len = uwsgi_n64(s_size);
|
||||
if (strlen(s_size) > 2 && s_size[0] == '0' && s_size[1] == 'x') {
|
||||
len = strtoul(s_size+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
len = uwsgi_n64(s_size);
|
||||
}
|
||||
pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) pages++;
|
||||
}
|
||||
|
||||
if (s_offset) {
|
||||
if (strlen(s_offset) > 2 && s_offset[0] == '0' && s_offset[1] == 'x') {
|
||||
offset = strtoul(s_offset+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
offset = uwsgi_n64(s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pages) {
|
||||
pages = atoi(s_pages);
|
||||
@@ -326,27 +367,43 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
|
||||
char *area = NULL;
|
||||
struct uwsgi_sharedarea *sa = NULL;
|
||||
|
||||
int fd = -1;
|
||||
if (s_file) {
|
||||
fd = open(s_file, O_RDWR|O_SYNC);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(s_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (s_fd) {
|
||||
fd = atoi(s_fd);
|
||||
}
|
||||
else if (s_ptr) {
|
||||
}
|
||||
|
||||
if (pages) {
|
||||
if (!area) {
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
if (fd > -1) {
|
||||
sa = uwsgi_sharedarea_init_fd(fd, len, offset);
|
||||
}
|
||||
else if (area) {
|
||||
sa = uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_ptr(area, len);
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you need to set a size for a sharedarea !!! [%s]\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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);
|
||||
if (s_offset) free(s_offset);
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
+19
-17
@@ -45,21 +45,21 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 1;
|
||||
uwsgi.workers[uwsgi.mywid].signum = sig;
|
||||
uwsgi.workers[uwsgi.mywid].signals++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signals++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.mules > 0) {
|
||||
set_mule_harakiri(uwsgi.harakiri_options.mules);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
@@ -269,20 +269,22 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = sig;
|
||||
|
||||
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
if (write(fd, (char *) &uh, 4) != 4) {
|
||||
uwsgi_error("uwsgi_remote_signal_send()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
// wait for connection
|
||||
if (uwsgi.wait_write_hook(fd, uwsgi.socket_timeout) <= 0) goto end;
|
||||
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
|
||||
if (uwsgi_write_true_nb(fd, (char *) &uh, 4, uwsgi.socket_timeout)) goto end;
|
||||
|
||||
if (uwsgi_read_whole_true_nb(fd, (char *) &uh, 4, uwsgi.socket_timeout)) goto end;
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
return uh.modifier2;
|
||||
|
||||
end:
|
||||
close(fd);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+100
-98
@@ -76,18 +76,66 @@ char *uwsgi_getsockname(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int create_server_socket(int domain, int type) {
|
||||
int serverfd = socket(domain, type, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.close_on_exec2 && fcntl(serverfd, F_SETFD, FD_CLOEXEC) < 0)
|
||||
uwsgi_error("fcntl()");
|
||||
|
||||
if (domain != AF_UNIX) {
|
||||
int reuse = 1;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
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
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
int bind_to_unix_dgram(char *socket_name) {
|
||||
|
||||
int serverfd;
|
||||
struct sockaddr_un *uws_addr;
|
||||
socklen_t len;
|
||||
|
||||
serverfd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_DGRAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
@@ -140,15 +188,11 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +200,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
if (socket_name[0] == '@') {
|
||||
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
|
||||
@@ -203,15 +229,6 @@ 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()");
|
||||
uwsgi_nuclear_blast();
|
||||
@@ -243,7 +260,6 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
struct sockaddr_in uws_addr;
|
||||
char *udp_port;
|
||||
int bcast = 1;
|
||||
int reuse = 1;
|
||||
|
||||
struct ip_mreq mc;
|
||||
|
||||
@@ -288,15 +304,8 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
}
|
||||
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
serverfd = create_server_socket(AF_INET, SOCK_DGRAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (multicast) {
|
||||
// if multicast is enabled remember to bind to INADDR_ANY
|
||||
@@ -649,7 +658,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#else
|
||||
struct sockaddr_in uws_addr;
|
||||
#endif
|
||||
int reuse = 1;
|
||||
int family = AF_INET;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||
|
||||
@@ -667,37 +675,9 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#endif
|
||||
|
||||
|
||||
serverfd = socket(family, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
serverfd = create_server_socket(family, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef IP_FREEBIND
|
||||
#define IP_FREEBIND 15
|
||||
@@ -750,7 +730,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
#ifdef __linux__
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.socket_timeout, sizeof(int))) {
|
||||
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
|
||||
}
|
||||
// OSX has no SO_ACCEPTFILTER !!!
|
||||
@@ -781,15 +761,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
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()");
|
||||
uwsgi_nuclear_blast();
|
||||
@@ -1762,13 +1733,6 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
int zero_used = 0;
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1789,6 +1753,24 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
if (!uwsgi.is_a_reload) {
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
if (uwsgi.chmod_socket) {
|
||||
if (uwsgi.chmod_socket_value) {
|
||||
if (chmod(uwsgi_sock->name, uwsgi.chmod_socket_value) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("chmod() fd0 socket to 666 for lazy and brave users\n");
|
||||
if (chmod(uwsgi_sock->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
|
||||
@@ -1823,6 +1805,13 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
stdin_done:
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1928,6 +1917,19 @@ found:
|
||||
return up;
|
||||
}
|
||||
|
||||
int uwsgi_socket_passcred(int fd) {
|
||||
#ifdef SO_PASSCRED
|
||||
int optval = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
|
||||
uwsgi_error("uwsgi_socket_passcred()/setsockopt()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_protocols_register() {
|
||||
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
|
||||
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
|
||||
|
||||
+114
-33
@@ -72,12 +72,12 @@ struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
|
||||
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name, size_t name_len) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
while (uspool) {
|
||||
if (!strcmp(uspool->dir, name)) {
|
||||
if (!uwsgi_strncmp(uspool->dir, strlen(uspool->dir), name, name_len)) {
|
||||
return uspool;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
@@ -167,47 +167,125 @@ void destroy_spool(char *dir, char *file) {
|
||||
|
||||
}
|
||||
|
||||
struct spooler_req {
|
||||
char *spooler;
|
||||
size_t spooler_len;
|
||||
char *priority;
|
||||
size_t priority_len;
|
||||
time_t at;
|
||||
};
|
||||
|
||||
int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {
|
||||
static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, uint16_t value_len, void *data) {
|
||||
struct spooler_req *sr = (struct spooler_req *) data;
|
||||
if (!uwsgi_strncmp(key, key_len, "spooler", 7)) {
|
||||
sr->spooler = value;
|
||||
sr->spooler_len = value_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(key, key_len, "priority", 8)) {
|
||||
sr->priority = value;
|
||||
sr->priority_len = value_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(key, key_len, "at", 2)) {
|
||||
// at can be a float...
|
||||
char *dot = memchr(value, '.', value_len);
|
||||
if (dot) {
|
||||
value_len = dot - value;
|
||||
}
|
||||
sr->at = uwsgi_str_num(value, value_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CHANGED in 2.0.7: wsgi_req is useless !
|
||||
*/
|
||||
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {
|
||||
|
||||
struct timeval tv;
|
||||
int fd;
|
||||
struct uwsgi_header uh;
|
||||
static uint64_t internal_counter = 0;
|
||||
int fd = -1;
|
||||
struct spooler_req sr;
|
||||
|
||||
if (len > 0xffff) {
|
||||
uwsgi_log("[uwsgi-spooler] args buffer is limited to 64k, use the 'body' for bigger values\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse the request buffer
|
||||
memset(&sr, 0, sizeof(struct spooler_req));
|
||||
uwsgi_hooked_parse(buf, len, spooler_req_parser_hook, &sr);
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (!uspool) {
|
||||
uspool = uwsgi.spoolers;
|
||||
uwsgi_log("[uwsgi-spooler] no spooler available\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if it is a number, get the spooler by id instead of by name
|
||||
if (sr.spooler && sr.spooler_len) {
|
||||
uspool = uwsgi_get_spooler_by_name(sr.spooler, sr.spooler_len);
|
||||
if (!uspool) {
|
||||
uwsgi_log("[uwsgi-spooler] unable to find spooler \"%.*s\"\n", sr.spooler_len, sr.spooler);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// this lock is for threads, the pid value in filename will avoid multiprocess races
|
||||
uwsgi_lock(uspool->lock);
|
||||
|
||||
// we increase it even if the request fails
|
||||
internal_counter++;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
if (priority) {
|
||||
if (snprintf(filename, 1024, "%s/%s", uspool->dir, priority) <= 0) {
|
||||
char *filename = NULL;
|
||||
size_t filename_len = 0;
|
||||
|
||||
if (sr.priority && sr.priority_len) {
|
||||
filename_len = strlen(uspool->dir) + sr.priority_len + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/%.*s", uspool->dir, (int) sr.priority_len, sr.priority);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
// no need to check for errors...
|
||||
(void) mkdir(filename, 0777);
|
||||
|
||||
if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, rand(),
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >=(int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter,
|
||||
rand(), (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// now lock the file, it will no be runnable, until the lock is not removed
|
||||
@@ -215,13 +293,15 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
// in such case the spooler will detect a zeroed file and will retry later
|
||||
if (uwsgi_fcntl_lock(fd)) {
|
||||
close(fd);
|
||||
free(filename);
|
||||
uwsgi_unlock(uspool->lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 17;
|
||||
uh.modifier2 = 0;
|
||||
uh.pktsize = (uint16_t) size;
|
||||
uh.pktsize = (uint16_t) len;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh.pktsize = uwsgi_swap16(uh.pktsize);
|
||||
#endif
|
||||
@@ -231,7 +311,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, size) != size) {
|
||||
if (write(fd, buf, len) != (ssize_t) len) {
|
||||
uwsgi_log("[spooler] unable to write args for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
@@ -243,28 +323,28 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
}
|
||||
}
|
||||
|
||||
if (at > 0) {
|
||||
if (sr.at > 0) {
|
||||
#ifdef __UCLIBC__
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = at;
|
||||
ts[0].tv_sec = sr.at;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = at;
|
||||
ts[1].tv_sec = sr.at;
|
||||
ts[1].tv_nsec = 0;
|
||||
if (futimens(fd, ts)) {
|
||||
uwsgi_error("futimens()");
|
||||
uwsgi_error("uwsgi_spooler_request()/futimens()");
|
||||
}
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = at;
|
||||
tv[0].tv_sec = sr.at;
|
||||
tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = at;
|
||||
tv[1].tv_sec = sr.at;
|
||||
tv[1].tv_usec = 0;
|
||||
#ifdef __sun__
|
||||
if (futimesat(fd, NULL, tv)) {
|
||||
#else
|
||||
if (futimes(fd, tv)) {
|
||||
#endif
|
||||
uwsgi_error("futimes()");
|
||||
uwsgi_error("uwsgi_spooler_request()/futimes()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -273,7 +353,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
close(fd);
|
||||
|
||||
if (!uwsgi.spooler_quiet)
|
||||
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
|
||||
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) len + body_len + 4, filename);
|
||||
|
||||
// and here waiting threads can continue
|
||||
uwsgi_unlock(uspool->lock);
|
||||
@@ -293,18 +373,19 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
|
||||
spoolers = spoolers->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return filename;
|
||||
|
||||
|
||||
clear:
|
||||
uwsgi_unlock(uspool->lock);
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("uwsgi_spool_request()/write()");
|
||||
if (unlink(filename)) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("uwsgi_spool_request()/unlink()");
|
||||
}
|
||||
free(filename);
|
||||
// unlock the file too
|
||||
close(fd);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -367,7 +448,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
spooler_readdir(uspool, NULL);
|
||||
}
|
||||
|
||||
int timeout = uwsgi.shared->spooler_frequency;
|
||||
int timeout = uwsgi.shared->spooler_frequency ? uwsgi.shared->spooler_frequency : uwsgi.spooler_frequency;
|
||||
if (wakeup > 0) {
|
||||
timeout = 0;
|
||||
}
|
||||
@@ -552,11 +633,11 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler) {
|
||||
time_t now = uwsgi_now();
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
|
||||
}
|
||||
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
if (ret == 0)
|
||||
|
||||
+147
-17
@@ -95,15 +95,38 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (!servername) return SSL_TLSEXT_ERR_NOACK;
|
||||
size_t servername_len = strlen(servername);
|
||||
// reduce DOS attempts
|
||||
int count = 5;
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.sni;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
|
||||
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
while(count > 0) {
|
||||
struct uwsgi_string_list *usl = uwsgi.sni;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
|
||||
SSL_set_SSL_CTX(ssl, (SSL_CTX *) usl->custom_ptr);
|
||||
// the following steps are taken from nginx
|
||||
SSL_set_verify(ssl, SSL_CTX_get_verify_mode((SSL_CTX *)usl->custom_ptr),
|
||||
SSL_CTX_get_verify_callback((SSL_CTX *)usl->custom_ptr));
|
||||
SSL_set_verify_depth(ssl, SSL_CTX_get_verify_depth((SSL_CTX *)usl->custom_ptr));
|
||||
#ifdef SSL_CTRL_CLEAR_OPTIONS
|
||||
SSL_clear_options(ssl, SSL_get_options(ssl) & ~SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
|
||||
#endif
|
||||
SSL_set_options(ssl, SSL_CTX_get_options((SSL_CTX *)usl->custom_ptr));
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (!uwsgi.subscription_dotsplit) break;
|
||||
char *next = memchr(servername+1, '.', servername_len-1);
|
||||
if (next) {
|
||||
servername_len -= next - servername;
|
||||
servername = next;
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (uwsgi.subscription_dotsplit) goto end;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
|
||||
@@ -126,13 +149,12 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
if (uwsgi_file_exists(sni_dir_client_ca)) {
|
||||
client_ca = sni_dir_client_ca;
|
||||
}
|
||||
usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
|
||||
struct uwsgi_string_list *usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
|
||||
if (!usl) goto done;
|
||||
free(sni_dir_cert);
|
||||
free(sni_dir_key);
|
||||
free(sni_dir_client_ca);
|
||||
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
|
||||
uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
done:
|
||||
@@ -140,13 +162,39 @@ done:
|
||||
free(sni_dir_key);
|
||||
free(sni_dir_client_ca);
|
||||
}
|
||||
|
||||
end:
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *uwsgi_write_pem_to_file(char *name, char *buf, size_t len, char *ext) {
|
||||
if (!uwsgi.ssl_tmp_dir) return NULL;
|
||||
char *filename = uwsgi_concat4(uwsgi.ssl_tmp_dir, "/", name, ext);
|
||||
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (write(fd, buf, len) != (ssize_t) len) {
|
||||
uwsgi_log("unable to write pem data in file %s\n", filename);
|
||||
uwsgi_error("uwsgi_write_pem_to_file()/write()");
|
||||
free(filename);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return filename;
|
||||
}
|
||||
|
||||
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
|
||||
|
||||
int crt_need_free = 0;
|
||||
int key_need_free = 0;
|
||||
int client_ca_need_free = 0;
|
||||
|
||||
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
|
||||
@@ -166,11 +214,27 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
/*
|
||||
we need to support both file-based certs and stream based
|
||||
as dealing with openssl memory bio for keys is really overkill,
|
||||
we store them in a tmp directory
|
||||
*/
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(crt, strlen(crt), "-----BEGIN ", 11)) {
|
||||
crt = uwsgi_write_pem_to_file(name, crt, strlen(crt), ".crt");
|
||||
if (!crt) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
crt_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (crt_need_free) free(crt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this part is based from stud
|
||||
@@ -179,26 +243,43 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
||||
BIO_free(bio);
|
||||
if (dh) {
|
||||
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
|
||||
SSL_CTX_set_tmp_dh(ctx, dh);
|
||||
DH_free(dh);
|
||||
}
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
#ifdef NID_X9_62_prime256v1
|
||||
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if (ecdh) {
|
||||
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
|
||||
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (crt_need_free) free(crt);
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(key, strlen(key), "-----BEGIN ", 11)) {
|
||||
key = uwsgi_write_pem_to_file(name, key, strlen(key), ".key");
|
||||
if (!key) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
key_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (key_need_free) free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (key_need_free) free(key);
|
||||
|
||||
// if ciphers are specified, prefer server ciphers
|
||||
if (ciphers && strlen(ciphers) > 0) {
|
||||
@@ -226,19 +307,37 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
}
|
||||
// in the future we should allow to set the verify depth
|
||||
SSL_CTX_set_verify_depth(ctx, 1);
|
||||
|
||||
if (uwsgi.ssl_tmp_dir && !uwsgi_starts_with(client_ca, strlen(client_ca), "-----BEGIN ", 11)) {
|
||||
if (!name) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
client_ca = uwsgi_write_pem_to_file(name, client_ca, strlen(client_ca), ".ca");
|
||||
if (!client_ca) {
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
client_ca_need_free = 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
|
||||
uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
return NULL;
|
||||
}
|
||||
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
|
||||
if (!list) {
|
||||
uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
|
||||
SSL_CTX_free(ctx);
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_CTX_set_client_CA_list(ctx, list);
|
||||
|
||||
if (client_ca_need_free) free(client_ca);
|
||||
}
|
||||
|
||||
|
||||
@@ -511,10 +610,41 @@ struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *ke
|
||||
SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca);
|
||||
if (!ctx) {
|
||||
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name);
|
||||
free(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
|
||||
usl->custom_ptr = ctx;
|
||||
// mark it as dynamic
|
||||
usl->custom = 1;
|
||||
uwsgi_log_verbose("[uwsgi-sni for pid %d] added SSL context for %s\n", (int) getpid(), name);
|
||||
return usl;
|
||||
}
|
||||
|
||||
void uwsgi_ssl_del_sni_item(char *name, uint16_t name_len) {
|
||||
struct uwsgi_string_list *usl = NULL, *last_sni = NULL, *sni_item = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.sni) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, name, name_len) && usl->custom) {
|
||||
sni_item = usl;
|
||||
break;
|
||||
}
|
||||
last_sni = usl;
|
||||
}
|
||||
|
||||
if (!sni_item) return;
|
||||
|
||||
if (last_sni) {
|
||||
last_sni->next = sni_item->next;
|
||||
}
|
||||
else {
|
||||
uwsgi.sni = sni_item->next;
|
||||
}
|
||||
|
||||
// we are free to destroy it as no more clients are using it
|
||||
SSL_CTX_free((SSL_CTX *) sni_item->custom_ptr);
|
||||
free(sni_item->value);
|
||||
free(sni_item);
|
||||
|
||||
uwsgi_log_verbose("[uwsgi-sni for pid %d] destroyed SSL context for %s\n",(int) getpid(), name);
|
||||
}
|
||||
|
||||
+4
-1
@@ -450,7 +450,8 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
if (st->st_mtime <= ims) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16))
|
||||
return -1;
|
||||
return uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
}
|
||||
@@ -458,6 +459,8 @@ 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
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
|
||||
+22
-31
@@ -111,7 +111,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -123,7 +123,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -161,7 +161,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -200,7 +200,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":", key);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -239,7 +239,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":", key);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\"", str);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -266,7 +266,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\"", str);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -299,7 +299,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -337,7 +337,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
@@ -551,25 +551,16 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
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;
|
||||
uint16_t i;
|
||||
// replace " with '
|
||||
for(i=0;i<kl;i++) {
|
||||
if (k[i] == '"') {
|
||||
k[i] = '\'';
|
||||
}
|
||||
}
|
||||
for(i=0;i<vl;i++) {
|
||||
if (v[i] == '"') {
|
||||
v[i] = '\'';
|
||||
}
|
||||
}
|
||||
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
|
||||
if (uwsgi_stats_str(us, var)) {
|
||||
char *escaped_var = uwsgi_malloc(((kl+vl+1)*2)+1);
|
||||
escape_json(var, strlen(var), escaped_var);
|
||||
free(var);
|
||||
if (uwsgi_stats_str(us, escaped_var)) {
|
||||
us->dirty = 1;
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
return;
|
||||
}
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
us->dirty = 1;
|
||||
}
|
||||
@@ -578,7 +569,7 @@ static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *dat
|
||||
|
||||
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
|
||||
if (!uc->in_request) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi.workers[0].cores[0].buffer;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uc->buffer;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (!pktsize) return 0;
|
||||
char *dst = uwsgi.workers[0].cores[0].buffer;
|
||||
|
||||
+491
-222
@@ -20,6 +20,57 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static void uwsgi_subscription_sni_check(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (usr->sni_key_len > 0 && usr->sni_crt_len > 0) {
|
||||
if (!current_slot->sni_enabled) {
|
||||
char *sni_key = uwsgi_concat2n(usr->sni_key, usr->sni_key_len, "", 0);
|
||||
char *sni_crt = uwsgi_concat2n(usr->sni_crt, usr->sni_crt_len, "", 0);
|
||||
char *sni_ca = NULL;
|
||||
if (usr->sni_ca_len > 0) {
|
||||
sni_ca = uwsgi_concat2n(usr->sni_ca, usr->sni_ca_len, "", 0);
|
||||
}
|
||||
char *servername = NULL;
|
||||
char *colon = memchr(current_slot->key, ':', current_slot->keylen);
|
||||
if (colon) {
|
||||
servername = uwsgi_concat2n(current_slot->key, colon - current_slot->key, "", 0);
|
||||
}
|
||||
else {
|
||||
servername = uwsgi_concat2n(current_slot->key, current_slot->keylen, "", 0);
|
||||
}
|
||||
if (uwsgi_ssl_add_sni_item(servername, sni_crt, sni_key, uwsgi.sni_dir_ciphers, sni_ca)) {
|
||||
current_slot->sni_enabled = 1;
|
||||
}
|
||||
if (sni_key)
|
||||
free(sni_key);
|
||||
if (sni_crt)
|
||||
free(sni_crt);
|
||||
if (sni_ca)
|
||||
free(sni_ca);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_subscription_credentials_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_credentials_check_dir) {
|
||||
char *filename = uwsgi_concat2n(usl->value, usl->len, slot->key, slot->keylen);
|
||||
struct stat st;
|
||||
int ret = stat(filename, &st);
|
||||
free(filename);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
if (st.st_uid != usr->uid)
|
||||
continue;
|
||||
if (st.st_gid != usr->gid)
|
||||
continue;
|
||||
// accepted...
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
|
||||
|
||||
if (keylen > 0xff)
|
||||
@@ -301,10 +352,16 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
// first check if i am the only node
|
||||
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (node_slot->sign_ctx) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(node_slot->sign_ctx);
|
||||
}
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
// if there is a SNI context active, destroy it
|
||||
if (node_slot->sni_enabled) {
|
||||
uwsgi_ssl_del_sni_item(node_slot->key, node_slot->keylen);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
free(node_slot);
|
||||
slot[hash_key] = NULL;
|
||||
@@ -324,7 +381,7 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (node_slot->sign_ctx) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(node_slot->sign_ctx);
|
||||
}
|
||||
@@ -337,6 +394,11 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int subscription_new_sign_ctx(struct uwsgi_subscribe_slot *, struct uwsgi_subscribe_req *);
|
||||
static int subscription_is_safe(struct uwsgi_subscribe_req *);
|
||||
#endif
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) {
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot;
|
||||
@@ -345,28 +407,28 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (usr->address_len > 0xff || usr->address_len == 0)
|
||||
return NULL;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_slot) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir && !uwsgi_subscription_sign_check(current_slot, usr)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.subscriptions_credentials_check_dir && !uwsgi_subscription_credentials_check(current_slot, usr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = current_slot->nodes;
|
||||
while (node) {
|
||||
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
|
||||
#ifdef UWSGI_SSL
|
||||
// this should avoid sending sniffed packets...
|
||||
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check <= node->unix_check) {
|
||||
if (current_slot->sign_ctx && !subscription_is_safe(usr) && usr->unix_check <= node->unix_check) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
// eventually the packet could be upgraded to sni...
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
// remove death mark and update cores and load
|
||||
node->death_mark = 0;
|
||||
@@ -384,10 +446,12 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
if (current_slot->sign_ctx && !subscription_is_safe(usr) && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
// check here as we are sure the node will be added
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
|
||||
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
@@ -396,7 +460,8 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
node->modifier2 = usr->modifier2;
|
||||
node->requests = 0;
|
||||
node->last_requests = 0;
|
||||
node->transferred = 0;
|
||||
node->tx = 0;
|
||||
node->rx = 0;
|
||||
node->reference = 0;
|
||||
node->death_mark = 0;
|
||||
node->failcnt = 0;
|
||||
@@ -407,6 +472,14 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (!node->weight)
|
||||
node->weight = 1;
|
||||
node->wrr = 0;
|
||||
node->pid = usr->pid;
|
||||
node->uid = usr->uid;
|
||||
node->gid = usr->gid;
|
||||
node->notify[0] = 0;
|
||||
if (usr->notify_len > 0 && usr->notify_len < 102) {
|
||||
memcpy(node->notify, usr->notify, usr->notify_len);
|
||||
node->notify[usr->notify_len] = 0;
|
||||
}
|
||||
node->last_check = uwsgi_now();
|
||||
node->slot = current_slot;
|
||||
memcpy(node->name, usr->address, usr->address_len);
|
||||
@@ -414,66 +487,51 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
old_node->next = node;
|
||||
}
|
||||
node->next = NULL;
|
||||
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (node->notify[0]) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "[subscription ack] %.*s => new node: %.*s", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (ret > 0 && ret < 1024)
|
||||
uwsgi_notify_msg(node->notify, buf, ret);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
|
||||
#ifdef UWSGI_SSL
|
||||
FILE *kf = NULL;
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
|
||||
kf = fopen(keyfile, "r");
|
||||
free(keyfile);
|
||||
if (!kf)
|
||||
return NULL;
|
||||
|
||||
current_slot->sign_ctx = NULL;
|
||||
if (uwsgi.subscriptions_sign_check_dir && !subscription_new_sign_ctx(current_slot, usr)) {
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
|
||||
uint32_t hash = djb33x_hash(usr->key, usr->keylen);
|
||||
int hash_key = hash % 0xffff;
|
||||
current_slot->hash = hash_key;
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
current_slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
|
||||
fclose(kf);
|
||||
if (!current_slot->sign_public_key) {
|
||||
uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
current_slot->sign_ctx = EVP_MD_CTX_create();
|
||||
if (!current_slot->sign_ctx) {
|
||||
uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
|
||||
EVP_PKEY_free(current_slot->sign_public_key);
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!uwsgi_subscription_sign_check(current_slot, usr)) {
|
||||
EVP_PKEY_free(current_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(current_slot->sign_ctx);
|
||||
current_slot->keylen = usr->keylen;
|
||||
memcpy(current_slot->key, usr->key, usr->keylen);
|
||||
if (uwsgi.subscriptions_credentials_check_dir) {
|
||||
if (!uwsgi_subscription_credentials_check(current_slot, usr)) {
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
current_slot->keylen = usr->keylen;
|
||||
memcpy(current_slot->key, usr->key, usr->keylen);
|
||||
|
||||
current_slot->key[usr->keylen] = 0;
|
||||
current_slot->hits = 0;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
current_slot->sni_enabled = 0;
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
current_slot->nodes->slot = current_slot;
|
||||
current_slot->nodes->len = usr->address_len;
|
||||
current_slot->nodes->reference = 0;
|
||||
current_slot->nodes->requests = 0;
|
||||
current_slot->nodes->last_requests = 0;
|
||||
current_slot->nodes->transferred = 0;
|
||||
current_slot->nodes->tx = 0;
|
||||
current_slot->nodes->rx = 0;
|
||||
current_slot->nodes->death_mark = 0;
|
||||
current_slot->nodes->failcnt = 0;
|
||||
current_slot->nodes->modifier1 = usr->modifier1;
|
||||
@@ -485,6 +543,14 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (!current_slot->nodes->weight)
|
||||
current_slot->nodes->weight = 1;
|
||||
current_slot->nodes->wrr = 0;
|
||||
current_slot->nodes->pid = usr->pid;
|
||||
current_slot->nodes->uid = usr->uid;
|
||||
current_slot->nodes->gid = usr->gid;
|
||||
current_slot->nodes->notify[0] = 0;
|
||||
if (usr->notify_len > 0 && usr->notify_len < 102) {
|
||||
memcpy(current_slot->nodes->notify, usr->notify, usr->notify_len);
|
||||
current_slot->nodes->notify[usr->notify_len] = 0;
|
||||
}
|
||||
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
|
||||
current_slot->nodes->last_check = uwsgi_now();
|
||||
|
||||
@@ -511,42 +577,153 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash);
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
|
||||
if (current_slot->nodes->notify[0]) {
|
||||
char buf[1024];
|
||||
int ret = snprintf(buf, 1024, "[subscription ack] %.*s => new node: %.*s", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
if (ret > 0 && ret < 1024)
|
||||
uwsgi_notify_msg(current_slot->nodes->notify, buf, ret);
|
||||
}
|
||||
return current_slot->nodes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void send_subscription(int sfd, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
|
||||
int fd = sfd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
ssize_t ret;
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
char *udp_port = strchr(host, ':');
|
||||
|
||||
if (!socket_name) {
|
||||
socket_name = uwsgi.sockets->name;
|
||||
if (fd == -1) {
|
||||
if (udp_port) {
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
else {
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
}
|
||||
if (fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(fd);
|
||||
}
|
||||
else if (fd == -2) {
|
||||
static int unix_fd = -1;
|
||||
static int inet_fd = -1;
|
||||
if (udp_port) {
|
||||
if (inet_fd == -1) {
|
||||
inet_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (inet_fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(inet_fd);
|
||||
}
|
||||
fd = inet_fd;
|
||||
}
|
||||
else {
|
||||
if (unix_fd == -1) {
|
||||
unix_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (unix_fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(unix_fd);
|
||||
}
|
||||
fd = unix_fd;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, host, 102);
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
// could be useless as internally the socket could add them automagically
|
||||
ret = uwsgi_pass_cred2(fd, message, message_size, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_subscription()/sendto()");
|
||||
}
|
||||
|
||||
if (sfd == -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
|
||||
// make space for uwsgi header
|
||||
ub->pos = 4;
|
||||
|
||||
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize)) goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name))) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores)) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load)) goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name)))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load))
|
||||
goto end;
|
||||
if (uwsgi.auto_weight) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores))
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_key) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, sni_key, strlen(sni_key)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_crt) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, sni_crt, strlen(sni_crt)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sni_ca) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, sni_ca, strlen(sni_ca)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.subscription_notify_socket) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.subscription_notify_socket, strlen(uwsgi.subscription_notify_socket)))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi.notify_socket_fd > -1 && uwsgi.notify_socket) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "notify", 6, uwsgi.notify_socket, strlen(uwsgi.notify_socket)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (sign) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd) )) goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd)))
|
||||
goto end;
|
||||
|
||||
unsigned int signature_len = 0;
|
||||
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
|
||||
@@ -560,15 +737,98 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
|
||||
}
|
||||
#endif
|
||||
|
||||
// add uwsgi header
|
||||
if (uwsgi_buffer_set_uh(ub, 224, cmd))
|
||||
goto end;
|
||||
|
||||
return ub;
|
||||
|
||||
send_udp_message(224, cmd, udp_address, ub->buf, ub->pos - 4);
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_send_subscription_from_fd(int fd, char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
|
||||
if (!socket_name) {
|
||||
socket_name = uwsgi.sockets->name;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_subscription_ub(key, keysize, modifier1, modifier2, cmd, socket_name, sign, sni_key, sni_crt, sni_ca);
|
||||
|
||||
if (!ub)
|
||||
return;
|
||||
|
||||
send_subscription(fd, udp_address, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
uwsgi_send_subscription_from_fd(-1, udp_address, key, keysize, modifier1, modifier2, cmd, socket_name, sign, sni_key, sni_crt, sni_ca);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static int subscription_is_safe(struct uwsgi_subscribe_req *usr) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_sign_skip_uid) {
|
||||
if (usl->custom == 0) {
|
||||
usl->custom = atoi(usl->value);
|
||||
}
|
||||
if (usr->uid > 0 && usr->uid == (uid_t) usl->custom) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int subscription_new_sign_ctx(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (subscription_is_safe(usr)) return 1;
|
||||
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return 0;
|
||||
|
||||
if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
|
||||
FILE *kf = fopen(keyfile, "r");
|
||||
free(keyfile);
|
||||
if (!kf) return 0;
|
||||
slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
|
||||
fclose(kf);
|
||||
if (!slot->sign_public_key) {
|
||||
uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
|
||||
return 0;
|
||||
}
|
||||
slot->sign_ctx = EVP_MD_CTX_create();
|
||||
if (!slot->sign_ctx) {
|
||||
uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
|
||||
EVP_PKEY_free(slot->sign_public_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_subscription_sign_check(slot, usr)) {
|
||||
EVP_PKEY_free(slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(slot->sign_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
int uwsgi_subscription_sign_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (subscription_is_safe(usr)) return 1;
|
||||
|
||||
if (usr->sign_len == 0 || usr->base_len == 0)
|
||||
return 0;
|
||||
|
||||
if (!slot->sign_ctx) {
|
||||
if (!subscription_new_sign_ctx(slot, usr)) return 0;
|
||||
}
|
||||
|
||||
if (EVP_VerifyInit_ex(slot->sign_ctx, uwsgi.subscriptions_sign_check_md, NULL) == 0) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
@@ -610,134 +870,133 @@ struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
|
||||
|
||||
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
|
||||
size_t subfile_size;
|
||||
size_t i;
|
||||
char *key = NULL;
|
||||
int keysize = 0;
|
||||
char *modifier1 = NULL;
|
||||
int modifier1_len = 0;
|
||||
char *socket_name = NULL;
|
||||
char *udp_address = subscription;
|
||||
char *udp_port = NULL;
|
||||
char *subscription_key = NULL;
|
||||
char *sign = NULL;
|
||||
size_t subfile_size;
|
||||
size_t i;
|
||||
char *key = NULL;
|
||||
int keysize = 0;
|
||||
char *modifier1 = NULL;
|
||||
int modifier1_len = 0;
|
||||
char *socket_name = NULL;
|
||||
char *udp_address = subscription;
|
||||
char *udp_port = NULL;
|
||||
char *subscription_key = NULL;
|
||||
char *sign = NULL;
|
||||
|
||||
// check for explicit socket_name
|
||||
char *equal = strchr(subscription, '=');
|
||||
if (equal) {
|
||||
socket_name = subscription;
|
||||
if (socket_name[0] == '=') {
|
||||
equal = strchr(socket_name + 1, '=');
|
||||
if (!equal)
|
||||
return;
|
||||
*equal = '\0';
|
||||
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
|
||||
if (!us)
|
||||
return;
|
||||
socket_name = us->name;
|
||||
}
|
||||
*equal = '\0';
|
||||
udp_address = equal + 1;
|
||||
}
|
||||
// check for explicit socket_name
|
||||
char *equal = strchr(subscription, '=');
|
||||
if (equal) {
|
||||
socket_name = subscription;
|
||||
if (socket_name[0] == '=') {
|
||||
equal = strchr(socket_name + 1, '=');
|
||||
if (!equal)
|
||||
return;
|
||||
*equal = '\0';
|
||||
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
|
||||
if (!us)
|
||||
return;
|
||||
socket_name = us->name;
|
||||
}
|
||||
*equal = '\0';
|
||||
udp_address = equal + 1;
|
||||
}
|
||||
|
||||
// check for unix socket
|
||||
if (udp_address[0] != '/') {
|
||||
udp_port = strchr(udp_address, ':');
|
||||
if (!udp_port) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
subscription_key = strchr(udp_port + 1, ':');
|
||||
}
|
||||
else {
|
||||
subscription_key = strchr(udp_address + 1, ':');
|
||||
}
|
||||
// check for unix socket
|
||||
if (udp_address[0] != '/') {
|
||||
udp_port = strchr(udp_address, ':');
|
||||
if (!udp_port) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
subscription_key = strchr(udp_port + 1, ':');
|
||||
}
|
||||
else {
|
||||
subscription_key = strchr(udp_address + 1, ':');
|
||||
}
|
||||
|
||||
if (!subscription_key) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
if (!subscription_key) {
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
return;
|
||||
}
|
||||
|
||||
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
|
||||
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
|
||||
|
||||
if (subscription_key[1] == '@') {
|
||||
if (!uwsgi_file_exists(subscription_key + 2))
|
||||
goto clear;
|
||||
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
|
||||
if (subfile_size > 0) {
|
||||
key = lines;
|
||||
for (i = 0; i < subfile_size; i++) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (lines[i] == '\n') {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
}
|
||||
}
|
||||
key = lines + i + 1;
|
||||
keysize = 0;
|
||||
continue;
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
if (!uwsgi_file_exists(subscription_key + 2))
|
||||
goto clear;
|
||||
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
|
||||
if (subfile_size > 0) {
|
||||
key = lines;
|
||||
for (i = 0; i < subfile_size; i++) {
|
||||
if (lines[i] == 0) {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (lines[i] == '\n') {
|
||||
if (keysize > 0) {
|
||||
if (key[0] != '#' && key[0] != '\n') {
|
||||
lines[i] = 0;
|
||||
modifier1 = strchr(key, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
}
|
||||
}
|
||||
key = lines + i + 1;
|
||||
keysize = 0;
|
||||
continue;
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
}
|
||||
free(lines);
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
|
||||
free(lines);
|
||||
}
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
if (modifier1) {
|
||||
modifier1[0] = 0;
|
||||
modifier1++;
|
||||
sign = strchr(modifier1 + 1, ',');
|
||||
if (sign) {
|
||||
*sign = 0;
|
||||
sign++;
|
||||
}
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
|
||||
sign = strchr(modifier1 + 1, ',');
|
||||
if (sign) {
|
||||
*sign = 0;
|
||||
sign++;
|
||||
}
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
sign[-1] = ',';
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
sign[-1] = ',';
|
||||
}
|
||||
|
||||
clear:
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
free(udp_address);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
free(udp_address);
|
||||
|
||||
}
|
||||
|
||||
@@ -752,25 +1011,20 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
char *s2_modifier1 = NULL;
|
||||
char *s2_modifier2 = NULL;
|
||||
char *s2_check = NULL;
|
||||
char *s2_sni_key = NULL;
|
||||
char *s2_sni_crt = NULL;
|
||||
char *s2_sni_ca = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"server", &s2_server,
|
||||
"key", &s2_key,
|
||||
"socket", &s2_socket,
|
||||
"addr", &s2_addr,
|
||||
"weight", &s2_weight,
|
||||
"modifier1", &s2_modifier1,
|
||||
"modifier2", &s2_modifier2,
|
||||
"sign", &s2_sign,
|
||||
"check", &s2_check,
|
||||
NULL)) {
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "server", &s2_server, "key", &s2_key, "socket", &s2_socket, "addr", &s2_addr, "weight", &s2_weight, "modifier1", &s2_modifier1, "modifier2", &s2_modifier2, "sign", &s2_sign, "check", &s2_check, "sni_key", &s2_sni_key, "sni_crt", &s2_sni_crt, "sni_ca", &s2_sni_ca, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s2_server || !s2_key) goto end;
|
||||
if (!s2_server || !s2_key)
|
||||
goto end;
|
||||
|
||||
if (s2_check) {
|
||||
if (uwsgi_file_exists(s2_check)) goto end;
|
||||
if (uwsgi_file_exists(s2_check))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s2_weight) {
|
||||
@@ -798,41 +1052,56 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
modifier2 = atoi(s2_modifier2);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign);
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign, s2_sni_key, s2_sni_crt, s2_sni_ca);
|
||||
end:
|
||||
if (s2_server) free(s2_server);
|
||||
if (s2_key) free(s2_key);
|
||||
if (s2_socket) free(s2_socket);
|
||||
if (s2_addr) free(s2_addr);
|
||||
if (s2_weight) free(s2_weight);
|
||||
if (s2_modifier1) free(s2_modifier1);
|
||||
if (s2_modifier2) free(s2_modifier2);
|
||||
if (s2_sign) free(s2_sign);
|
||||
if (s2_check) free(s2_check);
|
||||
if (s2_server)
|
||||
free(s2_server);
|
||||
if (s2_key)
|
||||
free(s2_key);
|
||||
if (s2_socket)
|
||||
free(s2_socket);
|
||||
if (s2_addr)
|
||||
free(s2_addr);
|
||||
if (s2_weight)
|
||||
free(s2_weight);
|
||||
if (s2_modifier1)
|
||||
free(s2_modifier1);
|
||||
if (s2_modifier2)
|
||||
free(s2_modifier2);
|
||||
if (s2_sign)
|
||||
free(s2_sign);
|
||||
if (s2_check)
|
||||
free(s2_check);
|
||||
if (s2_sni_crt)
|
||||
free(s2_sni_crt);
|
||||
if (s2_sni_key)
|
||||
free(s2_sni_key);
|
||||
if (s2_sni_ca)
|
||||
free(s2_sni_ca);
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
if (uwsgi.subscriptions_blocked) return;
|
||||
if (uwsgi.subscriptions_blocked)
|
||||
return;
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
uwsgi_subscribe(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
// --subscribe2
|
||||
subscriptions = uwsgi.subscriptions2;
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe2(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
while (subscriptions) {
|
||||
if (verbose) {
|
||||
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
|
||||
}
|
||||
uwsgi_subscribe2(subscriptions->value, cmd);
|
||||
subscriptions = subscriptions->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+345
-233
@@ -47,7 +47,7 @@ void inc_harakiri(int sec) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri += sec;
|
||||
}
|
||||
else {
|
||||
alarm(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] + sec);
|
||||
alarm(uwsgi.harakiri_options.workers + sec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,8 @@ void uwsgi_set_cgroup() {
|
||||
if (!uwsgi.cgroup)
|
||||
return;
|
||||
|
||||
if (getuid()) return;
|
||||
if (getuid())
|
||||
return;
|
||||
|
||||
usl = uwsgi.cgroup;
|
||||
|
||||
@@ -278,41 +279,41 @@ void uwsgi_set_cgroup() {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
void uwsgi_apply_cap(cap_value_t *cap, int caps_count) {
|
||||
cap_value_t minimal_cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID, CAP_SETPCAP };
|
||||
void uwsgi_apply_cap(cap_value_t * cap, int caps_count) {
|
||||
cap_value_t minimal_cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID, CAP_SETPCAP };
|
||||
|
||||
cap_t caps = cap_init();
|
||||
cap_t caps = cap_init();
|
||||
|
||||
if (!caps) {
|
||||
uwsgi_error("cap_init()");
|
||||
exit(1);
|
||||
}
|
||||
cap_clear(caps);
|
||||
if (!caps) {
|
||||
uwsgi_error("cap_init()");
|
||||
exit(1);
|
||||
}
|
||||
cap_clear(caps);
|
||||
|
||||
cap_set_flag(caps, CAP_EFFECTIVE, 4, minimal_cap_values, CAP_SET);
|
||||
cap_set_flag(caps, CAP_EFFECTIVE, 4, minimal_cap_values, CAP_SET);
|
||||
|
||||
cap_set_flag(caps, CAP_PERMITTED, 4, minimal_cap_values, CAP_SET);
|
||||
cap_set_flag(caps, CAP_PERMITTED, caps_count, cap, CAP_SET);
|
||||
cap_set_flag(caps, CAP_PERMITTED, 4, minimal_cap_values, CAP_SET);
|
||||
cap_set_flag(caps, CAP_PERMITTED, caps_count, cap, CAP_SET);
|
||||
|
||||
cap_set_flag(caps, CAP_INHERITABLE, caps_count, cap, CAP_SET);
|
||||
cap_set_flag(caps, CAP_INHERITABLE, caps_count, cap, CAP_SET);
|
||||
|
||||
if (cap_set_proc(caps) < 0) {
|
||||
uwsgi_error("cap_set_proc()");
|
||||
exit(1);
|
||||
}
|
||||
cap_free(caps);
|
||||
if (cap_set_proc(caps) < 0) {
|
||||
uwsgi_error("cap_set_proc()");
|
||||
exit(1);
|
||||
}
|
||||
cap_free(caps);
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef SECBIT_KEEP_CAPS
|
||||
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -517,7 +518,7 @@ void uwsgi_as_root() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (in_jail) {
|
||||
if (in_jail || uwsgi.jailed) {
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_post_jail) {
|
||||
@@ -587,7 +588,7 @@ void uwsgi_as_root() {
|
||||
exit(1);
|
||||
}
|
||||
#ifdef __linux__
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
|
||||
if (uwsgi.logging_options.memory_report) {
|
||||
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
|
||||
}
|
||||
#endif
|
||||
@@ -603,10 +604,10 @@ void uwsgi_as_root() {
|
||||
}
|
||||
*space = 0;
|
||||
#if defined(MS_REC) && defined(MS_PRIVATE)
|
||||
if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
if (chdir(arg)) {
|
||||
uwsgi_error("pivot_root()/chdir()");
|
||||
@@ -619,7 +620,7 @@ void uwsgi_as_root() {
|
||||
uwsgi_error("pivot_root()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
|
||||
if (uwsgi.logging_options.memory_report) {
|
||||
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
|
||||
}
|
||||
free(arg);
|
||||
@@ -632,25 +633,25 @@ void uwsgi_as_root() {
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
if (uwsgi.unshare2 && !uwsgi.reloads) {
|
||||
if (uwsgi.unshare2 && !uwsgi.reloads) {
|
||||
|
||||
if (unshare(uwsgi.unshare2)) {
|
||||
uwsgi_error("unshare()");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare2);
|
||||
}
|
||||
if (unshare(uwsgi.unshare2)) {
|
||||
uwsgi_error("unshare()");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare2);
|
||||
}
|
||||
#ifdef CLONE_NEWUSER
|
||||
if (uwsgi.unshare2 & CLONE_NEWUSER) {
|
||||
if (setuid(0)) {
|
||||
uwsgi_error("uwsgi_as_root()/setuid(0)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (uwsgi.unshare2 & CLONE_NEWUSER) {
|
||||
if (setuid(0)) {
|
||||
uwsgi_error("uwsgi_as_root()/setuid(0)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
in_jail = 1;
|
||||
}
|
||||
in_jail = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.refork_as_root) {
|
||||
@@ -753,7 +754,11 @@ void uwsgi_as_root() {
|
||||
}
|
||||
|
||||
if (uwsgi.logfile_chown) {
|
||||
if (fchown(2, uwsgi.uid, uwsgi.gid)) {
|
||||
int log_fd = 2;
|
||||
if (uwsgi.log_master && uwsgi.original_log_fd > -1) {
|
||||
log_fd = uwsgi.original_log_fd;
|
||||
}
|
||||
if (fchown(log_fd, uwsgi.uid, uwsgi.gid)) {
|
||||
uwsgi_error("fchown()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -977,20 +982,51 @@ nonroot:
|
||||
}
|
||||
}
|
||||
|
||||
static void close_and_free_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// close the connection with the client
|
||||
if (!wsgi_req->fd_closed) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_file) {
|
||||
fclose(wsgi_req->post_file);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_read_buf) {
|
||||
free(wsgi_req->post_read_buf);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_readline_buf) {
|
||||
free(wsgi_req->post_readline_buf);
|
||||
}
|
||||
|
||||
if (wsgi_req->proto_parser_buf) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// destroy a request
|
||||
void uwsgi_destroy_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
close_and_free_request(wsgi_req);
|
||||
|
||||
int foo;
|
||||
if (uwsgi.threads > 1) {
|
||||
// now the thread can die...
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &foo);
|
||||
}
|
||||
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
if (uwsgi.threads > 1) {
|
||||
// now the thread can die...
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &foo);
|
||||
}
|
||||
|
||||
// reset for avoiding following requests to fail on non-uwsgi protocols
|
||||
// thanks Marko Tiikkaja for catching it
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
|
||||
// some plugins expected async_id to be defined before setup
|
||||
int tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
wsgi_req->async_id = tmp_id;
|
||||
}
|
||||
|
||||
// finalize/close/free a request
|
||||
@@ -1021,13 +1057,14 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uint64_t end_of_request = uwsgi_micros();
|
||||
wsgi_req->end_of_request = end_of_request;
|
||||
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
if (!wsgi_req->do_not_account_avg_rt) {
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
}
|
||||
|
||||
// get memory usage
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
get_memusage(&rss, &vsz);
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = rss;
|
||||
@@ -1048,27 +1085,8 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_apply_final_routes(wsgi_req);
|
||||
#endif
|
||||
|
||||
// close the connection with the client
|
||||
if (!wsgi_req->fd_closed) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_file) {
|
||||
fclose(wsgi_req->post_file);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_read_buf) {
|
||||
free(wsgi_req->post_read_buf);
|
||||
}
|
||||
|
||||
if (wsgi_req->post_readline_buf) {
|
||||
free(wsgi_req->post_readline_buf);
|
||||
}
|
||||
|
||||
if (wsgi_req->proto_parser_buf) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
}
|
||||
// close socket and free parsers-allocated memory
|
||||
close_and_free_request(wsgi_req);
|
||||
|
||||
// after_request hook
|
||||
if (!wsgi_req->is_raw && uwsgi.p[wsgi_req->uh->modifier1]->after_request)
|
||||
@@ -1077,7 +1095,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
// after_request custom hooks
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.after_request_hooks) {
|
||||
void (*func)(struct wsgi_request *) = (void (*)(struct wsgi_request *)) usl->custom_ptr;
|
||||
void (*func) (struct wsgi_request *) = (void (*)(struct wsgi_request *)) usl->custom_ptr;
|
||||
func(wsgi_req);
|
||||
}
|
||||
|
||||
@@ -1107,7 +1125,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// defunct process reaper
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1) {
|
||||
if (uwsgi.reaper == 1) {
|
||||
while (waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
@@ -1154,21 +1172,21 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
// some plugins expected async_id to be defined before setup
|
||||
wsgi_req->async_id = tmp_id;
|
||||
|
||||
// yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.shared->options[UWSGI_OPTION_MAX_REQUESTS]
|
||||
&& (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
|
||||
if (uwsgi.max_requests > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.max_requests
|
||||
&& (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
|
||||
if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] * 1000000)) {
|
||||
if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
@@ -1344,13 +1362,13 @@ int wsgi_req_async_recv(struct wsgi_request *wsgi_req) {
|
||||
if (event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->fd) < 0)
|
||||
return -1;
|
||||
|
||||
async_add_timeout(wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
async_add_timeout(wsgi_req, uwsgi.socket_timeout);
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
|
||||
}
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1381,8 +1399,8 @@ int wsgi_req_recv(int queue, struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
@@ -1431,7 +1449,7 @@ void uwsgi_heartbeat() {
|
||||
return;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
if (uwsgi.next_heartbeat < now) {
|
||||
if (uwsgi.next_heartbeat <= now) {
|
||||
char byte = 26;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
@@ -1455,7 +1473,15 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
// heartbeat
|
||||
// in multithreaded mode we are now locked
|
||||
if (uwsgi.has_emperor && uwsgi.heartbeat) {
|
||||
time_t now = uwsgi_now();
|
||||
// overengineering ... (reduce skew problems)
|
||||
timeout = uwsgi.heartbeat;
|
||||
if (!uwsgi.next_heartbeat) {
|
||||
uwsgi.next_heartbeat = now;
|
||||
}
|
||||
if (uwsgi.next_heartbeat >= now) {
|
||||
timeout = uwsgi.next_heartbeat - now;
|
||||
}
|
||||
}
|
||||
|
||||
// need edge trigger ?
|
||||
@@ -1478,7 +1504,7 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// check for heartbeat
|
||||
if (timeout > 0) {
|
||||
if (uwsgi.has_emperor && uwsgi.heartbeat) {
|
||||
uwsgi_heartbeat();
|
||||
// no need to continue if timed-out
|
||||
if (ret == 0) {
|
||||
@@ -1560,15 +1586,7 @@ void parse_sys_envs(char **envs) {
|
||||
char *earg, *eq_pos;
|
||||
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_", 6) &&
|
||||
strncmp(*uenvs, "UWSGI_RELOADS=", 14) &&
|
||||
strncmp(*uenvs, "UWSGI_VASSALS_DIR=", 18) &&
|
||||
strncmp(*uenvs, "UWSGI_EMPEROR_FD=", 17) &&
|
||||
strncmp(*uenvs, "UWSGI_BROODLORD_NUM=", 20) &&
|
||||
strncmp(*uenvs, "UWSGI_EMPEROR_FD_CONFIG=", 24) &&
|
||||
strncmp(*uenvs, "UWSGI_EMPEROR_PROXY=", 20) &&
|
||||
strncmp(*uenvs, "UWSGI_JAIL_PID=", 15) &&
|
||||
strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
|
||||
if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=", 14) && strncmp(*uenvs, "UWSGI_VASSALS_DIR=", 18) && strncmp(*uenvs, "UWSGI_EMPEROR_FD=", 17) && strncmp(*uenvs, "UWSGI_BROODLORD_NUM=", 20) && strncmp(*uenvs, "UWSGI_EMPEROR_FD_CONFIG=", 24) && strncmp(*uenvs, "UWSGI_EMPEROR_PROXY=", 20) && strncmp(*uenvs, "UWSGI_JAIL_PID=", 15) && strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
|
||||
earg = uwsgi_malloc(strlen(*uenvs + 6) + 1);
|
||||
env_to_arg(*uenvs + 6, earg);
|
||||
eq_pos = strchr(earg, '=');
|
||||
@@ -1871,7 +1889,7 @@ int uwsgi_num2str2n(int num, char *ptr, int size) {
|
||||
|
||||
int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
|
||||
int ret = snprintf(ptr, size, "%llu", num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0 || ret > size)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
@@ -2779,6 +2797,7 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
|
||||
{"ns", CLONE_NEWNS},
|
||||
{"fs", CLONE_NEWNS},
|
||||
{"mount", CLONE_NEWNS},
|
||||
{"mnt", CLONE_NEWNS},
|
||||
#endif
|
||||
#ifdef CLONE_SYSVSEM
|
||||
{"sysvsem", CLONE_SYSVSEM},
|
||||
@@ -2898,7 +2917,7 @@ static int uwsgi_get_cap_id(char *name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_build_cap(char *what, cap_value_t **cap) {
|
||||
int uwsgi_build_cap(char *what, cap_value_t ** cap) {
|
||||
|
||||
int cap_id;
|
||||
char *caps = uwsgi_str(what);
|
||||
@@ -3143,6 +3162,10 @@ void escape_json(char *src, size_t len, char *dst) {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '"';
|
||||
}
|
||||
else if (src[i] == '\\') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '\\';
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
@@ -3192,128 +3215,139 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
for (i = 0; i < *len; i++) {
|
||||
char c = buf[i];
|
||||
if (c == '#') break;
|
||||
switch(status) {
|
||||
case zero:
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
if (c == '#')
|
||||
break;
|
||||
switch (status) {
|
||||
case zero:
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
case percent1:
|
||||
if (c == '%') {
|
||||
*ptr++ = '%';
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
}
|
||||
value[0] = c;
|
||||
status = percent2;
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
case percent2:
|
||||
value[1] = c;
|
||||
*ptr++ = hex2num(value);
|
||||
}
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
break;
|
||||
case percent1:
|
||||
if (c == '%') {
|
||||
*ptr++ = '%';
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
case slash:
|
||||
if (c == '.') {
|
||||
status = dot;
|
||||
break;
|
||||
}
|
||||
// we could be at the first round (in non slash)
|
||||
if (i > 0 || !no_slash) {
|
||||
*ptr++ = '/'; new_len++;
|
||||
}
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c; new_len++;
|
||||
status = zero;
|
||||
}
|
||||
value[0] = c;
|
||||
status = percent2;
|
||||
break;
|
||||
case percent2:
|
||||
value[1] = c;
|
||||
*ptr++ = hex2num(value);
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
case slash:
|
||||
if (c == '.') {
|
||||
status = dot;
|
||||
break;
|
||||
case dot:
|
||||
if (c == '.') {
|
||||
status = dotdot;
|
||||
break;
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
if (i > 1) {
|
||||
*ptr++ = '/'; new_len++;
|
||||
}
|
||||
*ptr++ = '.'; new_len++;
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c; new_len++;
|
||||
status = zero;
|
||||
}
|
||||
// we could be at the first round (in non slash)
|
||||
if (i > 0 || !no_slash) {
|
||||
*ptr++ = '/';
|
||||
new_len++;
|
||||
}
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
case dotdot:
|
||||
// here we need to remove a segment
|
||||
if (c == '/') {
|
||||
current_new_len = new_len;
|
||||
while(current_new_len) {
|
||||
current_new_len--;
|
||||
ptr--;
|
||||
if (dst[current_new_len] == '/') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
case dot:
|
||||
if (c == '.') {
|
||||
status = dotdot;
|
||||
break;
|
||||
}
|
||||
if (c == '/') {
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
if (i > 1) {
|
||||
*ptr++ = '/';
|
||||
new_len++;
|
||||
}
|
||||
*ptr++ = '.';
|
||||
new_len++;
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
case dotdot:
|
||||
// here we need to remove a segment
|
||||
if (c == '/') {
|
||||
current_new_len = new_len;
|
||||
while (current_new_len) {
|
||||
current_new_len--;
|
||||
ptr--;
|
||||
if (dst[current_new_len] == '/') {
|
||||
break;
|
||||
}
|
||||
new_len = current_new_len;
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
if (i > 2) {
|
||||
*ptr++ = '/'; new_len++;
|
||||
}
|
||||
*ptr++ = '.'; new_len++;
|
||||
*ptr++ = '.'; new_len++;
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c; new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
new_len = current_new_len;
|
||||
status = slash;
|
||||
break;
|
||||
}
|
||||
if (i > 2) {
|
||||
*ptr++ = '/';
|
||||
new_len++;
|
||||
}
|
||||
*ptr++ = '.';
|
||||
new_len++;
|
||||
*ptr++ = '.';
|
||||
new_len++;
|
||||
if (c == '%') {
|
||||
status = percent1;
|
||||
break;
|
||||
}
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
status = zero;
|
||||
break;
|
||||
// over engineering
|
||||
default:
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
break;
|
||||
default:
|
||||
*ptr++ = c;
|
||||
new_len++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(status) {
|
||||
case slash:
|
||||
case dot:
|
||||
*ptr++ = '/'; new_len++;
|
||||
break;
|
||||
case dotdot:
|
||||
current_new_len = new_len;
|
||||
while(current_new_len) {
|
||||
if (dst[current_new_len-1] == '/') {
|
||||
break;
|
||||
}
|
||||
current_new_len--;
|
||||
switch (status) {
|
||||
case slash:
|
||||
case dot:
|
||||
*ptr++ = '/';
|
||||
new_len++;
|
||||
break;
|
||||
case dotdot:
|
||||
current_new_len = new_len;
|
||||
while (current_new_len) {
|
||||
if (dst[current_new_len - 1] == '/') {
|
||||
break;
|
||||
}
|
||||
new_len = current_new_len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
current_new_len--;
|
||||
}
|
||||
new_len = current_new_len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*len = new_len;
|
||||
@@ -3573,7 +3607,7 @@ void uwsgi_set_cpu_affinity() {
|
||||
base_cpu = base_cpu % uwsgi.cpus;
|
||||
}
|
||||
ret = snprintf(buf, 4096, "mapping worker %d to CPUs:", uwsgi.mywid);
|
||||
if (ret < 25) {
|
||||
if (ret < 25 || ret >= 4096) {
|
||||
uwsgi_log("unable to initialize cpu affinity !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -3591,7 +3625,7 @@ void uwsgi_set_cpu_affinity() {
|
||||
base_cpu = 0;
|
||||
CPU_SET(base_cpu, &cpuset);
|
||||
ret = snprintf(buf + pos, 4096 - pos, " %d", base_cpu);
|
||||
if (ret < 2) {
|
||||
if (ret < 2 || ret >= 4096) {
|
||||
uwsgi_log("unable to initialize cpu affinity !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -3729,7 +3763,7 @@ static void *uwsgi_thread_run(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
struct uwsgi_thread *uwsgi_thread_new_with_data(void (*func) (struct uwsgi_thread *), void *data) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_calloc(sizeof(struct uwsgi_thread));
|
||||
|
||||
@@ -3746,6 +3780,7 @@ struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
uwsgi_socket_nb(ut->pipe[1]);
|
||||
|
||||
ut->func = func;
|
||||
ut->data = data;
|
||||
|
||||
pthread_attr_init(&ut->tattr);
|
||||
pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED);
|
||||
@@ -3765,6 +3800,10 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
return uwsgi_thread_new_with_data(func, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
|
||||
size_t i;
|
||||
va_list ap;
|
||||
@@ -3854,7 +3893,7 @@ int uwsgi_send_http_stats(int fd) {
|
||||
|
||||
char buf[4096];
|
||||
|
||||
int ret = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
|
||||
@@ -3937,19 +3976,22 @@ void uwsgi_uuid(char *buf) {
|
||||
uuid_generate(uuid_value);
|
||||
uuid_unparse(uuid_value, buf);
|
||||
#else
|
||||
int i,r[11];
|
||||
if (!uwsgi_file_exists("/dev/urandom")) goto fallback;
|
||||
int i, r[11];
|
||||
if (!uwsgi_file_exists("/dev/urandom"))
|
||||
goto fallback;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0) goto fallback;
|
||||
for(i=0;i<11;i++) {
|
||||
if (fd < 0)
|
||||
goto fallback;
|
||||
for (i = 0; i < 11; i++) {
|
||||
if (read(fd, &r[i], 4) != 4) {
|
||||
close(fd); goto fallback;
|
||||
close(fd);
|
||||
goto fallback;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
goto done;
|
||||
fallback:
|
||||
for(i=0;i<11;i++) {
|
||||
for (i = 0; i < 11; i++) {
|
||||
r[i] = rand();
|
||||
}
|
||||
done:
|
||||
@@ -4174,7 +4216,8 @@ char *uwsgi_str_to_hex(char *src, size_t slen) {
|
||||
char *ptr = dst;
|
||||
size_t i;
|
||||
for (i = 0; i < slen; i++) {
|
||||
memcpy(ptr, uwsgi_hex_table[(int) src[i]], 2);
|
||||
uint8_t pos = (uint8_t) src[i];
|
||||
memcpy(ptr, uwsgi_hex_table[pos], 2);
|
||||
ptr += 2;
|
||||
}
|
||||
return dst;
|
||||
@@ -4339,15 +4382,84 @@ void uwsgi_exit(int status) {
|
||||
}
|
||||
|
||||
int uwsgi_base128(struct uwsgi_buffer *ub, uint64_t l, int first) {
|
||||
if( l > 127 ) {
|
||||
if (uwsgi_base128(ub, l/128, 0)) return -1;
|
||||
if (l > 127) {
|
||||
if (uwsgi_base128(ub, l / 128, 0))
|
||||
return -1;
|
||||
}
|
||||
l %= 128;
|
||||
if(first) {
|
||||
if (uwsgi_buffer_u8(ub, (uint8_t) l)) return -1;
|
||||
if (first) {
|
||||
if (uwsgi_buffer_u8(ub, (uint8_t) l))
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_u8(ub, 0x80 | (uint8_t) l)) return -1;
|
||||
if (uwsgi_buffer_u8(ub, 0x80 | (uint8_t) l))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
void uwsgi_setns(char *path) {
|
||||
int (*u_setns) (int, int) = (int (*)(int, int)) dlsym(RTLD_DEFAULT, "setns");
|
||||
if (!u_setns) {
|
||||
uwsgi_log("your system misses setns() syscall !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// cound be overwritten
|
||||
int count = 64;
|
||||
|
||||
uwsgi_log("joining namespaces from %s ...\n", path);
|
||||
for (;;) {
|
||||
int ns_fd = uwsgi_connect(path, 30, 0);
|
||||
if (ns_fd < 0) {
|
||||
uwsgi_error("uwsgi_setns()/uwsgi_connect()");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
int *fds = uwsgi_attach_fd(ns_fd, &count, "uwsgi-setns", 11);
|
||||
if (fds && count > 0) {
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (fds[i] > -1) {
|
||||
if (u_setns(fds[i], 0) < 0) {
|
||||
uwsgi_error("uwsgi_setns()/setns()");
|
||||
exit(1);
|
||||
}
|
||||
close(fds[i]);
|
||||
}
|
||||
}
|
||||
free(fds);
|
||||
break;
|
||||
}
|
||||
if (fds)
|
||||
free(fds);
|
||||
close(ns_fd);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mode_t uwsgi_mode_t(char *value, int *error) {
|
||||
mode_t mode = 0;
|
||||
*error = 0;
|
||||
|
||||
if (strlen(value) < 3) {
|
||||
*error = 1;
|
||||
return mode;
|
||||
}
|
||||
|
||||
if (strlen(value) == 3) {
|
||||
mode = (mode << 3) + (value[0] - '0');
|
||||
mode = (mode << 3) + (value[1] - '0');
|
||||
mode = (mode << 3) + (value[2] - '0');
|
||||
}
|
||||
else {
|
||||
mode = (mode << 3) + (value[1] - '0');
|
||||
mode = (mode << 3) + (value[2] - '0');
|
||||
mode = (mode << 3) + (value[3] - '0');
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
+254
-92
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI ***
|
||||
|
||||
Copyright (C) 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright (C) 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -39,8 +39,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0},
|
||||
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"suwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"ssl-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"suwsgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"ssl-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
#endif
|
||||
|
||||
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0},
|
||||
@@ -71,18 +71,18 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
|
||||
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI, 0},
|
||||
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_int, &uwsgi.harakiri_options.workers, 0},
|
||||
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose, 0},
|
||||
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"no-harakiri-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"no-harakiri-after-req-hook", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"backtrace-depth", required_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
|
||||
{"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MULE_HARAKIRI, 0},
|
||||
{"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_int, &uwsgi.harakiri_options.mules, 0},
|
||||
#ifdef UWSGI_XML
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -99,10 +99,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"set-ph", required_argument, 0, "set a placeholder", uwsgi_opt_set_placeholder, (void *) 1, UWSGI_OPT_IMMEDIATE},
|
||||
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
|
||||
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"declare-option2", required_argument, 0, "declare a new uWSGI custom option (non-immediate)", uwsgi_opt_add_custom_option, NULL, 0},
|
||||
|
||||
{"resolve", required_argument, 0, "place the result of a dns query in the specified placeholder, sytax: placeholder=name (immediate option)", uwsgi_opt_resolve, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-readline", required_argument, 0, "(opt logic) for cycle (expand the specified file to a list of lines)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_readline, UWSGI_OPT_IMMEDIATE},
|
||||
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
@@ -116,6 +120,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_hostname, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_hostname, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -149,6 +156,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL, 0},
|
||||
{"include", required_argument, 0, "include the specified file as immediate configuration", uwsgi_opt_load, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"inject-before", required_argument, 0, "inject a text file before the config file (advanced templating)", uwsgi_opt_add_string_list, &uwsgi.inject_before, UWSGI_OPT_IMMEDIATE},
|
||||
{"inject-after", required_argument, 0, "inject a text file after the config file (advanced templating)", uwsgi_opt_add_string_list, &uwsgi.inject_after, UWSGI_OPT_IMMEDIATE},
|
||||
{"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
|
||||
{"daemonize2", required_argument, 0, "daemonize uWSGI after app loading", uwsgi_opt_set_str, &uwsgi.daemonize2, 0},
|
||||
{"stop", required_argument, 0, "stop an instance", uwsgi_opt_pidfile_signal, (void *) SIGINT, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -164,9 +173,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL, 0},
|
||||
{"max-apps", required_argument, 0, "set the maximum number of per-worker applications", uwsgi_opt_set_int, &uwsgi.max_apps, 0},
|
||||
{"buffer-size", required_argument, 'b', "set internal buffer size", uwsgi_opt_set_16bit, &uwsgi.buffer_size, 0},
|
||||
{"memory-report", no_argument, 'm', "enable memory report", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_MEMORY_DEBUG, 0},
|
||||
{"memory-report", no_argument, 'm', "enable memory report", uwsgi_opt_true, &uwsgi.logging_options.memory_report, 0},
|
||||
{"profiler", required_argument, 0, "enable the specified profiler", uwsgi_opt_set_str, &uwsgi.profiler, 0},
|
||||
{"cgi-mode", no_argument, 'c', "force CGI-mode for plugins supporting it", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_CGI_MODE, 0},
|
||||
{"cgi-mode", no_argument, 'c', "force CGI-mode for plugins supporting it", uwsgi_opt_true, &uwsgi.cgi_mode, 0},
|
||||
{"abstract-socket", no_argument, 'a', "force UNIX socket in abstract mode (Linux only)", uwsgi_opt_true, &uwsgi.abstract_socket, 0},
|
||||
{"chmod-socket", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL, 0},
|
||||
{"chmod", optional_argument, 'C', "chmod-socket", uwsgi_opt_chmod_socket, NULL, 0},
|
||||
@@ -215,6 +224,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-no-blacklist", no_argument, 0, "disable Emperor blacklisting subsystem", uwsgi_opt_true, &uwsgi.emperor_no_blacklist, 0},
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
@@ -231,6 +241,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"vassals-include-before", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes_before, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos", required_argument, 0, "ask emperor for reinforcement when overloaded", uwsgi_opt_set_int, &uwsgi.vassal_sos, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
{"vassals-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
{"vassal-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
@@ -239,6 +250,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"mule-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a mule can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.mule_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
@@ -248,12 +260,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"print-sym", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"print-symbol", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER, 0},
|
||||
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS, 0},
|
||||
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MIN_WORKER_LIFETIME, 0},
|
||||
{"max-worker-lifetime", required_argument, 0, "reload workers after the specified amount of seconds (default is disabled)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_WORKER_LIFETIME, 0},
|
||||
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_true, &uwsgi.reaper, 0},
|
||||
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_64bit, &uwsgi.max_requests, 0},
|
||||
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_64bit, &uwsgi.min_worker_lifetime, 0},
|
||||
{"max-worker-lifetime", required_argument, 0, "reload workers after the specified amount of seconds (default is disabled)", uwsgi_opt_set_64bit, &uwsgi.max_worker_lifetime, 0},
|
||||
|
||||
{"socket-timeout", required_argument, 'z', "set internal sockets timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SOCKET_TIMEOUT, 0},
|
||||
{"socket-timeout", required_argument, 'z', "set internal sockets timeout", uwsgi_opt_set_int, &uwsgi.socket_timeout, 0},
|
||||
{"no-fd-passing", no_argument, 0, "disable file descriptor passing", uwsgi_opt_true, &uwsgi.no_fd_passing, 0},
|
||||
{"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
|
||||
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
|
||||
@@ -297,7 +309,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, UWSGI_OPT_IMMEDIATE},
|
||||
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
|
||||
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
|
||||
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SPOOLER_HARAKIRI, 0},
|
||||
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_int, &uwsgi.harakiri_options.spoolers, 0},
|
||||
{"spooler-frequency", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
|
||||
{"spooler-freq", required_argument, 0, "set spooler frequency", uwsgi_opt_set_int, &uwsgi.spooler_frequency, 0},
|
||||
|
||||
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
|
||||
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -316,7 +330,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"rpc-max", required_argument, 0, "maximum number of rpc slots (default: 64)", uwsgi_opt_set_64bit, &uwsgi.rpc_max, 0},
|
||||
|
||||
{"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_dyn_false, (void *) UWSGI_OPTION_LOGGING, 0},
|
||||
{"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_false, &uwsgi.logging_options.enabled, 0},
|
||||
|
||||
{"flock", required_argument, 0, "lock the specified file before starting, exit if locked", uwsgi_opt_flock, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"flock-wait", required_argument, 0, "lock the specified file before starting, wait if locked", uwsgi_opt_flock_wait, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -344,7 +358,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#ifdef __linux__
|
||||
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
|
||||
{"unshare2", required_argument, 0, "unshare() part of the processes and put it in a new namespace after rootfs change", uwsgi_opt_set_unshare, &uwsgi.unshare2, 0},
|
||||
{"setns-socket", required_argument, 0, "expose a unix socket returning namespace fds from /proc/self/ns", uwsgi_opt_set_str, &uwsgi.setns_socket, UWSGI_OPT_MASTER},
|
||||
{"setns-socket-skip", required_argument, 0, "skip the specified entry when sending setns file descriptors", uwsgi_opt_add_string_list, &uwsgi.setns_socket_skip, 0},
|
||||
{"setns-skip", required_argument, 0, "skip the specified entry when sending setns file descriptors", uwsgi_opt_add_string_list, &uwsgi.setns_socket_skip, 0},
|
||||
{"setns", required_argument, 0, "join a namespace created by an external uWSGI instance", uwsgi_opt_set_str, &uwsgi.setns, 0},
|
||||
{"setns-preopen", no_argument, 0, "open /proc/self/ns as soon as possible and cache fds", uwsgi_opt_true, &uwsgi.setns_preopen, 0},
|
||||
#endif
|
||||
{"jailed", no_argument, 0, "mark the instance as jailed (force the execution of post_jail hooks)", uwsgi_opt_true, &uwsgi.jailed, 0},
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
{"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0},
|
||||
{"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0},
|
||||
@@ -378,11 +398,22 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
|
||||
{"hook-accepting1-once", required_argument, 0, "run the specified hook after the first worker enters the accepting phase (once per instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1_once, 0},
|
||||
|
||||
{"hook-master-start", required_argument, 0, "run the specified hook when the Master starts", uwsgi_opt_add_string_list, &uwsgi.hook_master_start, 0},
|
||||
|
||||
{"hook-touch", required_argument, 0, "run the specified hook when the specified file is touched (syntax: <file> <action>)", uwsgi_opt_add_string_list, &uwsgi.hook_touch, 0},
|
||||
|
||||
{"hook-emperor-start", required_argument, 0, "run the specified hook when the Emperor starts", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_start, 0},
|
||||
{"hook-emperor-stop", required_argument, 0, "run the specified hook when the Emperor send a stop message", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_stop, 0},
|
||||
{"hook-emperor-reload", required_argument, 0, "run the specified hook when the Emperor send a reload message", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_reload, 0},
|
||||
{"hook-emperor-lost", required_argument, 0, "run the specified hook when the Emperor connection is lost", uwsgi_opt_add_string_list, &uwsgi.hook_emperor_lost, 0},
|
||||
|
||||
{"hook-as-vassal", required_argument, 0, "run the specified hook before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
|
||||
{"hook-as-emperor", required_argument, 0, "run the specified hook in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
|
||||
|
||||
{"hook-as-mule", required_argument, 0, "run the specified hook in each mule", uwsgi_opt_add_string_list, &uwsgi.hook_as_mule, 0},
|
||||
|
||||
{"hook-as-gateway", required_argument, 0, "run the specified hook in each gateway", uwsgi_opt_add_string_list, &uwsgi.hook_as_gateway, 0},
|
||||
|
||||
{"after-request-hook", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
{"after-request-call", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
|
||||
@@ -532,10 +563,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"metric", required_argument, 0, "add a custom metric", uwsgi_opt_add_string_list, &uwsgi.additional_metrics, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-threshold", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-alarm", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"alarm-metric", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-no-cores", no_argument, 0, "disable generation of cores-related metrics", uwsgi_opt_true, &uwsgi.metrics_no_cores, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
|
||||
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
|
||||
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
@@ -546,18 +579,24 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER|UWSGI_OPT_METRICS},
|
||||
{"stats-pusher-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-pushers-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-no-cores", no_argument, 0, "disable generation of cores-related stats", uwsgi_opt_true, &uwsgi.stats_no_cores, UWSGI_OPT_MASTER},
|
||||
{"stats-no-metrics", no_argument, 0, "do not include metrics in stats output", uwsgi_opt_true, &uwsgi.stats_no_metrics, UWSGI_OPT_MASTER},
|
||||
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
|
||||
|
||||
{"master-fifo", required_argument, 0, "enable the master fifo", uwsgi_opt_add_string_list, &uwsgi.master_fifo, UWSGI_OPT_MASTER},
|
||||
|
||||
{"notify-socket", required_argument, 0, "enable the notification socket", uwsgi_opt_set_str, &uwsgi.notify_socket, UWSGI_OPT_MASTER},
|
||||
{"subscription-notify-socket", required_argument, 0, "set the notification socket for subscriptions", uwsgi_opt_set_str, &uwsgi.subscription_notify_socket, UWSGI_OPT_MASTER},
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
|
||||
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
|
||||
{"legion-death-on-lord-error", required_argument, 0, "declare itself as a dead node for the specified amount of seconds if one of the lord hooks fails", uwsgi_opt_set_int, &uwsgi.legion_death_on_lord_error, UWSGI_OPT_MASTER},
|
||||
{"legion-skew-tolerance", required_argument, 0, "set the clock skew tolerance of legion subsystem (default 30 seconds)", uwsgi_opt_set_int, &uwsgi.legion_skew_tolerance, UWSGI_OPT_MASTER},
|
||||
{"legion-lord", required_argument, 0, "action to call on Lord election", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -572,7 +611,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-skip-uid", required_argument, 0, "skip signature check for the specified uid when using unix sockets credentials", uwsgi_opt_add_string_list, &uwsgi.subscriptions_sign_skip_uid, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"subscriptions-credentials-check", required_argument, 0, "add a directory to search for subscriptions key credentials", uwsgi_opt_add_string_list, &uwsgi.subscriptions_credentials_check_dir, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-use-credentials", no_argument, 0, "enable management of SCM_CREDENTIALS in subscriptions UNIX sockets", uwsgi_opt_true, &uwsgi.subscriptions_use_credentials, 0},
|
||||
{"subscription-algo", required_argument, 0, "set load balancing algorithm for the subscription system", uwsgi_opt_ssa, NULL, 0},
|
||||
{"subscription-dotsplit", no_argument, 0, "try to fallback to the next part (dot based) in subscription key", uwsgi_opt_true, &uwsgi.subscription_dotsplit, 0},
|
||||
{"subscribe-to", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
|
||||
@@ -582,6 +624,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"subscribe-freq", required_argument, 0, "send subscription announce at the specified interval", uwsgi_opt_set_int, &uwsgi.subscribe_freq, 0},
|
||||
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
|
||||
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
|
||||
{"start-unsubscribed", no_argument, 0, "configure subscriptions but do not send them (useful with master fifo)", uwsgi_opt_true, &uwsgi.subscriptions_blocked, 0},
|
||||
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
|
||||
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -597,8 +640,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#ifdef UWSGI_PCRE
|
||||
{"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
|
||||
#endif
|
||||
{"ssl-tmp-dir", required_argument, 0, "store ssl-related temp files in the specified directory", uwsgi_opt_set_str, &uwsgi.ssl_tmp_dir, 0},
|
||||
#endif
|
||||
{"check-interval", required_argument, 0, "set the interval (in seconds) of master checks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MASTER_INTERVAL, 0},
|
||||
{"check-interval", required_argument, 0, "set the interval (in seconds) of master checks", uwsgi_opt_set_int, &uwsgi.master_interval, UWSGI_OPT_MASTER},
|
||||
{"forkbomb-delay", required_argument, 0, "sleep for the specified number of seconds when a forkbomb is detected", uwsgi_opt_set_int, &uwsgi.forkbomb_delay, UWSGI_OPT_MASTER},
|
||||
{"binary-path", required_argument, 0, "force binary path", uwsgi_opt_set_str, &uwsgi.binary_path, 0},
|
||||
{"privileged-binary-patch", required_argument, 0, "patch the uwsgi binary with a new command (before privileges drop)", uwsgi_opt_set_str, &uwsgi.privileged_binary_patch, 0},
|
||||
@@ -639,10 +683,17 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-cheap", required_argument, 0, "use main alarm thread rather than create dedicated threads for curl-based alarms", uwsgi_opt_true, &uwsgi.alarm_cheap, 0},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"segfault-alarm", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"alarm-backlog", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"backlog-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"lq-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"alarm-lq", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"alarm-listen-queue", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
{"listen-queue-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -652,28 +703,28 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarm-msg-size", required_argument, 0, "set the max size of an alarm message (default 8192)", uwsgi_opt_set_64bit, &uwsgi.alarm_msg_size, 0},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
|
||||
|
||||
{"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
|
||||
{"log-date", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
|
||||
{"log-prefix", optional_argument, 0, "prefix logs with a string", uwsgi_opt_log_date, NULL, 0},
|
||||
|
||||
{"log-zero", no_argument, 0, "log responses without body", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_ZERO, 0},
|
||||
{"log-slow", required_argument, 0, "log requests slower than the specified number of milliseconds", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_SLOW, 0},
|
||||
{"log-4xx", no_argument, 0, "log requests with a 4xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_4xx, 0},
|
||||
{"log-5xx", no_argument, 0, "log requests with a 5xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_5xx, 0},
|
||||
{"log-big", required_argument, 0, "log requestes bigger than the specified size", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_BIG, 0},
|
||||
{"log-sendfile", required_argument, 0, "log sendfile requests", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_SENDFILE, 0},
|
||||
{"log-ioerror", required_argument, 0, "log requests with io errors", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_IOERROR, 0},
|
||||
{"log-zero", no_argument, 0, "log responses without body", uwsgi_opt_true, &uwsgi.logging_options.zero, 0},
|
||||
{"log-slow", required_argument, 0, "log requests slower than the specified number of milliseconds", uwsgi_opt_set_int, &uwsgi.logging_options.slow, 0},
|
||||
{"log-4xx", no_argument, 0, "log requests with a 4xx response", uwsgi_opt_true, &uwsgi.logging_options._4xx, 0},
|
||||
{"log-5xx", no_argument, 0, "log requests with a 5xx response", uwsgi_opt_true, &uwsgi.logging_options._5xx, 0},
|
||||
{"log-big", required_argument, 0, "log requestes bigger than the specified size", uwsgi_opt_set_64bit, &uwsgi.logging_options.big, 0},
|
||||
{"log-sendfile", required_argument, 0, "log sendfile requests", uwsgi_opt_true, &uwsgi.logging_options.sendfile, 0},
|
||||
{"log-ioerror", required_argument, 0, "log requests with io errors", uwsgi_opt_true, &uwsgi.logging_options.ioerror, 0},
|
||||
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
|
||||
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
|
||||
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.logging_options.log_x_forwarded_for, 0},
|
||||
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
|
||||
|
||||
{"drop-after-init", no_argument, 0, "run privileges drop after plugin initialization", uwsgi_opt_true, &uwsgi.drop_after_init, 0},
|
||||
@@ -688,7 +739,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cheap", no_argument, 0, "set cheap mode (spawn workers only after the first request)", uwsgi_opt_true, &uwsgi.status.is_cheap, UWSGI_OPT_MASTER},
|
||||
{"cheaper", required_argument, 0, "set cheaper mode (adaptive process spawning)", uwsgi_opt_set_int, &uwsgi.cheaper_count, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-initial", required_argument, 0, "set the initial number of processes to spawn in cheaper mode", uwsgi_opt_set_int, &uwsgi.cheaper_initial, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning)", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
|
||||
{"cheaper-algo", required_argument, 0, "choose to algorithm used for adaptive process spawning", uwsgi_opt_set_str, &uwsgi.requested_cheaper_algo, UWSGI_OPT_MASTER},
|
||||
{"cheaper-step", required_argument, 0, "number of additional processes to spawn at each overload", uwsgi_opt_set_int, &uwsgi.cheaper_step, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-overload", required_argument, 0, "increase workers after specified overload", uwsgi_opt_set_64bit, &uwsgi.cheaper_overload, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-algo-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
@@ -848,7 +899,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"disable-sendfile", no_argument, 0, "disable sendfile() and rely on boring read()/write()", uwsgi_opt_true, &uwsgi.disable_sendfile, 0},
|
||||
|
||||
{"check-cache", optional_argument, 0, "check for response data in the specified cache (empty for default cache)", uwsgi_opt_set_str, &uwsgi.use_check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on connection sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"close-on-exec2", no_argument, 0, "set close-on-exec on server sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec2, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
|
||||
@@ -901,6 +953,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-smart-attach-daemon2", required_argument, 0, "same as --smart-attach-daemon2 but daemon runs only on legion lord node", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"attach-daemon2", required_argument, 0, "attach-daemon keyval variant (supports smart modes too)", uwsgi_opt_add_daemon2, NULL, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"need-plugins", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -985,6 +1038,17 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
magic_table['b'] = uwsgi.binary_path;
|
||||
magic_table['p'] = fullname;
|
||||
|
||||
// compute filename hash
|
||||
uint32_t hash = djb33x_hash(magic_table['p'], strlen(magic_table['p']));
|
||||
char *hex = uwsgi_str_to_hex((char *)&hash, 4);
|
||||
magic_table['j'] = uwsgi_concat2n(hex, 8, "", 0);
|
||||
free(hex);
|
||||
|
||||
struct stat st;
|
||||
if (!lstat(fullname, &st)) {
|
||||
magic_table['i'] = uwsgi_num2str(st.st_ino);
|
||||
}
|
||||
|
||||
magic_table['s'] = uwsgi_get_last_char(fullname, '/') + 1;
|
||||
|
||||
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
|
||||
@@ -1057,6 +1121,8 @@ reuse:
|
||||
magic_table['E'] = magic_table['e'];
|
||||
magic_table['N'] = magic_table['n'];
|
||||
magic_table['X'] = magic_table['x'];
|
||||
magic_table['I'] = magic_table['i'];
|
||||
magic_table['J'] = magic_table['j'];
|
||||
uwsgi.magic_table_first_round = 1;
|
||||
}
|
||||
|
||||
@@ -1193,6 +1259,11 @@ void kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1214,6 +1285,11 @@ void gracefully_kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1255,6 +1331,12 @@ void grace_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
@@ -1301,6 +1383,11 @@ void reap_them_all(int signum) {
|
||||
if (uwsgi.workers[i].pid > 0)
|
||||
uwsgi_curse(i, SIGTERM);
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void harakiri() {
|
||||
@@ -1362,7 +1449,7 @@ void what_i_am_doing() {
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
|
||||
#endif
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
|
||||
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d core %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, i, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
else {
|
||||
@@ -1379,14 +1466,14 @@ void what_i_am_doing() {
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
|
||||
#endif
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
|
||||
if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now()) {
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("SIGUSR2: --- uWSGI worker %d (pid: %d) is managing request %.*s since %.*s ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, wsgi_req->uri_len, wsgi_req->uri, 24, ctime_storage);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now() && uwsgi.workers[uwsgi.mywid].sig) {
|
||||
else if (uwsgi.harakiri_options.workers > 0 && uwsgi.workers[uwsgi.mywid].harakiri < uwsgi_now() && uwsgi.workers[uwsgi.mywid].sig) {
|
||||
uwsgi_log("HARAKIRI: --- uWSGI worker %d (pid: %d) WAS handling signal %d ---\n", (int) uwsgi.mywid, (int) uwsgi.mypid, uwsgi.workers[uwsgi.mywid].signum);
|
||||
}
|
||||
}
|
||||
@@ -1497,25 +1584,40 @@ static void vacuum(void) {
|
||||
next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
if (uwsgi.stats) {
|
||||
// is a unix socket ?
|
||||
if (!strchr(uwsgi.stats, ':') && uwsgi.stats[0] != '@') {
|
||||
if (unlink(uwsgi.stats)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("VACUUM: unix socket %s (stats) removed.\n", uwsgi.stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void signal_pidfile(int sig, char *filename) {
|
||||
int signal_pidfile(int sig, char *filename) {
|
||||
|
||||
int ret = 0;
|
||||
size_t size = 0;
|
||||
|
||||
char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
|
||||
if (size > 0) {
|
||||
if (kill((pid_t) atoi(buffer), sig)) {
|
||||
uwsgi_error("kill()");
|
||||
uwsgi_error("signal_pidfile()/kill()");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("error: invalid pidfile\n");
|
||||
ret = -1;
|
||||
}
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/ void uwsgi_command_signal(char *opt) {
|
||||
@@ -1862,6 +1964,17 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
return uwsgi_run();
|
||||
}
|
||||
|
||||
static char *uwsgi_at_file_read(char *filename) {
|
||||
size_t size = 0;
|
||||
char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
if (size > 1) {
|
||||
if (buffer[size-2] == '\n' || buffer[size-2] == '\r') {
|
||||
buffer[size-2] = 0;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
#ifdef __APPLE__
|
||||
@@ -2036,6 +2149,12 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
uwsgi.magic_table['k'] = uwsgi_num2str(uwsgi.cpus);
|
||||
uwsgi.magic_table['['] = "\033";
|
||||
uwsgi.magic_table['u'] = uwsgi_num2str((int)getuid());
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
uwsgi.magic_table['U'] = pw ? pw->pw_name : uwsgi.magic_table['u'];
|
||||
uwsgi.magic_table['g'] = uwsgi_num2str((int)getgid());
|
||||
struct group *gr = getgrgid(getgid());
|
||||
uwsgi.magic_table['G'] = gr ? gr->gr_name : uwsgi.magic_table['g'];
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -2053,7 +2172,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_apply_config_pass('$', (char *(*)(char *)) getenv);
|
||||
|
||||
// third pass: FILEs
|
||||
uwsgi_apply_config_pass('@', uwsgi_simple_file_read);
|
||||
uwsgi_apply_config_pass('@', uwsgi_at_file_read);
|
||||
|
||||
// last pass: REFERENCEs
|
||||
uwsgi_apply_config_pass('%', uwsgi_manage_placeholder);
|
||||
@@ -2127,7 +2246,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
|
||||
|
||||
// setup master logging
|
||||
if (uwsgi.log_master && !uwsgi.daemonize2)
|
||||
if (uwsgi.log_master)
|
||||
uwsgi_setup_log_master();
|
||||
|
||||
// setup offload engines
|
||||
@@ -2268,6 +2387,16 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
// initialize shared sockets
|
||||
uwsgi_setup_shared_sockets();
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi.setns_preopen) {
|
||||
uwsgi_setns_preopen();
|
||||
}
|
||||
// eventually join a linux namespace
|
||||
if (uwsgi.setns) {
|
||||
uwsgi_setns(uwsgi.setns);
|
||||
}
|
||||
#endif
|
||||
|
||||
// start the Emperor if needed
|
||||
if (uwsgi.early_emperor && uwsgi.emperor) {
|
||||
uwsgi_emperor_start();
|
||||
@@ -2702,7 +2831,11 @@ int uwsgi_start(void *v_argv) {
|
||||
!uwsgi.command_mode &&
|
||||
!uwsgi.daemons_cnt &&
|
||||
!uwsgi.crons &&
|
||||
!uwsgi.spoolers &&
|
||||
!uwsgi.emperor_proxy
|
||||
#ifdef __linux__
|
||||
&& !uwsgi.setns_socket
|
||||
#endif
|
||||
#ifdef UWSGI_SSL
|
||||
&& !uwsgi.legions
|
||||
#endif
|
||||
@@ -2857,7 +2990,7 @@ unsafe:
|
||||
}
|
||||
|
||||
// initialize locks and socket as soon as possible, as the master could enqueue tasks
|
||||
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
|
||||
if (uwsgi.spoolers != NULL) {
|
||||
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -2995,15 +3128,13 @@ next:
|
||||
|
||||
|
||||
|
||||
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->mode == UWSGI_SPOOLER_EXTERNAL)
|
||||
goto next2;
|
||||
uspool->pid = spooler_start(uspool);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->mode == UWSGI_SPOOLER_EXTERNAL)
|
||||
goto next2;
|
||||
uspool->pid = spooler_start(uspool);
|
||||
next2:
|
||||
uspool = uspool->next;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process) {
|
||||
@@ -3079,6 +3210,16 @@ int uwsgi_run() {
|
||||
//from now on the process is a real worker
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(PR_SET_PDEATHSIG)
|
||||
// avoid workers running without master at all costs !!! (dangerous)
|
||||
if (uwsgi.master_process && uwsgi.no_orphans) {
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL)) {
|
||||
uwsgi_error("uwsgi_run()/prctl()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// eventually maps (or disable) sockets for the worker
|
||||
uwsgi_map_sockets();
|
||||
|
||||
@@ -3193,7 +3334,7 @@ void uwsgi_worker_run() {
|
||||
}
|
||||
|
||||
// setup UNIX signals for the worker
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) {
|
||||
if (uwsgi.harakiri_options.workers > 0 && !uwsgi.master_process) {
|
||||
signal(SIGALRM, (void *) &harakiri);
|
||||
}
|
||||
uwsgi_unix_signal(SIGHUP, gracefully_kill);
|
||||
@@ -3570,6 +3711,13 @@ void uwsgi_init_all_apps() {
|
||||
if (uwsgi.need_app) {
|
||||
if (!uwsgi.lazy)
|
||||
uwsgi_log("*** no app loaded. GAME OVER ***\n");
|
||||
if (uwsgi.lazy_apps) {
|
||||
if (uwsgi.master_process) {
|
||||
if (kill(uwsgi.workers[0].pid, SIGINT)) {
|
||||
uwsgi_error("kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
else {
|
||||
@@ -3638,8 +3786,20 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_false(char *opt, char *value, void *key) {
|
||||
|
||||
int *ptr = (int *) key;
|
||||
*ptr = 0;
|
||||
if (value) {
|
||||
if (!strcasecmp("false", value) || !strcasecmp("off", value) || !strcasecmp("no", value) || !strcmp("0", value)) {
|
||||
*ptr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
@@ -3668,7 +3828,8 @@ void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
@@ -3714,6 +3875,44 @@ void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_uid(char *opt, char *value, void *key) {
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (!uid) {
|
||||
struct passwd *p = getpwnam(value);
|
||||
if (p) {
|
||||
uid = p->pw_uid;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find user %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (key) {
|
||||
uid_t *ptr = (uid_t *) key;
|
||||
*ptr = uid;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_gid(char *opt, char *value, void *key) {
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (!gid) {
|
||||
struct group *g = getgrnam(value);
|
||||
if (g) {
|
||||
gid = g->gr_gid;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find group %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (key) {
|
||||
gid_t *ptr = (gid_t *) key;
|
||||
*ptr = gid;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_rawint(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
@@ -3755,27 +3954,6 @@ void uwsgi_opt_set_megabytes(char *opt, char *value, void *key) {
|
||||
*ptr = (uint64_t)strtoul(value, NULL, 10) * 1024 * 1024;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_dyn(char *opt, char *value, void *key) {
|
||||
|
||||
long *fake_ptr = (long *) key;
|
||||
uint8_t dyn_opt_id = (long) fake_ptr;
|
||||
uwsgi.shared->options[dyn_opt_id] = atoi(value);
|
||||
}
|
||||
|
||||
void uwsgi_opt_dyn_true(char *opt, char *value, void *key) {
|
||||
|
||||
long *fake_ptr = (long *) key;
|
||||
uint8_t dyn_opt_id = (long) fake_ptr;
|
||||
uwsgi.shared->options[dyn_opt_id] = 1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_dyn_false(char *opt, char *value, void *key) {
|
||||
|
||||
long *fake_ptr = (long *) key;
|
||||
uint8_t dyn_opt_id = (long) fake_ptr;
|
||||
uwsgi.shared->options[dyn_opt_id] = 0;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_str(char *opt, char *value, void *key) {
|
||||
char **ptr = (char **) key;
|
||||
if (!value) {
|
||||
@@ -3992,27 +4170,14 @@ void uwsgi_opt_scd(char *opt, char *value, void *foobar) {
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_set_umask(char *opt, char *value, void *mode) {
|
||||
|
||||
mode_t umask_mode = 0;
|
||||
|
||||
if (strlen(value) < 3) {
|
||||
int error = 0;
|
||||
mode_t mask = uwsgi_mode_t(value, &error);
|
||||
if (error) {
|
||||
uwsgi_log("invalid umask: %s\n", value);
|
||||
}
|
||||
umask_mode = 0;
|
||||
if (strlen(value) == 3) {
|
||||
umask_mode = (umask_mode << 3) + (value[0] - '0');
|
||||
umask_mode = (umask_mode << 3) + (value[1] - '0');
|
||||
umask_mode = (umask_mode << 3) + (value[2] - '0');
|
||||
}
|
||||
else {
|
||||
umask_mode = (umask_mode << 3) + (value[1] - '0');
|
||||
umask_mode = (umask_mode << 3) + (value[2] - '0');
|
||||
umask_mode = (umask_mode << 3) + (value[3] - '0');
|
||||
}
|
||||
umask(umask_mode);
|
||||
umask(mask);
|
||||
|
||||
uwsgi.do_not_change_umask = 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_exit(char *opt, char *value, void *none) {
|
||||
@@ -4032,15 +4197,13 @@ void uwsgi_opt_print(char *opt, char *value, void *str) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_uid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.uid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.uid = atoi(value);
|
||||
if (!uwsgi.uid)
|
||||
uwsgi.uidname = value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.gid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.gid = atoi(value);
|
||||
if (!uwsgi.gid)
|
||||
uwsgi.gidname = value;
|
||||
}
|
||||
@@ -4087,8 +4250,7 @@ void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
|
||||
long *signum_fake_ptr = (long *) sig;
|
||||
int signum = (long) signum_fake_ptr;
|
||||
signal_pidfile(signum, pidfile);
|
||||
exit(0);
|
||||
exit(signal_pidfile(signum, pidfile));
|
||||
}
|
||||
|
||||
void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
|
||||
+32
-9
@@ -1,4 +1,4 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define REQ_DATA wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
|
||||
struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf;
|
||||
if (!ub) {
|
||||
@@ -61,7 +63,7 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
|
||||
// pong not received ?
|
||||
if (wsgi_req->websocket_last_pong < wsgi_req->websocket_last_ping) {
|
||||
if (wsgi_req->websocket_last_ping - wsgi_req->websocket_last_pong > uwsgi.websockets_pong_tolerance) {
|
||||
uwsgi_log("[uwsgi-websocket] no PONG received in %d seconds !!!\n", uwsgi.websockets_pong_tolerance);
|
||||
uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) no PONG received in %d seconds !!!\n", REQ_DATA, uwsgi.websockets_pong_tolerance);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -189,7 +191,7 @@ static ssize_t uwsgi_websockets_recv_pkt(struct wsgi_request *wsgi_req, int nb)
|
||||
}
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_websockets_recv_pkt()");
|
||||
uwsgi_req_error("uwsgi_websockets_recv_pkt()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -201,7 +203,7 @@ wait:
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_websockets_recv_pkt()");
|
||||
uwsgi_req_error("uwsgi_websockets_recv_pkt()");
|
||||
return -1;
|
||||
}
|
||||
// send unsolicited pong
|
||||
@@ -254,11 +256,11 @@ static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_re
|
||||
wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
|
||||
uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) BUG error in websocket parser\n", REQ_DATA);
|
||||
return NULL;
|
||||
}
|
||||
if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) {
|
||||
uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024);
|
||||
uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) invalid packet size received: %llu, max allowed: %llu\n", REQ_DATA, wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024);
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->websocket_phase = 2;
|
||||
@@ -312,7 +314,7 @@ static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_re
|
||||
break;
|
||||
// oops
|
||||
default:
|
||||
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
|
||||
uwsgi_log("[uwsgi-websocket] \"%.*s %.*s\" (%.*s) BUG error in websocket parser\n", REQ_DATA);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -367,18 +369,39 @@ ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len, char *proto, uint16_t proto_len) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (!key_len) {
|
||||
key = wsgi_req->http_sec_websocket_key;
|
||||
key_len = wsgi_req->http_sec_websocket_key_len;
|
||||
}
|
||||
if (key_len == 0) return -1;
|
||||
|
||||
char sha1[20];
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
|
||||
if (origin_len > 0) {
|
||||
|
||||
// if origin was requested or proto_len is specified, send it back
|
||||
if (wsgi_req->http_origin_len > 0 || origin_len > 0) {
|
||||
if (!origin_len) {
|
||||
origin = wsgi_req->http_origin;
|
||||
origin_len = wsgi_req->http_origin_len;
|
||||
}
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
|
||||
}
|
||||
|
||||
// if protocol was requested or proto_len is specified, send it back
|
||||
if (wsgi_req->http_sec_websocket_protocol_len > 0 || proto_len > 0) {
|
||||
if (!proto_len) {
|
||||
proto = wsgi_req->http_sec_websocket_protocol;
|
||||
proto_len = wsgi_req->http_sec_websocket_protocol_len;
|
||||
}
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Protocol", 22, proto, proto_len)) return -1;
|
||||
}
|
||||
// generate websockets sha1 and encode it to base64
|
||||
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
|
||||
size_t b64_len = 0;
|
||||
|
||||
+33
-25
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
|
||||
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t sta
|
||||
end = cl-1;
|
||||
}
|
||||
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
if (ret <= 0 || ret >= (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -82,12 +82,14 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply error routes
|
||||
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
if (wsgi_req->is_error_routing == 0) {
|
||||
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_error_routing = 0;
|
||||
}
|
||||
wsgi_req->is_error_routing = 0;
|
||||
#endif
|
||||
if (status_len <= 4) {
|
||||
char *new_sc = NULL;
|
||||
@@ -186,12 +188,14 @@ static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
if (wsgi_req->is_response_routing == 0) {
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
@@ -352,12 +356,14 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
if (wsgi_req->is_response_routing == 0) {
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -435,12 +441,14 @@ int uwsgi_response_writev_body_do(struct wsgi_request *wsgi_req, struct iovec *i
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
if (wsgi_req->is_response_routing == 0) {
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,16 +42,6 @@ def application(env, start_response):
|
||||
|
||||
yield '<h2>dynamic options</h2>'
|
||||
|
||||
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
|
||||
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
|
||||
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
|
||||
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
|
||||
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
|
||||
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
|
||||
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
|
||||
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
|
||||
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
|
||||
|
||||
yield '<table border="1">'
|
||||
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
|
||||
|
||||
|
||||
@@ -47,11 +47,6 @@ def serve_logo(e, sr):
|
||||
uwsgi.sendfile('logo_uWSGI.png')
|
||||
return ''
|
||||
|
||||
def serve_options(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in range(0,256):
|
||||
yield "<b>%d</b> = %d<br/>" % (opt, uwsgi.get_option(opt))
|
||||
|
||||
def serve_config(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in uwsgi.opt.keys():
|
||||
@@ -61,7 +56,6 @@ routes = {}
|
||||
routes['/xsendfile'] = xsendfile
|
||||
routes['/logo'] = serve_logo
|
||||
routes['/config'] = serve_config
|
||||
routes['/options'] = serve_options
|
||||
|
||||
@postfork
|
||||
def setprocname():
|
||||
@@ -119,11 +113,6 @@ def application(env, start_response):
|
||||
Configuration<br/>
|
||||
<iframe src="/config"></iframe><br/>
|
||||
|
||||
<br/>
|
||||
|
||||
Dynamic options<br/>
|
||||
<iframe src="/options"></iframe><br/>
|
||||
|
||||
<br/>
|
||||
Workers and applications<br/>
|
||||
<table border="1">
|
||||
|
||||
@@ -9,12 +9,6 @@ def serve_logo(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'image/png')])
|
||||
return uwsgi.sendfile('logo_uWSGI.png')
|
||||
|
||||
def serve_options(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in range(0,256):
|
||||
body = "{opt} = {optvalue}<br/>".format(opt=opt, optvalue=uwsgi.get_option(opt))
|
||||
yield bytes(body.encode('ascii'))
|
||||
|
||||
def serve_config(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in uwsgi.opt.keys():
|
||||
@@ -25,7 +19,6 @@ routes = {}
|
||||
routes['/xsendfile'] = xsendfile
|
||||
routes['/logo'] = serve_logo
|
||||
routes['/config'] = serve_config
|
||||
routes['/options'] = serve_options
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
@@ -43,9 +36,6 @@ Configuration<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
Dynamic options<br/>
|
||||
<iframe src="/options"></iframe><br/>
|
||||
|
||||
""".format(version=uwsgi.version.decode('ascii'))
|
||||
|
||||
return bytes(body.encode('ascii'))
|
||||
|
||||
+4
-1
@@ -61,6 +61,7 @@ void linux_namespace_start(void *argv) {
|
||||
for (;;) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
int waitpid_status;
|
||||
char *pid_str = NULL;
|
||||
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
|
||||
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
|
||||
if (uwsgi.ns_net) {
|
||||
@@ -77,10 +78,12 @@ void linux_namespace_start(void *argv) {
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
pid_str = uwsgi_num2str((int) pid);
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
if (setenv("UWSGI_JAIL_PID", pid_str, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
free(pid_str);
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* uwsgi ADMIN|10 */
|
||||
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint32_t opt_value = 0;
|
||||
|
||||
if (wsgi_req->uh->pktsize != 0 && wsgi_req->uh->pktsize != 4)
|
||||
return UWSGI_OK;
|
||||
|
||||
// write request
|
||||
if (wsgi_req->uh->pktsize == 4) {
|
||||
memcpy(&opt_value, wsgi_req->buffer, 4);
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh->modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh->modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh->modifier1 = 255;
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
}
|
||||
// get request
|
||||
else {
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh->modifier2, uwsgi.shared->options[wsgi_req->uh->modifier2]);
|
||||
|
||||
wsgi_req->uh->modifier1 = 10;
|
||||
wsgi_req->uh->pktsize = 4;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uwsgi.shared->options[wsgi_req->uh->modifier2], 4);
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin admin_plugin = {
|
||||
|
||||
.name = "admin",
|
||||
.modifier1 = 10,
|
||||
.request = uwsgi_request_admin,
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
NAME='admin'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['admin_plugin']
|
||||
@@ -222,8 +222,8 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
@@ -271,12 +271,11 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_airbrake_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_airbrake_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_airbrake_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_airbrake_loop, uacc);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
|
||||
@@ -3,9 +3,18 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_alarm_curl {
|
||||
CURL *curl;
|
||||
struct uwsgi_thread *ut;
|
||||
int pos;
|
||||
int blen;
|
||||
char *body;
|
||||
int hlen;
|
||||
char hdr[];
|
||||
};
|
||||
|
||||
struct uwsgi_alarm_curl_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *url;
|
||||
char *subject;
|
||||
char *to;
|
||||
};
|
||||
@@ -17,7 +26,7 @@ struct uwsgi_alarm_curl_opt {
|
||||
};
|
||||
|
||||
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
#ifdef CURLPROTO_SMTP
|
||||
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->to = arg;
|
||||
struct curl_slist *list = NULL;
|
||||
@@ -29,6 +38,7 @@ static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
curl_easy_setopt(curl, option, list);
|
||||
free(items);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -44,16 +54,33 @@ static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *ar
|
||||
uacc->subject = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
|
||||
static void uwsgi_alarm_curl_url(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
#ifndef CURLPROTO_SMTP
|
||||
if (!uwsgi_strnicmp(arg, 4, "smtp", 4)) {
|
||||
uwsgi_error("Please update libcurl to use SMTP protocol.\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef CURLOPT_MAIL_FROM
|
||||
uacc->url = arg;
|
||||
curl_easy_setopt(curl, option, arg);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_ssl_insecure(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, uwsgi_alarm_curl_url},
|
||||
#ifdef CURLPROTO_SMTP
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to},
|
||||
{"mail_from", CURLOPT_MAIL_FROM, NULL},
|
||||
#endif
|
||||
{"subject", 0, uwsgi_alarm_curl_set_subject},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
|
||||
{"ssl_insecure", 0, uwsgi_alarm_curl_ssl_insecure},
|
||||
{"auth_user", CURLOPT_USERNAME, NULL},
|
||||
{"auth_pass", CURLOPT_PASSWORD, NULL},
|
||||
{"method", CURLOPT_CUSTOMREQUEST, NULL},
|
||||
@@ -65,14 +92,10 @@ static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
|
||||
struct uwsgi_alarm_curl_opt *o = uaco;
|
||||
char *equal = strchr(opt,'=');
|
||||
if (!equal) {
|
||||
if (!uacc->first) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, opt);
|
||||
uacc->first = 1;
|
||||
}
|
||||
if (!equal && !uacc->url) {
|
||||
uwsgi_alarm_curl_url(curl, CURLOPT_URL, opt, uacc);
|
||||
return;
|
||||
}
|
||||
uacc->first = 1;
|
||||
*equal = 0;
|
||||
while(o->name) {
|
||||
if (!strcmp(o->name, opt)) {
|
||||
@@ -82,91 +105,137 @@ static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_cu
|
||||
else {
|
||||
curl_easy_setopt(curl, o->option, equal+1);
|
||||
}
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
struct uwsgi_alarm_curl *uac = userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
struct uwsgi_alarm_curl_config *uacc = ut->data;
|
||||
int remains = full_size;
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr+=4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
if (uac->pos < uac->hlen) {
|
||||
if (remains > uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->hdr + uac->pos, uac->hlen - uac->pos);
|
||||
ptr += uac->hlen - uac->pos;
|
||||
remains -= uac->hlen - uac->pos;
|
||||
uac->pos = uac->hlen;
|
||||
} else {
|
||||
memcpy(ptr, uac->hdr + uac->pos, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr+=9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
}
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
if (remains > uac->blen + uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, uac->blen + uac->hlen - uac->pos);
|
||||
remains -= uac->blen + uac->hlen - uac->pos;
|
||||
uac->pos = uac->blen + uac->hlen;
|
||||
return full_size - remains;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_alloc(struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
char *addr;
|
||||
struct uwsgi_alarm_curl *uac;
|
||||
size_t required = 0;
|
||||
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 2;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 2;
|
||||
if (required)
|
||||
required += 2; /* newline between MIME header and body */
|
||||
|
||||
uac = uwsgi_malloc(sizeof(*uac) + required);
|
||||
uac->hlen = required;
|
||||
addr = uac->hdr;
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr += 4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr += 9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (required) {
|
||||
*addr++ = '\r';
|
||||
*addr = '\n';
|
||||
}
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_init_curl(struct uwsgi_alarm_instance *uai) {
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
if (!curl) {
|
||||
uwsgi_error("Failed to initialize libcurl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
struct uwsgi_alarm_curl_config uacc;
|
||||
memset(&uacc, 0, sizeof(uacc));
|
||||
char *opts = uwsgi_str(uai->arg);
|
||||
|
||||
// fill curl options
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
|
||||
uwsgi_alarm_curl_setopt(curl, p, &uacc);
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
if (!uacc.url) {
|
||||
uwsgi_error("An URL is required to trigger curl-based alarm.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_alloc(&uacc);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, uac);
|
||||
free(opts);
|
||||
uac->curl = curl;
|
||||
uai->data_ptr = uac;
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_call_curl(struct uwsgi_alarm_curl *uac, char *msg, int len)
|
||||
{
|
||||
uac->pos = 0;
|
||||
uac->body = msg;
|
||||
uac->blen = len;
|
||||
curl_easy_setopt(uac->curl, CURLOPT_INFILESIZE, uac->hlen + uac->blen);
|
||||
CURLcode res = curl_easy_perform(uac->curl);
|
||||
if (res != CURLE_OK)
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_init_curl(ut->data);
|
||||
uac->ut = ut;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret < 0) return;
|
||||
@@ -174,31 +243,26 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
ut->pos = 0;
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
uwsgi_alarm_curl_call_curl(uac, ut->buf, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_init_curl(uai);
|
||||
else
|
||||
uwsgi_thread_new_with_data(uwsgi_alarm_curl_loop, uai);
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
struct uwsgi_alarm_curl *uac = uai->data_ptr;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_call_curl(uac, msg, len);
|
||||
else {
|
||||
struct uwsgi_thread *ut = uac->ut;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_load(void) {
|
||||
|
||||
@@ -4,10 +4,9 @@ void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
|
||||
|
||||
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_alarm_xmpp_loop, uai->arg);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
ut->data = uai->arg;
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
/*
|
||||
|
||||
python >= 3.4 asyncio (PEP 3156) loop engine
|
||||
|
||||
EXPERIMENTAL !!!
|
||||
|
||||
Author: Roberto De Ioris
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
static struct uwsgi_asyncio {
|
||||
PyObject *mod;
|
||||
PyObject *loop;
|
||||
PyObject *request;
|
||||
PyObject *hook_fd;
|
||||
PyObject *hook_timeout;
|
||||
PyObject *hook_fix;
|
||||
} uasyncio;
|
||||
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req
|
||||
|
||||
static void uwsgi_opt_setup_asyncio(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi.socket_timeout = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "asyncio";
|
||||
|
||||
}
|
||||
|
||||
static struct uwsgi_option asyncio_options[] = {
|
||||
{"asyncio", required_argument, 0, "a shortcut enabling asyncio loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_asyncio, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
static void gil_asyncio_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
}
|
||||
|
||||
static void gil_asyncio_release() {
|
||||
PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key));
|
||||
}
|
||||
|
||||
static int uwsgi_asyncio_wait_read_hook(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", fd, uasyncio.hook_fd,(long) wsgi_req) == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOl", timeout, uasyncio.hook_timeout, (long)wsgi_req);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", fd) == NULL) PyErr_Print();
|
||||
goto error;
|
||||
}
|
||||
// back to loop
|
||||
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
|
||||
// back from loop
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", fd) == NULL) PyErr_Print();
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
|
||||
Py_DECREF(ob_timeout);
|
||||
|
||||
if (wsgi_req->async_timed_out) return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int uwsgi_asyncio_wait_write_hook(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_writer", "iOl", fd, uasyncio.hook_fd,(long) wsgi_req) == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOl", timeout, uasyncio.hook_timeout, (long)wsgi_req);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_writer", "i", fd) == NULL) PyErr_Print();
|
||||
goto error;
|
||||
}
|
||||
// back to loop
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
// back from loop
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_writer", "i", fd) == NULL) PyErr_Print();
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
|
||||
Py_DECREF(ob_timeout);
|
||||
|
||||
if (wsgi_req->async_timed_out) return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *py_uwsgi_asyncio_request(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
int timed_out = 0;
|
||||
if (!PyArg_ParseTuple(args, "l|i:uwsgi_asyncio_request", &wsgi_req_ptr, &timed_out)) {
|
||||
uwsgi_log_verbose("[BUG] invalid arguments for asyncio callback !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
PyObject *ob_timeout = (PyObject *) wsgi_req->async_timeout;
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
Py_DECREF(ob_timeout);
|
||||
// avoid mess when closing the request
|
||||
wsgi_req->async_timeout = NULL;
|
||||
|
||||
if (timed_out > 0) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
int status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status > 0) {
|
||||
ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOli", uwsgi.socket_timeout, uasyncio.request, wsgi_req_ptr, 1);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
// trick for reference counting
|
||||
wsgi_req->async_timeout = (struct uwsgi_rb_timer *) ob_timeout;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) {
|
||||
PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
// we call this two time... overengineering :(
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
|
||||
uwsgi.schedule_to_req();
|
||||
goto again;
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
free_req_queue;
|
||||
again:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *py_uwsgi_asyncio_accept(PyObject *self, PyObject *args) {
|
||||
long uwsgi_sock_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l:uwsgi_asyncio_accept", &uwsgi_sock_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
uwsgi_async_queue_is_full(uwsgi_now());
|
||||
goto end;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) uwsgi_sock_ptr;
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
// in case of errors (or thundering herd, just reset it)
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
free_req_queue;
|
||||
goto end;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
|
||||
|
||||
// add callback for protocol
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", wsgi_req->fd, uasyncio.request, (long) wsgi_req) == NULL) {
|
||||
free_req_queue;
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
// add timeout
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOli", uwsgi.socket_timeout, uasyncio.request, (long)wsgi_req, 1);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
free_req_queue;
|
||||
}
|
||||
else {
|
||||
// trick for reference counting
|
||||
wsgi_req->async_timeout = (struct uwsgi_rb_timer *) ob_timeout;
|
||||
}
|
||||
end:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_fd(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l:uwsgi_asyncio_hook_fd", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_timeout(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.wsgi_req->async_timed_out = 1;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_fix(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef uwsgi_asyncio_accept_def[] = { {"uwsgi_asyncio_accept", py_uwsgi_asyncio_accept, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_request_def[] = { {"uwsgi_asyncio_request", py_uwsgi_asyncio_request, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_fd_def[] = { {"uwsgi_asyncio_hook_fd", py_uwsgi_asyncio_hook_fd, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_timeout_def[] = { {"uwsgi_asyncio_hook_timeout", py_uwsgi_asyncio_hook_timeout, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_fix_def[] = { {"uwsgi_asyncio_hook_fix", py_uwsgi_asyncio_hook_fix, METH_VARARGS, ""} };
|
||||
|
||||
static void uwsgi_asyncio_schedule_fix(struct wsgi_request *wsgi_req) {
|
||||
PyObject *cb = PyObject_CallMethod(uasyncio.loop, "call_soon", "Ol", uasyncio.hook_fix, (long) wsgi_req);
|
||||
if (!cb) goto error;
|
||||
Py_DECREF(cb);
|
||||
return;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
static void asyncio_loop() {
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running asyncio without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi_log("!!! Running asyncio with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
|
||||
}
|
||||
|
||||
if (!uwsgi.async_waiting_fd_table)
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
if (!uwsgi.async_proto_fd_table)
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
up.gil_get = gil_asyncio_get;
|
||||
up.gil_release = gil_asyncio_release;
|
||||
|
||||
uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;
|
||||
|
||||
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uwsgi.schedule_to_main) {
|
||||
uwsgi_log("*** DANGER *** asyncio mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
PyObject *asyncio = PyImport_ImportModule("asyncio");
|
||||
if (!asyncio) uwsgi_pyexit;
|
||||
|
||||
uasyncio.mod = asyncio;
|
||||
|
||||
uasyncio.loop = PyObject_CallMethod(asyncio, "get_event_loop", NULL);
|
||||
if (!uasyncio.loop) uwsgi_pyexit;
|
||||
|
||||
// main greenlet waiting for connection (one greenlet per-socket)
|
||||
PyObject *asyncio_accept = PyCFunction_New(uwsgi_asyncio_accept_def, NULL);
|
||||
Py_INCREF(asyncio_accept);
|
||||
|
||||
uasyncio.request = PyCFunction_New(uwsgi_asyncio_request_def, NULL);
|
||||
if (!uasyncio.request) uwsgi_pyexit;
|
||||
|
||||
uasyncio.hook_fd = PyCFunction_New(uwsgi_asyncio_hook_fd_def, NULL);
|
||||
if (!uasyncio.hook_fd) uwsgi_pyexit;
|
||||
uasyncio.hook_timeout = PyCFunction_New(uwsgi_asyncio_hook_timeout_def, NULL);
|
||||
if (!uasyncio.hook_timeout) uwsgi_pyexit;
|
||||
uasyncio.hook_fix = PyCFunction_New(uwsgi_asyncio_hook_fix_def, NULL);
|
||||
if (!uasyncio.hook_fix) uwsgi_pyexit;
|
||||
|
||||
Py_INCREF(uasyncio.request);
|
||||
Py_INCREF(uasyncio.hook_fd);
|
||||
Py_INCREF(uasyncio.hook_timeout);
|
||||
Py_INCREF(uasyncio.hook_fix);
|
||||
|
||||
// call add_handler on each socket
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", uwsgi_sock->fd, asyncio_accept, (long) uwsgi_sock) == NULL) {
|
||||
uwsgi_pyexit;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "run_forever", NULL) == NULL) {
|
||||
uwsgi_pyexit;
|
||||
}
|
||||
|
||||
// never here ?
|
||||
}
|
||||
|
||||
static void asyncio_init() {
|
||||
uwsgi_register_loop( (char *) "asyncio", asyncio_loop);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin asyncio_plugin = {
|
||||
.name = "asyncio",
|
||||
.options = asyncio_options,
|
||||
.on_load = asyncio_init,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='asyncio'
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['asyncio']
|
||||
@@ -281,7 +281,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
total_busyness += worker_busyness;
|
||||
u_carbon.was_busy[i-1] = 0;
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
// only running workers are counted in total memory stats and if memory-report option is enabled
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
total_vsz += uwsgi.workers[i].vsz_size;
|
||||
@@ -294,7 +294,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -327,7 +327,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
wok = carbon_write(fd, "%s%s.%s.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -380,6 +380,11 @@ metrics_loop:
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
if (!wok) goto clear;
|
||||
um = um->next;
|
||||
}
|
||||
|
||||
+217
-132
@@ -2,6 +2,8 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define kill_on_error if (!uc.do_not_kill_on_error) { if (kill(cgi_pid, SIGKILL)) uwsgi_error("kill()");}
|
||||
|
||||
struct uwsgi_cgi {
|
||||
struct uwsgi_dyn_dict *mountpoint;
|
||||
struct uwsgi_dyn_dict *helpers;
|
||||
@@ -16,6 +18,8 @@ struct uwsgi_cgi {
|
||||
int has_mountpoints;
|
||||
struct uwsgi_dyn_dict *default_cgi;
|
||||
int path_info;
|
||||
int do_not_kill_on_error;
|
||||
int async_max_attempts;
|
||||
} uc ;
|
||||
|
||||
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
@@ -62,6 +66,9 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
{"cgi-path-info", no_argument, 0, "disable PATH_INFO management in cgi scripts", uwsgi_opt_true, &uc.path_info, 0},
|
||||
|
||||
{"cgi-do-not-kill-on-error", no_argument, 0, "do not send SIGKILL to cgi script on errors", uwsgi_opt_true, &uc.do_not_kill_on_error, 0},
|
||||
{"cgi-async-max-attempts", no_argument, 0, "max waitpid() attempts in cgi async mode (default 10)", uwsgi_opt_set_int, &uc.async_max_attempts, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -179,78 +186,154 @@ static char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
/*
|
||||
start reading each line until Status or Location are found
|
||||
-1 error
|
||||
0 not found
|
||||
1 found
|
||||
*/
|
||||
static int uwsgi_cgi_check_status(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
char *key = buf, *value = NULL;
|
||||
size_t header_size = 0;
|
||||
int status_sent = 0;
|
||||
size_t i;
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
i++;
|
||||
goto send_body;
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
// Default status
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("setting default Status header\n");
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
return 1;
|
||||
}
|
||||
// invalid header
|
||||
else if (value == NULL) {
|
||||
return -1;
|
||||
// invalid header
|
||||
else if (value == NULL) return -1;
|
||||
header_size = (buf+i) - key;
|
||||
// security check
|
||||
if (buf+i > buf) {
|
||||
// remove \r
|
||||
if ((buf[i-1]) == '\r') {
|
||||
header_size--;
|
||||
}
|
||||
}
|
||||
|
||||
// enough space for Status ?
|
||||
if (header_size >= 11) {
|
||||
// "Status: NNN"
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found Status header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
return 1;
|
||||
}
|
||||
// Location: X
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found Location header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
header_size = (buf+i) - key;
|
||||
// security check
|
||||
if (buf+i > buf) {
|
||||
if ((buf[i-1]) == '\r') {
|
||||
header_size--;
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
else if (buf[i] == ':') {
|
||||
value = buf+i;
|
||||
}
|
||||
else if (buf[i] != '\r') {
|
||||
if (key == NULL) key = buf + i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// no Status/Location found
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, int fd, char *buf, size_t blen) {
|
||||
|
||||
size_t i;
|
||||
size_t header_size = 0;
|
||||
int status_sent = 0;
|
||||
size_t remains = blen;
|
||||
char *ptr = buf;
|
||||
size_t len = 0;
|
||||
|
||||
while(remains > 0) {
|
||||
ssize_t rlen = uwsgi_read_true_nb(fd, ptr, remains, uc.timeout);
|
||||
if (rlen < 0) {
|
||||
if (!errno) return 1;
|
||||
return -1;
|
||||
}
|
||||
// timed out
|
||||
if (rlen == 0) return -1;
|
||||
remains -= rlen;
|
||||
len += rlen;
|
||||
ptr += rlen;
|
||||
|
||||
// Search for Status/Location headers
|
||||
if (!status_sent) {
|
||||
status_sent = uwsgi_cgi_check_status(wsgi_req, buf, len);
|
||||
if (status_sent < 0) return -1;
|
||||
// need more data ?
|
||||
if (status_sent == 0) continue;
|
||||
}
|
||||
|
||||
// send headers
|
||||
char *key = buf;
|
||||
char *value = NULL;
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
i++;
|
||||
goto send_body;
|
||||
}
|
||||
// invalid header
|
||||
else if (value == NULL) {
|
||||
return -1;
|
||||
}
|
||||
header_size = (buf+i) - key;
|
||||
// security check
|
||||
if (buf+i > buf) {
|
||||
if ((buf[i-1]) == '\r') {
|
||||
header_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found CGI header: %.*s\n", header_size, key);
|
||||
uwsgi_log("found CGI header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
|
||||
if (status_sent == 0) {
|
||||
// "Status: NNN"
|
||||
// Ignore "Status: NNN" header
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
// default status
|
||||
if (status_sent == 0) {
|
||||
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
else if (buf[i] == ':') {
|
||||
value = buf+i;
|
||||
}
|
||||
|
||||
uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
else if (buf[i] == ':') {
|
||||
value = buf+i;
|
||||
}
|
||||
else if (buf[i] != '\r') {
|
||||
if (key == NULL) {
|
||||
key = buf + i;
|
||||
else if (buf[i] != '\r') {
|
||||
if (key == NULL) {
|
||||
key = buf + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,7 +635,6 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do
|
||||
int post_pipe[2];
|
||||
int nargs = 0;
|
||||
int waitpid_status;
|
||||
ssize_t len;
|
||||
int i;
|
||||
char **argv;
|
||||
|
||||
@@ -590,126 +672,96 @@ static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t do
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
uwsgi_socket_nb(cgi_pipe[0]);
|
||||
uwsgi_socket_nb(post_pipe[1]);
|
||||
|
||||
// ok start sending post data...
|
||||
size_t remains = wsgi_req->post_cl;
|
||||
while(remains > 0) {
|
||||
ssize_t rlen = 0;
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, 8192, &rlen);
|
||||
if (!buf) {
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
if (buf == uwsgi.empty) break;
|
||||
// write data to the node
|
||||
if (uwsgi_write_true_nb(post_pipe[1], buf, rlen, uc.timeout)) {
|
||||
close(post_pipe[1]);
|
||||
goto clear2;
|
||||
}
|
||||
remains -= rlen;
|
||||
}
|
||||
|
||||
close(post_pipe[1]);
|
||||
// wait for data
|
||||
char *headers_buf = uwsgi_malloc(uc.buffer_size);
|
||||
char *ptr = headers_buf;
|
||||
remains = uc.buffer_size;
|
||||
int completed = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], ptr, remains);
|
||||
if (len > 0) {
|
||||
ptr+=len;
|
||||
remains -= len;
|
||||
}
|
||||
else if (len == 0) {
|
||||
completed = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
uwsgi_log("CGI timeout !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
break;
|
||||
}
|
||||
char *buf = uwsgi_malloc(uc.buffer_size);
|
||||
|
||||
if (uwsgi_cgi_parse(wsgi_req, headers_buf, uc.buffer_size-remains)) {
|
||||
uwsgi_log("invalid CGI output !!!\n");
|
||||
int completed = uwsgi_cgi_parse(wsgi_req, cgi_pipe[0], buf, uc.buffer_size);
|
||||
if (completed < 0) {
|
||||
uwsgi_log("invalid CGI response !!!\n");
|
||||
kill_on_error
|
||||
goto clear;
|
||||
}
|
||||
|
||||
while (!completed) {
|
||||
int ret = uwsgi.wait_read_hook(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], headers_buf, uc.buffer_size);
|
||||
if (len > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, headers_buf, len);
|
||||
}
|
||||
// end of output
|
||||
else if (len == 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("read()");
|
||||
ssize_t rlen = uwsgi_read_true_nb(cgi_pipe[0], buf, uc.buffer_size, uc.timeout);
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
kill_on_error
|
||||
goto clear;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
uwsgi_log("CGI timeout !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
break;
|
||||
else if (rlen == 0) {
|
||||
uwsgi_log("CGI timeout !!!\n");
|
||||
kill_on_error
|
||||
goto clear;
|
||||
}
|
||||
else {
|
||||
if (errno) {
|
||||
uwsgi_req_error("error reading CGI response\n");
|
||||
kill_on_error
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
clear:
|
||||
free(headers_buf);
|
||||
free(buf);
|
||||
clear2:
|
||||
close(cgi_pipe[0]);
|
||||
close(post_pipe[1]);
|
||||
|
||||
// now wait for process exit/death
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
// in async mode we need a trick...
|
||||
if (uwsgi.async > 1) {
|
||||
pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG);
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
else if (diedpid == 0) {
|
||||
// pass the pid of the cgi to async_plagued (the after request hook will clear the process)
|
||||
wsgi_req->async_plagued = (int) cgi_pid;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// close all the fd except wsgi_req->poll.fd and 2;
|
||||
|
||||
for(i=0;i< (int)uwsgi.max_fd;i++) {
|
||||
if (post_pipe[0] == i) {
|
||||
continue;
|
||||
}
|
||||
if (wsgi_req->post_file) {
|
||||
if (fileno(wsgi_req->post_file) == i) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i != wsgi_req->fd && i != 2 && i != cgi_pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
// now map wsgi_req->poll.fd (or async_post) to 0 & cgi_pipe[1] to 1
|
||||
if (post_pipe[0] != 0) {
|
||||
dup2(post_pipe[0], 0);
|
||||
close(post_pipe[0]);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
|
||||
#endif
|
||||
dup2(post_pipe[0], 0);
|
||||
close(post_pipe[0]);
|
||||
|
||||
dup2(cgi_pipe[1],1);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
|
||||
// close all the fd > 2
|
||||
for(i=3;i<(int)uwsgi.max_fd;i++) {
|
||||
close(i);
|
||||
}
|
||||
|
||||
// fill cgi env
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
// no need to free the putenv() memory
|
||||
@@ -873,6 +925,39 @@ clear2:
|
||||
|
||||
|
||||
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_plagued > 0) {
|
||||
int waitpid_status;
|
||||
pid_t cgi_pid = (pid_t) wsgi_req->async_plagued;
|
||||
int max_attempts = uc.async_max_attempts;
|
||||
if (!max_attempts) max_attempts = 10;
|
||||
while(max_attempts) {
|
||||
pid_t diedpid = waitpid(cgi_pid, &waitpid_status, WNOHANG);
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
break;
|
||||
}
|
||||
else if (diedpid == 0) {
|
||||
int ret = uwsgi.wait_milliseconds_hook(1000);
|
||||
if (ret < 0) {
|
||||
kill_on_error
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
max_attempts--;
|
||||
}
|
||||
if (max_attempts == 0) {
|
||||
kill_on_error
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ int cheaper_backlog2_algo(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.socket_timeout;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
@@ -13,11 +13,13 @@ struct uwsgi_cheaper_busyness_global {
|
||||
uint64_t busyness_max;
|
||||
uint64_t busyness_min;
|
||||
uint64_t *last_values;
|
||||
uint64_t *current_busyness;
|
||||
uint64_t total_avg_busyness;
|
||||
int *was_busy;
|
||||
uint64_t tcheck;
|
||||
uint64_t last_cheaped; // last time worker was cheaped due to low busyness
|
||||
uint64_t next_cheap; // timestamp, we can cheap worker after it
|
||||
uint64_t penalty; // penelty for respawning to fast, it will be added to multiplier
|
||||
uint64_t penalty; // penalty for respawning to fast, it will be added to multiplier
|
||||
uint64_t min_multi; //initial multiplier will be stored here
|
||||
uint64_t cheap_multi; // current multiplier value
|
||||
int last_action; // 1 - spawn workers ; 2 - cheap worker
|
||||
@@ -41,7 +43,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_max, 0},
|
||||
|
||||
{"cheaper-busyness-min", required_argument, 0,
|
||||
"set the cheaper busyness low percent limit, belowe that value worker is considered idle (default 25)",
|
||||
"set the cheaper busyness low percent limit, below that value worker is considered idle (default 25)",
|
||||
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_min, 0},
|
||||
|
||||
{"cheaper-busyness-multiplier", required_argument, 0,
|
||||
@@ -57,7 +59,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
|
||||
#ifdef __linux__
|
||||
{"cheaper-busyness-backlog-alert", required_argument, 0,
|
||||
"spawn emergency worker(s) if anytime listen queue is higher than this value (default 33)",
|
||||
"spawn emergency worker(s) if any time listen queue is higher than this value (default 33)",
|
||||
uwsgi_opt_set_int, &uwsgi_cheaper_busyness_global.backlog_alert, 0},
|
||||
{"cheaper-busyness-backlog-multiplier", required_argument, 0,
|
||||
"set cheaper multiplier used for emergency workers (default 3)",
|
||||
@@ -148,46 +150,6 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
// we use microseconds
|
||||
uint64_t t = uwsgi.cheaper_overload*1000000;
|
||||
|
||||
// this happens on the first run, the required memory is allocated
|
||||
if (!uwsgi_cheaper_busyness_global.last_values) {
|
||||
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
}
|
||||
if (!uwsgi_cheaper_busyness_global.was_busy) {
|
||||
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set defaults
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
|
||||
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
|
||||
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
|
||||
#endif
|
||||
|
||||
if (!uwsgi_cheaper_busyness_global.min_multi) {
|
||||
// store initial multiplier so we don't loose its initial value
|
||||
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
|
||||
// since this is first run we will print current values
|
||||
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
|
||||
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
|
||||
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
#ifdef __linux__
|
||||
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
|
||||
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
|
||||
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize with current time
|
||||
if (uwsgi_cheaper_busyness_global.tcheck == 0) uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
|
||||
|
||||
if (uwsgi_cheaper_busyness_global.next_cheap == 0) set_next_cheap_time();
|
||||
|
||||
int active_workers = 0;
|
||||
uint64_t total_busyness = 0;
|
||||
uint64_t avg_busyness = 0;
|
||||
@@ -202,7 +164,7 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.shared->backlog;
|
||||
#endif
|
||||
|
||||
uint64_t now = uwsgi_micros();
|
||||
@@ -228,11 +190,23 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
|
||||
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
|
||||
i+1, uwsgi.cheaper_overload, percent);
|
||||
if (uwsgi.has_metrics) {
|
||||
// update metrics
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.current_busyness[i] = percent;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
}
|
||||
uwsgi_cheaper_busyness_global.last_values[i] = uwsgi.workers[i+1].running_time;
|
||||
}
|
||||
|
||||
avg_busyness = (active_workers ? total_busyness / active_workers : 0);
|
||||
if (uwsgi.has_metrics) {
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.total_avg_busyness = avg_busyness;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] %ds average busyness of %d worker(s) is at %d%%\n",
|
||||
(int) uwsgi.cheaper_overload, (int) active_workers, (int) avg_busyness);
|
||||
@@ -261,7 +235,7 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
// worker was cheaped and then spawned back in less than current multiplier*cheaper_overload seconds
|
||||
// we will increase the multiplier so that next time worker will need to wait longer before being cheaped
|
||||
uwsgi_cheaper_busyness_global.cheap_multi += uwsgi_cheaper_busyness_global.penalty;
|
||||
uwsgi_log("[busyness] worker(s) respawned to fast, increasing chpeaper multiplier to %llu (+%llu)\n",
|
||||
uwsgi_log("[busyness] worker(s) respawned to fast, increasing cheaper multiplier to %llu (+%llu)\n",
|
||||
uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
} else {
|
||||
decrease_multi();
|
||||
@@ -333,7 +307,7 @@ int cheaper_busyness_algo(int can_spawn) {
|
||||
// time needed to cheap them, than a lot min<busy<max when we do not reset timer
|
||||
// and then another idle cycle than would trigger cheaping
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), reseting cheaper timer\n",
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), resetting cheaper timer\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, uwsgi_cheaper_busyness_global.tolerance_counter);
|
||||
set_next_cheap_time();
|
||||
} else {
|
||||
@@ -385,10 +359,73 @@ void uwsgi_cheaper_register_busyness(void) {
|
||||
uwsgi_register_cheaper_algo("busyness", cheaper_busyness_algo);
|
||||
}
|
||||
|
||||
static int uwsgi_cheaper_busyness_init(void) {
|
||||
if (!uwsgi.requested_cheaper_algo || strcmp(uwsgi.requested_cheaper_algo, "busyness")) return 0;
|
||||
// this happens on the first run, the required memory is allocated
|
||||
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
// allocate metrics memory
|
||||
uwsgi_cheaper_busyness_global.current_busyness = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set defaults
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
|
||||
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
|
||||
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
|
||||
#endif
|
||||
|
||||
// store initial multiplier so we don't loose that value
|
||||
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
|
||||
// since this is first run we will print current values
|
||||
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
|
||||
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
|
||||
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
#ifdef __linux__
|
||||
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
|
||||
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
|
||||
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
|
||||
#endif
|
||||
|
||||
// register metrics if enabled
|
||||
if (uwsgi.has_metrics) {
|
||||
int i;
|
||||
char buf[4096];
|
||||
char buf2[4096];
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
if (snprintf(buf, 4096, "worker.%d.plugin.cheaper_busyness.busyness", i+1) <= 0) {
|
||||
uwsgi_log("[busyness] unable to register busyness metric for worker %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
if (snprintf(buf2, 4096, "3.%d.100.1", i+1) <= 0) {
|
||||
uwsgi_log("[busyness] unable to register busyness metric oid for worker %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.current_busyness[i], 0, NULL);
|
||||
}
|
||||
uwsgi_register_metric("plugin.cheaper_busyness.total_avg_busyness", "4.100.1", UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.total_avg_busyness, 0, NULL);
|
||||
uwsgi_log("[busyness] metrics registered\n");
|
||||
}
|
||||
|
||||
// initialize timers
|
||||
uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
|
||||
set_next_cheap_time();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cheaper_busyness_plugin = {
|
||||
|
||||
.name = "cheaper_busyness",
|
||||
.on_load = uwsgi_cheaper_register_busyness,
|
||||
.on_load = uwsgi_cheaper_register_busyness,
|
||||
.options = uwsgi_cheaper_busyness_options,
|
||||
|
||||
.init = uwsgi_cheaper_busyness_init
|
||||
};
|
||||
|
||||
@@ -41,8 +41,11 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
peers->session = cs;
|
||||
peers->fd = -1;
|
||||
// create input buffer
|
||||
peers->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
size_t bufsize = cs->corerouter->buffer_size;
|
||||
if (!bufsize) bufsize = uwsgi.page_size;
|
||||
peers->in = uwsgi_buffer_new(bufsize);
|
||||
// add timeout
|
||||
peers->current_timeout = cs->corerouter->socket_timeout;
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
peers->prev = old_peers;
|
||||
|
||||
@@ -272,6 +275,22 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
usr->sign = val;
|
||||
usr->sign_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_key", 7, key, keylen)) {
|
||||
usr->sni_key = val;
|
||||
usr->sni_key_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_crt", 7, key, keylen)) {
|
||||
usr->sni_crt = val;
|
||||
usr->sni_crt_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_ca", 6, key, keylen)) {
|
||||
usr->sni_ca = val;
|
||||
usr->sni_ca_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("notify", 6, key, keylen)) {
|
||||
usr->notify = val;
|
||||
usr->notify_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
@@ -291,7 +310,6 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
|
||||
}
|
||||
|
||||
if (peer->failed) {
|
||||
|
||||
if (peer->soopt) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\" (%d retries): %s\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, peer->retries, strerror(peer->soopt));
|
||||
@@ -550,7 +568,9 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
|
||||
struct corerouter_peer *peer = uwsgi_calloc(sizeof(struct corerouter_peer));
|
||||
// main_peer has only input buffer as output buffer is taken from backend peers
|
||||
peer->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
size_t bufsize = ucr->buffer_size;
|
||||
if (!bufsize) bufsize = uwsgi.page_size;
|
||||
peer->in = uwsgi_buffer_new(bufsize);
|
||||
|
||||
ucr->cr_table[new_connection] = peer;
|
||||
cs->main_peer = peer;
|
||||
@@ -562,8 +582,8 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
cs->corerouter = ucr;
|
||||
cs->ugs = ugs;
|
||||
|
||||
// set initial timeout
|
||||
peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
// set initial timeout (could be overridden)
|
||||
peer->current_timeout = ucr->socket_timeout;
|
||||
|
||||
ucr->active_sessions++;
|
||||
|
||||
@@ -602,6 +622,10 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
corerouter_close_session(ucr, cs);
|
||||
cs = NULL;
|
||||
}
|
||||
else {
|
||||
// truly set the timeout
|
||||
peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
@@ -919,10 +943,13 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
|
||||
uwsgi_log("starting %s in cheap mode\n", ucr->name);
|
||||
}
|
||||
for (i = 0; i < ucr->processes; i++) {
|
||||
if (register_gateway(ucr->name, uwsgi_corerouter_loop, ucr) == NULL) {
|
||||
struct uwsgi_gateway *ug = register_gateway(ucr->name, uwsgi_corerouter_loop, ucr);
|
||||
if (ug == NULL) {
|
||||
uwsgi_log("unable to register the %s gateway\n", ucr->name);
|
||||
exit(1);
|
||||
}
|
||||
ug->uid = ucr->uid;
|
||||
ug->gid = ucr->gid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1021,6 +1048,9 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
if (uwsgi_stats_keyvaln_comma(us, "key", s_slot->key, s_slot->keylen)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "hash", (unsigned long long) s_slot->hash)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) s_slot->hits)) goto end0;
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi_stats_keylong_comma(us, "sni_enabled", (unsigned long long) s_slot->sni_enabled)) goto end0;
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_key(us , "nodes")) goto end0;
|
||||
if (uwsgi_stats_list_open(us)) goto end0;
|
||||
@@ -1034,9 +1064,13 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) s_node->modifier1)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier2", (unsigned long long) s_node->modifier2)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_check", (unsigned long long) s_node->last_check)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) s_node->pid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) s_node->uid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) s_node->gid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) s_node->requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_requests", (unsigned long long) s_node->last_requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->transferred)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->tx)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "rx", (unsigned long long) s_node->rx)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cores", (unsigned long long) s_node->cores)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) s_node->load)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "weight", (unsigned long long) s_node->weight)) goto end0;
|
||||
@@ -1076,7 +1110,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
|
||||
+18
-4
@@ -3,12 +3,12 @@
|
||||
#define COREROUTER_STATUS_RECV_HDR 2
|
||||
#define COREROUTER_STATUS_RESPONSE 3
|
||||
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, uwsgi_now()+u->socket_timeout, x)
|
||||
#define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+u->socket_timeout, x)
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, uwsgi_now()+x->current_timeout, x)
|
||||
#define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+x->current_timeout, x)
|
||||
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
|
||||
|
||||
#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__)
|
||||
#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, x->session->client_address, x->session->client_port, __VA_ARGS__)
|
||||
#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key_len: 0) : x->key_len, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key: "") : x->key, x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__)
|
||||
#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key_len: 0) : x->key_len, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key: "") : x->key, x->session->client_address, x->session->client_port, __VA_ARGS__)
|
||||
|
||||
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
|
||||
errno = EINPROGRESS;\
|
||||
@@ -21,6 +21,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
|
||||
@@ -29,6 +30,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
|
||||
ubuf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
@@ -51,6 +53,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_read_exact(peer, l, f) read(peer->fd, peer->in->buf + peer->in->pos, (l - peer->in->pos));\
|
||||
@@ -59,6 +62,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_reset_hooks(peer) if(!peer->session->main_peer->disabled) {\
|
||||
@@ -184,6 +188,8 @@ struct corerouter_peer {
|
||||
|
||||
struct corerouter_peer *prev;
|
||||
struct corerouter_peer *next;
|
||||
|
||||
int current_timeout;
|
||||
};
|
||||
|
||||
struct uwsgi_corerouter {
|
||||
@@ -258,6 +264,14 @@ struct uwsgi_corerouter {
|
||||
|
||||
uint64_t active_sessions;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
struct uwsgi_string_list *resubscribe;
|
||||
char *resubscribe_bind;
|
||||
|
||||
size_t buffer_size;
|
||||
int fallback_on_no_key;
|
||||
};
|
||||
|
||||
// a session is started when a client connect to the router
|
||||
|
||||
@@ -4,7 +4,7 @@ common functions for various routers (fastrouter, http...)
|
||||
|
||||
*/
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -79,6 +79,9 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
}
|
||||
else {
|
||||
ugs->fd = bind_to_unix_dgram(ugs->name);
|
||||
if (ugs->fd < 1 || (uwsgi.subscriptions_use_credentials && uwsgi_socket_passcred(ugs->fd))) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
}
|
||||
@@ -113,10 +116,17 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
int i;
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
ssize_t len = -1;
|
||||
|
||||
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
len = uwsgi_recv_cred2(ugs->fd, bbuf, 4096, &usr.pid, &usr.uid, &usr.gid);
|
||||
}
|
||||
else {
|
||||
len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
}
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
|
||||
if (usr.sign_len > 0) {
|
||||
// calc the base size
|
||||
@@ -144,10 +154,6 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
if (node && node->len) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr.sign_len == 0 || usr.base_len == 0)
|
||||
return;
|
||||
if (usr.unix_check <= node->unix_check)
|
||||
return;
|
||||
if (!uwsgi_subscription_sign_check(node->slot, &usr)) {
|
||||
return;
|
||||
}
|
||||
@@ -177,6 +183,51 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resubscribe if needed ?
|
||||
if (ucr->resubscribe) {
|
||||
static char *address = NULL;
|
||||
if (!address) {
|
||||
struct uwsgi_gateway_socket *augs = uwsgi.gateway_sockets;
|
||||
while (augs) {
|
||||
if (!strcmp(ucr->name, augs->owner)) {
|
||||
if (!augs->subscription) {
|
||||
address = augs->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
augs = augs->next;
|
||||
}
|
||||
}
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
char *sni_key = NULL;
|
||||
char *sni_cert = NULL;
|
||||
char *sni_ca = NULL;
|
||||
if (usr.sni_key_len) {
|
||||
sni_key = uwsgi_concat2n(usr.sni_key, usr.sni_key_len, "", 0);
|
||||
}
|
||||
if (usr.sni_crt_len) {
|
||||
sni_cert = uwsgi_concat2n(usr.sni_crt, usr.sni_crt_len, "", 0);
|
||||
}
|
||||
if (usr.sni_ca_len) {
|
||||
sni_ca = uwsgi_concat2n(usr.sni_ca, usr.sni_ca_len, "", 0);
|
||||
}
|
||||
uwsgi_foreach(usl, ucr->resubscribe) {
|
||||
if (ucr->resubscribe_bind) {
|
||||
static int rfd = -1;
|
||||
if (rfd == -1) {
|
||||
rfd = bind_to_udp(ucr->resubscribe_bind, 0, 0);
|
||||
}
|
||||
uwsgi_send_subscription_from_fd(rfd, usl->value, usr.key, usr.keylen, usr.modifier1, usr.modifier2, bbuf[3], address, NULL, sni_key, sni_cert, sni_ca);
|
||||
}
|
||||
else {
|
||||
uwsgi_send_subscription_from_fd(-2, usl->value, usr.key, usr.keylen, usr.modifier1, usr.modifier2, bbuf[3], address, NULL, sni_key, sni_cert, sni_ca);
|
||||
}
|
||||
}
|
||||
if (sni_key) free(sni_key);
|
||||
if (sni_cert) free(sni_cert);
|
||||
if (sni_ca) free(sni_ca);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -65,8 +65,11 @@ int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct
|
||||
|
||||
char *name = peer->key;
|
||||
uint16_t name_len = peer->key_len;
|
||||
// max 5 split, reduce DOS attempts
|
||||
int count = 5;
|
||||
|
||||
split:
|
||||
if (!count) return 0;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("trying with %.*s\n", name_len, name);
|
||||
#endif
|
||||
@@ -76,6 +79,7 @@ split:
|
||||
if (next) {
|
||||
name_len -= next - name;
|
||||
name = next;
|
||||
count--;
|
||||
goto split;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-44
@@ -12,8 +12,8 @@ static void uwsgi_opt_setup_coroae(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi.socket_timeout = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "coroae";
|
||||
@@ -66,32 +66,14 @@ SV * coroae_coro_new(CV *block) {
|
||||
}
|
||||
|
||||
static int coroae_wait_milliseconds(int timeout) {
|
||||
int ret = -1;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(newSVnv(((double)timeout)/1000.0));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
char buf[256];
|
||||
double d = ((double)timeout)/1000.0;
|
||||
int ret = snprintf(buf, 256, "Coro::AnyEvent::sleep %f", d);
|
||||
if (ret <= 0 || ret > 256) return -1;
|
||||
perl_eval_pv(buf, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
int ret = 0;
|
||||
dSP;
|
||||
@@ -164,7 +146,7 @@ XS(XS_coroae_accept_request) {
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -244,8 +226,8 @@ edge:
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,21 +368,9 @@ static void coroae_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
perl_eval_pv("use Coro;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load Coro module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use AnyEvent;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load AnyEvent module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use Coro::AnyEvent;", 0);
|
||||
if (SvTRUE(ERRSV)) {
|
||||
uwsgi_log("unable to load Coro::AnyEvent module\n");
|
||||
exit(1);
|
||||
}
|
||||
perl_eval_pv("use Coro;", 1);
|
||||
perl_eval_pv("use AnyEvent;", 1);
|
||||
perl_eval_pv("use Coro::AnyEvent;", 1);
|
||||
|
||||
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = coroae_wait_fd_write;
|
||||
|
||||
@@ -10,7 +10,7 @@ static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
// use 1 minute as the cron resolution
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
|
||||
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
|
||||
|
||||
@@ -10,6 +10,10 @@ struct uwsgi_emperor_mongodb_state {
|
||||
char *address;
|
||||
char *collection;
|
||||
char *json;
|
||||
char *database;
|
||||
char *username;
|
||||
char *password;
|
||||
char *predigest;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,18 +24,26 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
try {
|
||||
|
||||
// requested fields
|
||||
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 );
|
||||
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 << "socket" << 1 );
|
||||
mongo::BSONObj q = mongo::fromjson(uems->json);
|
||||
// the connection object (will be automatically destroyed at each cycle)
|
||||
mongo::DBClientConnection c;
|
||||
// set the socket timeout
|
||||
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
c.setSoTimeout(uwsgi.socket_timeout);
|
||||
// connect
|
||||
c.connect(uems->address);
|
||||
|
||||
if (uems->database && uems->username && uems->password) {
|
||||
std::string err;
|
||||
if (c.auth(uems->database, uems->username, uems->password, err, uems->predigest ? false : true) == false) {
|
||||
uwsgi_log_verbose("[emperor-mongodb] unable to authenticate to db %s: %s\n", uems->database, err.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run the query
|
||||
std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p);
|
||||
while( cursor->more() ) {
|
||||
while(cursor.get() && cursor->more() ) {
|
||||
mongo::BSONObj p = cursor->next();
|
||||
|
||||
// checking for an empty string is not required, but we reduce the load
|
||||
@@ -40,6 +52,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
if (strlen(name) == 0) continue;
|
||||
|
||||
const char *config = p.getStringField("config");
|
||||
if (strlen(config) == 0) config = NULL;
|
||||
|
||||
time_t vassal_ts = 0;
|
||||
// ts must be a Date object !!!
|
||||
@@ -61,6 +74,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
}
|
||||
|
||||
const char *socket_name = p.getStringField("socket");
|
||||
if (strlen(socket_name) == 0) socket_name = NULL;
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
|
||||
}
|
||||
@@ -76,6 +90,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
b.append("name", c_ui->name);
|
||||
mongo::BSONObj q2 = b.obj();
|
||||
cursor = c.query(uems->collection, q2, 0, 0, &p);
|
||||
if (!cursor.get()) return;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("JSON: %s\n", q2.toString().c_str());
|
||||
#endif
|
||||
@@ -121,3 +136,40 @@ done:
|
||||
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
|
||||
}
|
||||
|
||||
// setup a new mongodb imperial monitor (keyval based)
|
||||
extern "C" void uwsgi_imperial_monitor_mongodb_init2(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
// allocate a new state
|
||||
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
|
||||
size_t arg_len = strlen(ues->arg);
|
||||
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
|
||||
|
||||
// parse args/ set defaults
|
||||
uems->address = (char *) "127.0.0.1:27017";
|
||||
uems->collection = (char *) "uwsgi.emperor.vassals";
|
||||
uems->json = (char *) "";
|
||||
char *args = NULL;
|
||||
if (arg_len <= 11) goto done;
|
||||
args = ues->arg+11;
|
||||
if (uwsgi_kvlist_parse(args, strlen(args), ',', '=',
|
||||
"addr", &uems->address,
|
||||
"address", &uems->address,
|
||||
"server", &uems->address,
|
||||
"collection", &uems->collection,
|
||||
"coll", &uems->collection,
|
||||
"json", &uems->json,
|
||||
"database", &uems->database,
|
||||
"db", &uems->database,
|
||||
"username", &uems->username,
|
||||
"password", &uems->password,
|
||||
"predigest", &uems->predigest,
|
||||
NULL)) {
|
||||
|
||||
uwsgi_log("[emperor-mongodb] invalid keyval syntax !\n");
|
||||
exit(1);
|
||||
}
|
||||
done:
|
||||
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init2(struct uwsgi_emperor_scanner *);
|
||||
|
||||
void emperor_mongodb_init(void) {
|
||||
uwsgi_register_imperial_monitor("mongodb", uwsgi_imperial_monitor_mongodb_init, uwsgi_imperial_monitor_mongodb);
|
||||
uwsgi_register_imperial_monitor("mongodb2", uwsgi_imperial_monitor_mongodb_init2, uwsgi_imperial_monitor_mongodb);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin emperor_mongodb_plugin = {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
NAME='emperor_zeromq'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['emperor_zeromq']
|
||||
|
||||
@@ -37,7 +37,7 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-events", required_argument, 0, "set the maximum number of concurrent events", uwsgi_opt_set_int, &ufr.cr.nevents, 0},
|
||||
{"fastrouter-quiet", required_argument, 0, "do not report failed connections to instances", uwsgi_opt_true, &ufr.cr.quiet, 0},
|
||||
{"fastrouter-cheap", no_argument, 0, "run the fastrouter in cheap mode", uwsgi_opt_true, &ufr.cr.cheap, 0},
|
||||
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the spcified address", uwsgi_opt_corerouter_ss, &ufr, 0},
|
||||
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the specified address", uwsgi_opt_corerouter_ss, &ufr, 0},
|
||||
{"fastrouter-subscription-slot", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "useless thanks to the new implementation", 0},
|
||||
|
||||
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
|
||||
@@ -48,6 +48,14 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-ss", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0},
|
||||
|
||||
{"fastrouter-uid", required_argument, 0, "drop fastrouter privileges to the specified uid", uwsgi_opt_uid, &ufr.cr.uid, 0 },
|
||||
{"fastrouter-gid", required_argument, 0, "drop fastrouter privileges to the specified gid", uwsgi_opt_gid, &ufr.cr.gid, 0 },
|
||||
{"fastrouter-resubscribe", required_argument, 0, "forward subscriptions to the specified subscription server", uwsgi_opt_add_string_list, &ufr.cr.resubscribe, 0},
|
||||
{"fastrouter-resubscribe-bind", required_argument, 0, "bind to the specified address when re-subscribing", uwsgi_opt_set_str, &ufr.cr.resubscribe_bind, 0},
|
||||
|
||||
{"fastrouter-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &ufr.cr.buffer_size, 0},
|
||||
{"fastrouter-fallback-on-no-key", no_argument, 0, "move to fallback node even if a subscription key is not found", uwsgi_opt_true, &ufr.cr.fallback_on_no_key, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -219,8 +227,15 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
return -1;
|
||||
|
||||
// check instance
|
||||
if (new_peer->instance_address_len == 0)
|
||||
if (new_peer->instance_address_len == 0) {
|
||||
if (ufr.cr.fallback_on_no_key) {
|
||||
new_peer->failed = 1;
|
||||
new_peer->can_retry = 1;
|
||||
corerouter_close_peer(&ufr.cr, new_peer);
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ else:
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
archdir2 = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyarchhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if archdir2:
|
||||
CFLAGS.append('-I' + archdir2)
|
||||
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
@@ -264,7 +264,7 @@ static void uwsgi_gccgo_request_goroutine(void *arg) {
|
||||
int ret,status;
|
||||
|
||||
for(;;) {
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -388,8 +388,8 @@ retry:
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
// spawn the new goroutine
|
||||
|
||||
@@ -8,18 +8,20 @@ struct uwsgi_geoip {
|
||||
char *city_db;
|
||||
GeoIP *country;
|
||||
GeoIP *city;
|
||||
int use_disk;
|
||||
|
||||
} ugeoip;
|
||||
|
||||
struct uwsgi_option uwsgi_geoip_options[] = {
|
||||
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
|
||||
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
{"geoip-use-disk", no_argument, 0, "do not cache geoip databases in memory", uwsgi_opt_true, &ugeoip.use_disk, 0},
|
||||
UWSGI_END_OF_OPTIONS
|
||||
};
|
||||
|
||||
static int uwsgi_geoip_init() {
|
||||
if (ugeoip.country_db) {
|
||||
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
|
||||
ugeoip.country = GeoIP_open(ugeoip.country_db, ugeoip.use_disk ? GEOIP_STANDARD : GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.country) {
|
||||
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
|
||||
exit(1);
|
||||
@@ -27,7 +29,7 @@ static int uwsgi_geoip_init() {
|
||||
}
|
||||
|
||||
if (ugeoip.city_db) {
|
||||
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
|
||||
ugeoip.city = GeoIP_open(ugeoip.city_db, ugeoip.use_disk ? GEOIP_STANDARD : GEOIP_MEMORY_CACHE);
|
||||
if (!ugeoip.city) {
|
||||
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
|
||||
exit(1);
|
||||
|
||||
@@ -8,8 +8,8 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi.socket_timeout = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "gevent";
|
||||
@@ -210,8 +210,8 @@ edge:
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
// hack to easily pass wsgi_req pointer to the greenlet
|
||||
@@ -257,7 +257,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
for(;;) {
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -345,11 +345,14 @@ static void gil_gevent_release() {
|
||||
|
||||
static void gevent_loop() {
|
||||
|
||||
// ensure SIGPIPE is ignored
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi_log("!!! Running gevent with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ static void uwsgi_glusterfs_add_mountpoint(char *arg, size_t arg_len) {
|
||||
static void uwsgi_glusterfs_setup() {
|
||||
|
||||
if (!uglusterfs.timeout) {
|
||||
uglusterfs.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
uglusterfs.timeout = uwsgi.socket_timeout;
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uglusterfs.mountpoints;
|
||||
|
||||
@@ -90,7 +90,7 @@ ssize_t uwsgi_graylog2_logger(struct uwsgi_logger *ul, char *message, size_t len
|
||||
int rlen = snprintf(g2c.json_buf, MAX_GELF, "{ \"version\": \"1.0\", \"host\": \"%s\", \"short_message\": \"%.*s\", \"full_message\": \"%.*s\", \"timestamp\": %d, \"level\": 5, \"facility\": \"uWSGI-%s\" }",
|
||||
g2c.host, truncated, g2c.escaped_buf, (int)g2c.escaped_len, g2c.escaped_buf, (int) uwsgi_now(), UWSGI_VERSION);
|
||||
|
||||
if (rlen > 0) {
|
||||
if (rlen > 0 && rlen < MAX_GELF) {
|
||||
if (compressBound((uLong) rlen) <= MAX_GELF) {
|
||||
if (compress((Bytef *) ul->buf, &destLen, (Bytef *) g2c.json_buf, (uLong) rlen) == Z_OK) {
|
||||
return sendto(ul->fd, ul->buf, destLen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
#define is_not_python(x) strcmp(uwsgi.p[x]->name, "python")
|
||||
|
||||
struct ugreenlet {
|
||||
int enabled;
|
||||
PyObject *callable;
|
||||
@@ -69,7 +71,7 @@ static void greenlet_schedule_to_req() {
|
||||
}
|
||||
|
||||
// call it in the main core
|
||||
if (uwsgi.p[modifier1]->suspend) {
|
||||
if (is_not_python(modifier1) && uwsgi.p[modifier1]->suspend) {
|
||||
uwsgi.p[modifier1]->suspend(NULL);
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ static void greenlet_schedule_to_req() {
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (uwsgi.p[modifier1]->resume) {
|
||||
if (is_not_python(modifier1) && uwsgi.p[modifier1]->resume) {
|
||||
uwsgi.p[modifier1]->resume(NULL);
|
||||
}
|
||||
|
||||
@@ -93,7 +95,7 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
// ensure gil
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
if (is_not_python(wsgi_req->uh->modifier1) && uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
|
||||
}
|
||||
PyObject *ret = PyGreenlet_Switch(ugl.main, NULL, NULL);
|
||||
@@ -103,7 +105,7 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
exit(1);
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
if (is_not_python(wsgi_req->uh->modifier1) && uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
|
||||
}
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
@@ -132,6 +134,10 @@ static void greenlet_init_apps(void) {
|
||||
|
||||
|
||||
PyGreenlet_Import();
|
||||
if (PyErr_Occurred()){
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
|
||||
ugl.main = PyGreenlet_GetCurrent();
|
||||
|
||||
@@ -79,6 +79,11 @@ static void uwsgi_gridfs_do(struct wsgi_request *wsgi_req, struct uwsgi_gridfs_m
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, gfile.getContentLength());
|
||||
|
||||
char http_last_modified[49];
|
||||
time_t t = gfile.getUploadDate().toTimeT();
|
||||
int size = uwsgi_http_date(t, http_last_modified);
|
||||
uwsgi_response_add_header(wsgi_req, (char *)"Last-Modified", 13, http_last_modified, size);
|
||||
|
||||
if (ugm->etag) {
|
||||
std::string g_md5 = gfile.getMD5();
|
||||
if (!g_md5.empty()) {
|
||||
@@ -169,7 +174,7 @@ static struct uwsgi_gridfs_mountpoint *uwsgi_gridfs_add_mountpoint(char *arg, si
|
||||
ugm->timeout = atoi(ugm->timeout_str);
|
||||
}
|
||||
else {
|
||||
ugm->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
ugm->timeout = uwsgi.socket_timeout;
|
||||
}
|
||||
|
||||
if (ugm->prefix) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user