mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66099275ca | ||
|
|
e7a40eb173 | ||
|
|
8342150b78 | ||
|
|
e2253f3693 | ||
|
|
d2f07c7583 | ||
|
|
1c87053a13 | ||
|
|
d69e23414f | ||
|
|
3d37d272ee | ||
|
|
9094a0f811 | ||
|
|
97efcca2b7 | ||
|
|
2445fd1f61 | ||
|
|
3234e0aae8 | ||
|
|
c5e7eb5d95 | ||
|
|
e051e4fe1c | ||
|
|
5f691ec987 | ||
|
|
a8e0aac9b0 | ||
|
|
bcdbab247c | ||
|
|
2e378dfc29 | ||
|
|
acc270ad81 | ||
|
|
b0c3ee02f9 | ||
|
|
06ab5eaee5 | ||
|
|
46de2ae0cb | ||
|
|
65fe93ac14 | ||
|
|
f7cdd22f9a | ||
|
|
3d553d2ae0 | ||
|
|
582d5828aa | ||
|
|
245a66b0e5 | ||
|
|
596c81124e | ||
|
|
a86a1fcc40 | ||
|
|
34036ac8b4 | ||
|
|
11cd6c34a5 | ||
|
|
aaea6ff2e2 | ||
|
|
38c30bc257 | ||
|
|
2f3e83b78e | ||
|
|
43e8c65841 | ||
|
|
555902a0ee | ||
|
|
9d4f4eb3c3 | ||
|
|
5d338cfb3a | ||
|
|
3406441d95 | ||
|
|
df08c7bfb5 | ||
|
|
75b4a3cb28 | ||
|
|
c356c01f12 | ||
|
|
ba8aa44baa | ||
|
|
a1dc7a660c | ||
|
|
3a4663844b | ||
|
|
309f449a43 | ||
|
|
f059a69312 | ||
|
|
93116a1239 | ||
|
|
5e4440443a | ||
|
|
373481b888 | ||
|
|
105b9c69cf | ||
|
|
9012ead72c | ||
|
|
6c1d2625a8 | ||
|
|
c0733b5771 | ||
|
|
f4759d7acd | ||
|
|
7082188a06 | ||
|
|
bcd9ed011d | ||
|
|
25c6d7a3a1 | ||
|
|
675c02c7fa | ||
|
|
32896a1418 | ||
|
|
548e736d84 | ||
|
|
87575b1a22 | ||
|
|
1aa6eeca1b | ||
|
|
f778e30d48 | ||
|
|
e071184d53 | ||
|
|
1d09cde778 | ||
|
|
70ee29becb | ||
|
|
60e26333bf | ||
|
|
865b9c199d | ||
|
|
833193a1ba | ||
|
|
4eab050634 | ||
|
|
688d1d3b75 | ||
|
|
349daee614 | ||
|
|
0d272cf747 | ||
|
|
46ac28efae | ||
|
|
31b3bcc83d | ||
|
|
f364d676fa | ||
|
|
c72fde1eed | ||
|
|
a5cacfbba6 | ||
|
|
921cfa5d79 | ||
|
|
9c676c62f5 | ||
|
|
2917de3e76 | ||
|
|
e836272c07 | ||
|
|
7e25452242 | ||
|
|
42d42d9e4c | ||
|
|
73c3e971e6 | ||
|
|
b627edf1b8 | ||
|
|
7fbc46750b | ||
|
|
1a63634359 | ||
|
|
c30e99a0df | ||
|
|
3c53f26cbd | ||
|
|
a5c74293d8 | ||
|
|
e5da0fc28c | ||
|
|
8e9bcc4758 | ||
|
|
bcf1f46d33 | ||
|
|
8cd13f2ad9 | ||
|
|
13df278cc4 | ||
|
|
56fedbd80c | ||
|
|
c4b563f260 | ||
|
|
39706c5899 | ||
|
|
e45f710694 | ||
|
|
0c86212aa2 | ||
|
|
3cfa743cb5 | ||
|
|
f14cb7e02a | ||
|
|
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 | ||
|
|
3b4581a581 | ||
|
|
dfaa1d9313 | ||
|
|
795721b91e | ||
|
|
6bd0095513 | ||
|
|
38682590e9 | ||
|
|
aa2a212be8 | ||
|
|
51714203a7 | ||
|
|
fbac57a903 | ||
|
|
768d1c4099 | ||
|
|
82fa510030 | ||
|
|
a6e6bff082 | ||
|
|
304f847dc6 | ||
|
|
5bb7f02921 | ||
|
|
02ee60c6ef | ||
|
|
4d3526a377 | ||
|
|
ca9d1830bb | ||
|
|
4ff485d565 | ||
|
|
63d5c6afc9 | ||
|
|
3a36551d1f | ||
|
|
26877e1da9 | ||
|
|
d81330c514 | ||
|
|
441013b71b | ||
|
|
a6b9e653a4 | ||
|
|
c7161139e7 | ||
|
|
ce07c1a454 | ||
|
|
4eb3b76c35 | ||
|
|
3519fcbcc6 | ||
|
|
70dd9fca32 | ||
|
|
a573602171 | ||
|
|
29418654d7 | ||
|
|
31c31c4ce2 | ||
|
|
0217766dd1 | ||
|
|
3d15660407 | ||
|
|
57ce416ae1 | ||
|
|
248a22b064 | ||
|
|
49c5206d86 | ||
|
|
5b17363b40 | ||
|
|
e6c3c04e64 | ||
|
|
9a36b2b891 | ||
|
|
bfd699dac5 | ||
|
|
cc3e43eb3d | ||
|
|
b934ac9588 | ||
|
|
92b6c62cac | ||
|
|
46cceb0465 | ||
|
|
f1b3522c2a | ||
|
|
c99f5d0875 | ||
|
|
b972c2d6bb | ||
|
|
d226f65890 | ||
|
|
60b54c4d7c | ||
|
|
ace79b1179 | ||
|
|
9993e3710c | ||
|
|
98541dbc65 | ||
|
|
cabb6d72d9 | ||
|
|
217f2f99ff | ||
|
|
890e0004b6 | ||
|
|
d17d947cd1 | ||
|
|
a69c775cd5 | ||
|
|
4c051d90ed | ||
|
|
f55c52eaff | ||
|
|
88b5f968a4 | ||
|
|
6fdeecce0f | ||
|
|
f6923728d8 | ||
|
|
cf96783dce | ||
|
|
e4d3d209c8 | ||
|
|
5182eaf485 | ||
|
|
082d47e156 | ||
|
|
0715031b00 | ||
|
|
27c3532617 | ||
|
|
cb1370b148 | ||
|
|
9cc58a3c13 | ||
|
|
150f0c631e | ||
|
|
0574a120bc | ||
|
|
c6550ece68 | ||
|
|
e76a40530b | ||
|
|
31c73ce298 | ||
|
|
b304766718 | ||
|
|
0ab1cfacc9 | ||
|
|
b1f06bce32 | ||
|
|
347ef1a5bf | ||
|
|
b4d9eb4f73 | ||
|
|
f44a36900a | ||
|
|
b6c969254d | ||
|
|
c5003561dd | ||
|
|
18dead4cd2 | ||
|
|
62aee259fa | ||
|
|
69c49f713e | ||
|
|
08525a91ee | ||
|
|
40fee74a5f | ||
|
|
6d8f179863 | ||
|
|
d0b3c442c1 | ||
|
|
de82b58952 | ||
|
|
eb33fa7b19 | ||
|
|
9dde5f9d82 | ||
|
|
036df0e5ff | ||
|
|
1154aa8ddc | ||
|
|
3371dd2f94 | ||
|
|
06791376af | ||
|
|
30e0af3826 | ||
|
|
e4903ee0bf | ||
|
|
859c386b40 | ||
|
|
b83fecf4d3 | ||
|
|
25dc608fa3 | ||
|
|
c01cf1f6be | ||
|
|
9825f95ed5 | ||
|
|
36143381e1 | ||
|
|
8c25bafc73 | ||
|
|
826f49c010 | ||
|
|
8b006c0874 | ||
|
|
5806c333f5 | ||
|
|
e606d1e5d1 | ||
|
|
ec954b8aa7 | ||
|
|
95d20e9f48 | ||
|
|
165aad8cd0 | ||
|
|
29c339a3c3 | ||
|
|
12afba035b | ||
|
|
eeb203afd4 | ||
|
|
2ccdd0fb67 | ||
|
|
6a18d10c56 | ||
|
|
d1383d7749 | ||
|
|
0abbabbe10 | ||
|
|
ea44525c22 | ||
|
|
2396c7cf31 | ||
|
|
4805a9c219 | ||
|
|
882cdcc2b6 | ||
|
|
59c8bb51b4 | ||
|
|
3c2350f5ad | ||
|
|
422e958fe3 | ||
|
|
4d9c7809d6 | ||
|
|
6b3d8ea146 | ||
|
|
b5d8538fe8 | ||
|
|
47796b315e | ||
|
|
222bcd8fdc | ||
|
|
f92b800a7c | ||
|
|
dec2b234f8 | ||
|
|
3dbd7e3115 | ||
|
|
09d8747918 | ||
|
|
fa78fd915b | ||
|
|
db56141485 | ||
|
|
7685af4652 | ||
|
|
21cb62db6c | ||
|
|
c62aa8e7ed | ||
|
|
4765965d8e | ||
|
|
556feaef2c | ||
|
|
799b8a22e0 | ||
|
|
2336580164 | ||
|
|
ca4f30c003 | ||
|
|
d7d0a71d87 | ||
|
|
44b92f1578 | ||
|
|
abed95362f | ||
|
|
72ecc217f7 | ||
|
|
1405d01d50 | ||
|
|
def65c4793 | ||
|
|
26386909de | ||
|
|
2d4e04059a | ||
|
|
ac557739c2 | ||
|
|
73bfc20ba1 | ||
|
|
6d5ae96d50 | ||
|
|
20b5b7b0dc | ||
|
|
82c5afd0c7 | ||
|
|
ec14f5b0fe | ||
|
|
d93bdcb7b4 | ||
|
|
b68ffc842d | ||
|
|
0326c1d508 | ||
|
|
42f45bfbf9 | ||
|
|
d018d3af99 | ||
|
|
42afc476d7 | ||
|
|
b5037d3f0f | ||
|
|
065dd7cfff | ||
|
|
7909e092b5 | ||
|
|
9da53f5fd4 | ||
|
|
025cb7744e | ||
|
|
e48a3ff1b7 | ||
|
|
2be371003c | ||
|
|
60d940e301 | ||
|
|
96c56cd8d5 | ||
|
|
4184619f7b | ||
|
|
50a8ec8a19 | ||
|
|
79c702278a | ||
|
|
8fc41a4c85 | ||
|
|
9c6455252d | ||
|
|
83e41844f3 | ||
|
|
2cc17d6b11 | ||
|
|
14057b72c8 | ||
|
|
faf72b6a77 | ||
|
|
963afa5174 | ||
|
|
ce8ff8c45f | ||
|
|
5ae742e8e1 | ||
|
|
60f6572985 | ||
|
|
4ea34c63d2 | ||
|
|
5699d21aa7 | ||
|
|
dda8d25495 | ||
|
|
d4f690322c | ||
|
|
4f2f30d1e5 | ||
|
|
d3b28e7956 | ||
|
|
ab4afdbeaa | ||
|
|
54e2d698cb | ||
|
|
8b0565c0b8 | ||
|
|
102d6f25ed | ||
|
|
d0a53aa976 | ||
|
|
f8cf808e47 | ||
|
|
f8bbd2177e | ||
|
|
f44c145941 | ||
|
|
f34ac9f6aa | ||
|
|
b971230fd9 | ||
|
|
5c6340caac | ||
|
|
c0b97b47d3 | ||
|
|
a6b7f6e5bb | ||
|
|
1b99f9a750 | ||
|
|
a434195318 | ||
|
|
a6a8faea78 | ||
|
|
31458320ab | ||
|
|
037a1f7f77 | ||
|
|
10d4d10ac9 | ||
|
|
00e8d509f8 | ||
|
|
c9ca14df4d | ||
|
|
841cdfc62d | ||
|
|
fc7026c076 | ||
|
|
b96581c183 | ||
|
|
4fa5d72af6 | ||
|
|
f4be581666 | ||
|
|
24fb5518d8 | ||
|
|
2e8061d62a | ||
|
|
23d70f6936 | ||
|
|
95ea88628a | ||
|
|
68b411f487 | ||
|
|
40bfbc0a44 | ||
|
|
fc9b6ea275 | ||
|
|
522f3bb3a1 | ||
|
|
743c7ceaa6 | ||
|
|
c780cd47ce | ||
|
|
54e7e01c05 | ||
|
|
7d422d11e4 | ||
|
|
5c35b60d1d | ||
|
|
94353efb3f | ||
|
|
0586a2ba47 | ||
|
|
be6081c6f7 | ||
|
|
955fb6479e | ||
|
|
1b334e8cf7 | ||
|
|
718e198ac8 | ||
|
|
3757e5a8bb | ||
|
|
d505964321 | ||
|
|
1114c1a429 | ||
|
|
f58a9c6119 | ||
|
|
e791cb2c00 | ||
|
|
f741dbb01b | ||
|
|
d5f0741e8d | ||
|
|
b265ed8313 | ||
|
|
6cb160bb26 | ||
|
|
009a3f2c0d | ||
|
|
11b3d1fb94 | ||
|
|
7a39472700 | ||
|
|
4489b48603 | ||
|
|
d2f69af964 | ||
|
|
34e9dabffc | ||
|
|
6a4f46639e | ||
|
|
0d07ff25f9 | ||
|
|
c1d9c4ef12 | ||
|
|
0227ff7a9b | ||
|
|
082b178ae3 | ||
|
|
0e695cbd6e | ||
|
|
be2ed4dc4a | ||
|
|
4777666588 | ||
|
|
5647057ecc | ||
|
|
94cb950058 | ||
|
|
8d65371bf6 | ||
|
|
c747a36ae1 | ||
|
|
e51cb65857 | ||
|
|
8fa4fdb8c8 | ||
|
|
d584857c78 | ||
|
|
f0b1d79f8b | ||
|
|
28566ad772 | ||
|
|
40c0e139d4 | ||
|
|
04f2444ea0 | ||
|
|
9f71d28afa | ||
|
|
af262fb325 | ||
|
|
243657b5aa | ||
|
|
032302edaa | ||
|
|
d4bd658d84 | ||
|
|
78843c3e06 | ||
|
|
692ba1f6b3 | ||
|
|
400a9d72ef | ||
|
|
11f8f0385a | ||
|
|
c40d15981c | ||
|
|
baa1bf21f1 | ||
|
|
3dd3122236 | ||
|
|
927ef2ccde | ||
|
|
af6eaf6737 | ||
|
|
7c543f5627 | ||
|
|
b06e35c610 | ||
|
|
842c2148d7 | ||
|
|
a2a94bd78e | ||
|
|
4452c30fc8 | ||
|
|
f462792c8e | ||
|
|
03879fdc0c | ||
|
|
389d0b95d5 | ||
|
|
6ec32e192f | ||
|
|
22c034cdca | ||
|
|
396d8c3022 | ||
|
|
a535ecbe17 | ||
|
|
fd436c3e4f | ||
|
|
e5c245ea2f | ||
|
|
3008b7c83b | ||
|
|
eca6cd3066 | ||
|
|
691a41f290 | ||
|
|
df4cf539a1 | ||
|
|
baa1167dfe | ||
|
|
d8a83ab7cf | ||
|
|
8184351b3b | ||
|
|
4a4dbbcf69 | ||
|
|
56f79efc74 | ||
|
|
ea073a9bbd | ||
|
|
c5b2ca4b20 | ||
|
|
c0f9d8d2ff | ||
|
|
497660279f | ||
|
|
625395bd26 | ||
|
|
79a7797409 | ||
|
|
3b13de3e6e | ||
|
|
7f99855527 | ||
|
|
8c29178f81 | ||
|
|
ed71000033 | ||
|
|
20860ed069 | ||
|
|
2e62f13917 | ||
|
|
1b2a83ce70 | ||
|
|
113ec5ae9e | ||
|
|
68e81828d1 | ||
|
|
543790dc83 | ||
|
|
be24060578 | ||
|
|
bdedc1c94c | ||
|
|
e2454aa898 | ||
|
|
dfa4834be3 | ||
|
|
f204249110 | ||
|
|
f4c25a6cd1 | ||
|
|
fbfbacce14 | ||
|
|
a0eed32b3f | ||
|
|
9fe9fe1bb6 | ||
|
|
192312e3ea | ||
|
|
ee46fe6ba6 | ||
|
|
58abd07a88 | ||
|
|
c246a6008e | ||
|
|
706f1b59c3 | ||
|
|
ddbc8920f7 | ||
|
|
7e3bf6868e | ||
|
|
4c7ecef577 | ||
|
|
e3da0aaad4 | ||
|
|
99e576e40c | ||
|
|
7604ce3441 | ||
|
|
a0082b5b98 | ||
|
|
c90c639348 | ||
|
|
2e188dc25a | ||
|
|
312d21cb3f | ||
|
|
4ee138be7c | ||
|
|
299aef99b3 | ||
|
|
06953e4547 | ||
|
|
7565ee8740 | ||
|
|
10377f02a3 | ||
|
|
a41e6e2c61 | ||
|
|
6b2b909d33 | ||
|
|
70cd18bffb | ||
|
|
d6be4bcad9 | ||
|
|
85530b5d8e | ||
|
|
e3848e84d3 | ||
|
|
4ec9312b10 | ||
|
|
aedf3b2455 | ||
|
|
2210ec7f71 | ||
|
|
a9bee41707 | ||
|
|
3adbfd100f | ||
|
|
8d8de4b8da | ||
|
|
099403d554 | ||
|
|
13938a6aa7 | ||
|
|
9be3a4aaf8 | ||
|
|
009e42f349 | ||
|
|
207dd3bc77 | ||
|
|
feec6b3151 | ||
|
|
bf8207f0f1 | ||
|
|
9fcbc6ee68 | ||
|
|
dcb58aaa34 | ||
|
|
7163d8ddd4 | ||
|
|
c7b24eec45 | ||
|
|
1e7098f787 | ||
|
|
b28f0d9863 | ||
|
|
b49c4f4af9 | ||
|
|
2c39aafb0b | ||
|
|
1036d9c18b | ||
|
|
f0c8cbf190 | ||
|
|
f51db4481b | ||
|
|
717eba7ab3 | ||
|
|
3cc971ba55 | ||
|
|
23b3d7483f | ||
|
|
ba03837e29 | ||
|
|
06952fbaff | ||
|
|
27be00b4cc | ||
|
|
b50a377190 | ||
|
|
1ed9cb0bec | ||
|
|
a548ede3c7 | ||
|
|
de26c09030 | ||
|
|
19aa7c2560 | ||
|
|
215e0c4cbc | ||
|
|
d484acefa4 | ||
|
|
4032efd3e8 | ||
|
|
f9d412bcca | ||
|
|
5f52063b9e | ||
|
|
87833abb42 | ||
|
|
0fcbd5e334 | ||
|
|
5b55bf5f5c | ||
|
|
b8cc1d962f | ||
|
|
762c73e2ac | ||
|
|
57cd0e9135 | ||
|
|
5e0a85bff0 | ||
|
|
d2eaef524c | ||
|
|
a98c5a3931 | ||
|
|
040da07323 | ||
|
|
34f43ec97b | ||
|
|
7e3cfe94d6 | ||
|
|
e2c3b650a1 | ||
|
|
404dfaeda7 | ||
|
|
a1ec530945 | ||
|
|
b8dfd617f2 | ||
|
|
f34ed4dc47 | ||
|
|
cd2ff0e585 | ||
|
|
449955562f | ||
|
|
41a4bbccfc | ||
|
|
87b17c001d | ||
|
|
67b7753814 | ||
|
|
b190744b77 | ||
|
|
4b603071d8 | ||
|
|
16c55f0217 | ||
|
|
c989f2fb33 | ||
|
|
6429a47b0d | ||
|
|
f8a48a3ae9 | ||
|
|
fb3272d165 | ||
|
|
be5f67906e | ||
|
|
f730023e88 | ||
|
|
50954d34db | ||
|
|
ef2d9e781f | ||
|
|
a9bb310a20 | ||
|
|
86f37556da | ||
|
|
a57617c09a | ||
|
|
63ac62cf1d | ||
|
|
ac371730fd | ||
|
|
4ed6588c80 | ||
|
|
81d20edc4c | ||
|
|
a9fc6adccf | ||
|
|
21ad94ba4e | ||
|
|
571b9f27e1 | ||
|
|
cbf9ccf062 | ||
|
|
dd8fd8f19c | ||
|
|
1535b8ee13 | ||
|
|
f2491536dd | ||
|
|
88ce0181b3 | ||
|
|
4ad2658090 | ||
|
|
8d80c5e84d | ||
|
|
bae9235103 | ||
|
|
8ae2d0d00c | ||
|
|
373b89e70c | ||
|
|
c14e18b270 | ||
|
|
68ec3afd1a | ||
|
|
8918e81256 | ||
|
|
469fd697cb | ||
|
|
20844ebfca | ||
|
|
38652076d3 | ||
|
|
f13ae47fc0 | ||
|
|
ad4ee9d5c3 | ||
|
|
03a4e900ea | ||
|
|
b52dbf2aa0 | ||
|
|
c7a22c3b53 | ||
|
|
775aae3f1e | ||
|
|
862731ba91 | ||
|
|
8c302eee51 | ||
|
|
b6d34067c4 | ||
|
|
dbe15195b7 | ||
|
|
5642aa1eb5 | ||
|
|
5dd465ccc1 | ||
|
|
ae78c3007e | ||
|
|
16211d9439 | ||
|
|
515619fe2a | ||
|
|
a7d550165d | ||
|
|
efceacd9e5 | ||
|
|
ea5ebc2d15 | ||
|
|
fba82c203c | ||
|
|
a50516af7a | ||
|
|
6056b51653 | ||
|
|
23a3170c59 | ||
|
|
e136128408 | ||
|
|
fce94e0f54 | ||
|
|
06fa65bc5d | ||
|
|
571ec5ca72 | ||
|
|
39bc0ecd46 | ||
|
|
7a5373360c | ||
|
|
15453ffef6 | ||
|
|
a25747a096 | ||
|
|
bb1ef59b52 | ||
|
|
6bb3af840d | ||
|
|
0223c74ecc | ||
|
|
c7004d7ba4 | ||
|
|
915d2e9192 | ||
|
|
df79b9367b | ||
|
|
ce3d026037 | ||
|
|
d0f6c4130b | ||
|
|
26bcf28182 | ||
|
|
272d1ccc03 | ||
|
|
6c440af24e | ||
|
|
8954520cb9 | ||
|
|
31bde74fab | ||
|
|
13c64a383c | ||
|
|
809028f11b | ||
|
|
dee9d2ba1e | ||
|
|
29d80ce061 | ||
|
|
abcd3242d8 | ||
|
|
f4762299f9 | ||
|
|
107f4309a4 | ||
|
|
d2a8df19ea | ||
|
|
29efd15534 | ||
|
|
e7fb216a8d | ||
|
|
952b96cdcb | ||
|
|
8ee82fc296 | ||
|
|
afe2bfb856 | ||
|
|
5b63e9aea0 | ||
|
|
91f70259e2 | ||
|
|
f120cacc03 | ||
|
|
aff1d782b8 | ||
|
|
b489fd8a24 | ||
|
|
47e0eb68c2 | ||
|
|
9498e25245 | ||
|
|
a33e18b589 | ||
|
|
f2dcdf2289 | ||
|
|
74c53e8a61 | ||
|
|
1feed87c10 | ||
|
|
f89742d81a | ||
|
|
340b9d603e | ||
|
|
1c0fc64243 | ||
|
|
1d5173d923 | ||
|
|
49a8bf0b9b | ||
|
|
0a7e5a41a2 | ||
|
|
43ff563429 | ||
|
|
2daf6f1f66 | ||
|
|
985f56768f | ||
|
|
35278588f5 | ||
|
|
f6545be647 | ||
|
|
f387d27582 | ||
|
|
5d8e5d943f | ||
|
|
4046f76cb2 | ||
|
|
8baeb0af2f | ||
|
|
63e0105a0f | ||
|
|
70daa57caf | ||
|
|
db0f7951a9 | ||
|
|
45a7a3066d | ||
|
|
c73a6723d7 | ||
|
|
fb55f57531 | ||
|
|
8cf4d5802a | ||
|
|
e3c042e567 | ||
|
|
5435f8927c | ||
|
|
e1e65c46ac | ||
|
|
e1f3665a8e | ||
|
|
ef09a010cf | ||
|
|
3f5d79c755 | ||
|
|
3b5468f39f | ||
|
|
5598c7cc22 | ||
|
|
d6fdb812a2 | ||
|
|
e6d5f6c612 | ||
|
|
8f10daa2bf | ||
|
|
f027153452 | ||
|
|
0ebda93a50 | ||
|
|
dc4e8950d2 | ||
|
|
0f5336028f | ||
|
|
e02341bffe | ||
|
|
ac92ff4079 | ||
|
|
a5da77bc54 | ||
|
|
0441e88b82 | ||
|
|
815f4abec0 | ||
|
|
4f9e2ff3f6 | ||
|
|
ce8dd001bf | ||
|
|
d4e90f5215 | ||
|
|
da13562890 | ||
|
|
d320075ab0 | ||
|
|
4061826da4 | ||
|
|
2854321891 | ||
|
|
c4181cdc55 | ||
|
|
327582b695 | ||
|
|
f56b9be4c5 | ||
|
|
28ccace24f | ||
|
|
13f82176e3 | ||
|
|
be4d324f6b | ||
|
|
36486caabb | ||
|
|
b3af255727 | ||
|
|
a56f726f7d | ||
|
|
24d6470f38 | ||
|
|
7e079e4c40 | ||
|
|
0d9bc03c53 | ||
|
|
7598666768 | ||
|
|
cd6f027705 | ||
|
|
0803a7f0b0 | ||
|
|
0eb956db4a | ||
|
|
76c6ae6d16 | ||
|
|
40054e3494 | ||
|
|
8927dfd538 | ||
|
|
68f734fcad | ||
|
|
af4c7f74d5 | ||
|
|
4581d1e7ce | ||
|
|
d465f61506 | ||
|
|
5cae9b9ba4 | ||
|
|
428a2d9366 | ||
|
|
1c00b54b06 | ||
|
|
6228fb91da | ||
|
|
307cf3a0ef | ||
|
|
f723a804c0 | ||
|
|
24ac19e2d6 | ||
|
|
38147d50ff | ||
|
|
9f7db10582 | ||
|
|
ed35a50e6c | ||
|
|
fae08f49cf | ||
|
|
35f5b5b2eb | ||
|
|
b785c8fccf | ||
|
|
597c3cd7f1 | ||
|
|
bbbe01ef4b | ||
|
|
ea1e1cb65f | ||
|
|
a1d31ae954 | ||
|
|
fa0ed9489a | ||
|
|
7bb7b351e0 | ||
|
|
cb45f207a6 | ||
|
|
82ffb60bdd | ||
|
|
ec38ce9a26 | ||
|
|
8279926bab | ||
|
|
ac17b0910e | ||
|
|
aae3e7ff17 | ||
|
|
4cfff98cd1 | ||
|
|
19ee50949c | ||
|
|
ec27d624c3 | ||
|
|
0dc8803ff8 | ||
|
|
e8ea1a55f9 | ||
|
|
a0cb71ca78 | ||
|
|
5c5aef3827 | ||
|
|
737a7f4d51 | ||
|
|
c3ee774d56 | ||
|
|
2d5adacc65 | ||
|
|
b7a8cc0297 | ||
|
|
317b0f79a8 | ||
|
|
4644578276 | ||
|
|
f1d450c12f | ||
|
|
6624f75ec7 | ||
|
|
8941505ea0 | ||
|
|
18b177db25 | ||
|
|
27421f3642 | ||
|
|
30f9479e85 | ||
|
|
a9f7631ab4 | ||
|
|
cb8519510f | ||
|
|
f7881bfb78 | ||
|
|
4cf4c75d5d | ||
|
|
91bcbc77b3 | ||
|
|
b1db4d35c3 | ||
|
|
060462b849 | ||
|
|
0e08c0211c | ||
|
|
e69cc2bcd5 | ||
|
|
996af7d46c | ||
|
|
e8e66f15da | ||
|
|
cd09b4a55d | ||
|
|
f4a1d76396 | ||
|
|
ab8cc168e5 | ||
|
|
5e43ef6fae | ||
|
|
caa3614f78 | ||
|
|
a81ca89ae9 | ||
|
|
5861705cd6 | ||
|
|
4e68dacad3 | ||
|
|
4f8f15a3b6 | ||
|
|
aa6b86fbdf | ||
|
|
7a18ff48ba | ||
|
|
e354de9f5e | ||
|
|
10073bc4ae | ||
|
|
6fd051b248 | ||
|
|
1cf034881e | ||
|
|
1393281c74 | ||
|
|
edf95a4b0a | ||
|
|
8887f83f7f | ||
|
|
7513d80440 | ||
|
|
67289b7cf1 | ||
|
|
a88f478fac | ||
|
|
d385661a93 | ||
|
|
e8895ba773 | ||
|
|
5a23a8d457 | ||
|
|
e01a3d8bd2 | ||
|
|
b270bd24d7 | ||
|
|
ab989ebf16 | ||
|
|
7c31b6657f | ||
|
|
ba7d322aaf | ||
|
|
537187b7f8 | ||
|
|
d22a7c7223 | ||
|
|
c9f986fa59 | ||
|
|
d7388ca5e7 | ||
|
|
df5ad62ebf | ||
|
|
41dab14020 | ||
|
|
744e166e9d | ||
|
|
5a3b93f763 | ||
|
|
656de924eb | ||
|
|
703444dd40 | ||
|
|
ff8ca18e8f | ||
|
|
1f90be1ae1 | ||
|
|
ee95c2eb0b | ||
|
|
6606f3f0dc | ||
|
|
bcd97f7247 | ||
|
|
271e7f8f4c | ||
|
|
e78d8594a8 | ||
|
|
659360b366 | ||
|
|
6c1c86ea79 | ||
|
|
5da36b7199 | ||
|
|
294452eef7 | ||
|
|
3ac0e28d9c | ||
|
|
ce22b69a2f | ||
|
|
8b31a998ed | ||
|
|
dad97bc104 | ||
|
|
e20e43eee0 | ||
|
|
aafd4e757d | ||
|
|
575fc26bd7 | ||
|
|
5743eb2575 | ||
|
|
31972ded93 | ||
|
|
28321a0f94 | ||
|
|
406dfbc770 | ||
|
|
c59595cefc | ||
|
|
7108ee1ba0 | ||
|
|
cf8e68f7a0 | ||
|
|
a9510c2209 | ||
|
|
b2be5943a8 | ||
|
|
8f19fe292e | ||
|
|
d3e7668d0a | ||
|
|
88e67a74e5 | ||
|
|
7fecda1a23 | ||
|
|
56b6fa88f9 | ||
|
|
e847cfe4bc | ||
|
|
1a854ae3ba | ||
|
|
c75180bf95 | ||
|
|
d496450b84 | ||
|
|
d2636ed133 | ||
|
|
59de0c2085 | ||
|
|
4b7df29bd1 | ||
|
|
b099ba6a29 | ||
|
|
164069e194 | ||
|
|
b3e4ff8613 | ||
|
|
3eb5ec3543 | ||
|
|
c3c698a615 | ||
|
|
ac6d2f3e83 | ||
|
|
d1f1b8a43a | ||
|
|
85586a621c | ||
|
|
1a384a334f | ||
|
|
8901afded5 | ||
|
|
ab12703a11 | ||
|
|
9992b4c964 | ||
|
|
9a2dbd08cd | ||
|
|
5f92a00b71 | ||
|
|
7bd9d51217 | ||
|
|
80c649aa40 | ||
|
|
6c8fe2cc53 | ||
|
|
dcc7167d75 | ||
|
|
e3a52e4039 | ||
|
|
498f6162f7 | ||
|
|
33d85d3670 | ||
|
|
afbf5b9633 | ||
|
|
a8505be6c0 | ||
|
|
4a07632569 | ||
|
|
d4f0589c39 | ||
|
|
a9989d46fc | ||
|
|
99cf598c0c | ||
|
|
a6af22b8f0 | ||
|
|
0961d61a88 | ||
|
|
7b76a2d749 | ||
|
|
b516f1d3ec | ||
|
|
8fdef7a1f9 | ||
|
|
10258db4ae | ||
|
|
621c9523cf | ||
|
|
c415adab28 | ||
|
|
7fef1048b3 | ||
|
|
1e7aaeeeed | ||
|
|
c5b4564001 | ||
|
|
a9127c8d79 | ||
|
|
a0f7a5c70f | ||
|
|
ecf3cae35b | ||
|
|
d553bc8014 | ||
|
|
a1553d3632 | ||
|
|
bb42ae1b4a | ||
|
|
61ac2efe0e | ||
|
|
1c0a3ec413 | ||
|
|
8b7e93385b | ||
|
|
c742624054 | ||
|
|
8011f0615d | ||
|
|
8096b2198f | ||
|
|
3556bd5283 | ||
|
|
26710694af | ||
|
|
0f397eeb55 | ||
|
|
bf929398a9 | ||
|
|
4f8a0f753e | ||
|
|
7db5da9566 | ||
|
|
4d1389805c | ||
|
|
ee87e2b946 | ||
|
|
6356d78768 | ||
|
|
afdf7e740e | ||
|
|
51ce3ddf78 | ||
|
|
192186056e | ||
|
|
336a7febd7 | ||
|
|
63e73d1b73 | ||
|
|
a02ab9a723 | ||
|
|
95f15ab9dd | ||
|
|
5d0ea0066a | ||
|
|
9ff6b2da9b | ||
|
|
6ac7e27847 | ||
|
|
4ed1c5e747 | ||
|
|
bae3bc096f | ||
|
|
9d73683de2 | ||
|
|
f5fec0ab71 | ||
|
|
9909ab10c4 | ||
|
|
65cff01fee | ||
|
|
10190a3012 | ||
|
|
79ab696f4e | ||
|
|
cb603682e4 | ||
|
|
c986a06bf7 | ||
|
|
e2843a6cee | ||
|
|
ea1f239807 | ||
|
|
8d7618146a | ||
|
|
eb9e419bb0 | ||
|
|
f98f71ac26 | ||
|
|
03baaaebcb | ||
|
|
cbca954508 | ||
|
|
22ba6cc406 | ||
|
|
6bd172acb4 | ||
|
|
818ba4416f | ||
|
|
adff12841c | ||
|
|
480c306591 | ||
|
|
cbd1481cb7 | ||
|
|
d1c1871222 | ||
|
|
15a94b8fb0 | ||
|
|
66be54e6a7 | ||
|
|
62c85cc2eb | ||
|
|
1ae05a9ebc | ||
|
|
3457c70f30 | ||
|
|
c1ec9126da | ||
|
|
398da2fac7 | ||
|
|
47f33d6346 | ||
|
|
2cad82d537 | ||
|
|
8d06d78537 | ||
|
|
b61be000de | ||
|
|
9ca6de6e7a | ||
|
|
5c03c25e96 | ||
|
|
23843163ad | ||
|
|
8b07fbbedc | ||
|
|
5bf55220d4 | ||
|
|
0e1de3d6e8 | ||
|
|
3a7ba3675b | ||
|
|
5c0deb5bdb | ||
|
|
50dcbc2b01 | ||
|
|
90d72f7843 | ||
|
|
90ee59c70d | ||
|
|
59eda11c1b | ||
|
|
78684a424f | ||
|
|
4a936dda6e | ||
|
|
094d4b99a4 | ||
|
|
382268308e | ||
|
|
97315d27b9 | ||
|
|
26ae573b72 | ||
|
|
803c44d783 | ||
|
|
90f3f1037a | ||
|
|
ce39a751d9 | ||
|
|
ceebf7d32d | ||
|
|
8da59bf0ac | ||
|
|
d25979502a | ||
|
|
549bc3bf9f | ||
|
|
22b2f325e0 | ||
|
|
6615d1b90c | ||
|
|
8f045c4254 | ||
|
|
a4434349e5 | ||
|
|
01272be25f | ||
|
|
be0beed403 | ||
|
|
453d2abed5 | ||
|
|
57e9ccbef0 | ||
|
|
989124772b | ||
|
|
72400e4b91 | ||
|
|
900cba29a7 | ||
|
|
f177a65c1e | ||
|
|
b6baf9016d | ||
|
|
86ac6e8044 | ||
|
|
66d8fb95db | ||
|
|
22da8d9ba2 | ||
|
|
819e9c1b16 | ||
|
|
dd4b2e8bc2 | ||
|
|
e2f7ac2017 | ||
|
|
31b5cf6926 | ||
|
|
25fe3035c2 | ||
|
|
0cf56823cd | ||
|
|
c2f36968c3 | ||
|
|
a508c7f53e | ||
|
|
48de68031d | ||
|
|
81ef85af82 | ||
|
|
16b65d7dbe | ||
|
|
5a98e6511b | ||
|
|
2418f08e22 | ||
|
|
80a821bc20 | ||
|
|
378f78bd87 | ||
|
|
f010591e19 | ||
|
|
5274abdcca | ||
|
|
48f9e8c5c8 | ||
|
|
5c02117fde | ||
|
|
bc56a188f8 | ||
|
|
b6df1b22ab | ||
|
|
0fbf2dd5bb | ||
|
|
38c126d11a | ||
|
|
7dff602e5e | ||
|
|
e401f32815 | ||
|
|
12e94b70a7 | ||
|
|
884de3959c | ||
|
|
fe12325e50 | ||
|
|
bea86f3f79 | ||
|
|
7a5f3667da | ||
|
|
0813788c98 | ||
|
|
b1ca73e7f0 | ||
|
|
ebf9e9b1a3 | ||
|
|
b0abab7a1d | ||
|
|
995bb493df | ||
|
|
1b2375fc84 | ||
|
|
b7315bcb5a | ||
|
|
2c9ebdaa69 | ||
|
|
fbd9e5b4d7 | ||
|
|
b9a3425b6d | ||
|
|
d4742c611b | ||
|
|
c645a590aa | ||
|
|
275a7fe63f | ||
|
|
0ff16d8312 | ||
|
|
1cb31d6c7e | ||
|
|
8a6eb553df | ||
|
|
946af8b9ee | ||
|
|
098a1f647e | ||
|
|
c9681dc430 | ||
|
|
ff0b8b2d53 | ||
|
|
75f520d43a | ||
|
|
65209748ba | ||
|
|
cd604ef07b | ||
|
|
51da8bc531 | ||
|
|
2374ba12bd | ||
|
|
0a75aaec25 | ||
|
|
a8c286ae83 | ||
|
|
9cbdfc7764 | ||
|
|
cb1423436f | ||
|
|
2fb391795a | ||
|
|
9ec20f2d8f | ||
|
|
9323ca5136 | ||
|
|
978e6072ab | ||
|
|
d0e3869d54 | ||
|
|
15c7e956f2 | ||
|
|
ed61545ec7 | ||
|
|
1aac5becdc | ||
|
|
4bca26debc | ||
|
|
d6eecd1637 | ||
|
|
00e7620d2e | ||
|
|
d657283aad | ||
|
|
70a879ea94 | ||
|
|
591ee22472 | ||
|
|
956b05d39d | ||
|
|
5bdad6d4cb | ||
|
|
29a6ac6ed7 | ||
|
|
8f7f091e9b | ||
|
|
63dfe7628b | ||
|
|
ce507e7851 | ||
|
|
a9cd76173e | ||
|
|
44f8ffb434 | ||
|
|
28c395f111 | ||
|
|
39df68c38e | ||
|
|
b33ca9225a | ||
|
|
bd137afecf | ||
|
|
a3b9bed8c2 | ||
|
|
0a157739bc | ||
|
|
c46b08ad5e | ||
|
|
754e6193a4 | ||
|
|
56b49fe2dd | ||
|
|
36a7215f94 | ||
|
|
702247affd | ||
|
|
e752b1f8e5 | ||
|
|
920eee36e3 | ||
|
|
a5070a5d98 | ||
|
|
ccb5aefa61 | ||
|
|
378b08e37c | ||
|
|
5763483c91 | ||
|
|
559f8ee095 | ||
|
|
4382ef360c | ||
|
|
0cb576cf1a | ||
|
|
dee4d047b4 | ||
|
|
2520cc7bb9 | ||
|
|
192c31efe0 | ||
|
|
a1d8ebc2d2 | ||
|
|
14a9de2147 | ||
|
|
a760a9a3f1 | ||
|
|
efd14e1c7a | ||
|
|
6019c46cee | ||
|
|
ec6acfbc1c | ||
|
|
e925dbaad6 | ||
|
|
8321adf0bc | ||
|
|
e1c5e9e874 | ||
|
|
0aec581714 | ||
|
|
b77b8623d1 | ||
|
|
5ab986d6d9 | ||
|
|
09b8332236 | ||
|
|
d05345abc0 | ||
|
|
804c369f0d | ||
|
|
8f67fc886c | ||
|
|
ca3b1a9b30 | ||
|
|
63c1dbb3ed | ||
|
|
9a424dfe29 | ||
|
|
0a6eb596bb | ||
|
|
34452376db | ||
|
|
53a90a59c5 | ||
|
|
ec491ebd83 | ||
|
|
cdc41c305e | ||
|
|
6cf67b399c | ||
|
|
dc3c56bccc | ||
|
|
4657f2039a | ||
|
|
b0082fbd0d | ||
|
|
ede1b4df11 | ||
|
|
d78a3d1f8a | ||
|
|
6152555f26 | ||
|
|
bbad505044 | ||
|
|
11c5429184 | ||
|
|
4e865c4525 | ||
|
|
2fa785a539 | ||
|
|
296a8449c9 | ||
|
|
f20213ff10 | ||
|
|
8a7067ee24 | ||
|
|
a3024e9f5a | ||
|
|
86e651f5e7 | ||
|
|
409710b2b1 | ||
|
|
14a406a276 | ||
|
|
28a283b1c1 | ||
|
|
ccf298a148 | ||
|
|
914b600af4 | ||
|
|
4944994667 | ||
|
|
3a487578a5 | ||
|
|
39eeccb16a | ||
|
|
32acd3b9d1 | ||
|
|
c57baae477 | ||
|
|
4a6ed633b9 | ||
|
|
2ab1845547 | ||
|
|
f4d2e1f20c | ||
|
|
81dca1f690 | ||
|
|
2b331fd68f | ||
|
|
cc77e4dba7 | ||
|
|
620a13a308 | ||
|
|
42d4ba09d7 | ||
|
|
ca071fa52f | ||
|
|
d38e5dec7b | ||
|
|
e5db38f7c0 | ||
|
|
68a29730c0 | ||
|
|
5c33c4d341 | ||
|
|
a1d6270089 | ||
|
|
1968175b00 | ||
|
|
cf1e2aeeba | ||
|
|
199b0b9f57 | ||
|
|
87a0daa465 | ||
|
|
c2af90b58f | ||
|
|
62f01453af | ||
|
|
375d6ee331 | ||
|
|
222ca2915b | ||
|
|
5ca848f9fe | ||
|
|
68d878ff6b | ||
|
|
782a7b418a | ||
|
|
724d7854ad | ||
|
|
f8e64d17e8 | ||
|
|
3b40799000 | ||
|
|
709964ca92 | ||
|
|
d2cdedc610 | ||
|
|
b7d0730343 | ||
|
|
30b4ea7d49 | ||
|
|
546dadbd06 | ||
|
|
76edf902de | ||
|
|
7c4caef5e7 | ||
|
|
068024134c | ||
|
|
538ab57b6e | ||
|
|
fd6d9148f3 | ||
|
|
f033f59755 | ||
|
|
7168c6dd69 | ||
|
|
f121d41c2f | ||
|
|
e56e774eac | ||
|
|
6d9b0918a3 | ||
|
|
d445418611 | ||
|
|
6d15a51c9a | ||
|
|
42a615efdd | ||
|
|
54cd1f79a6 | ||
|
|
8ed8f46374 | ||
|
|
dd3a2996a4 | ||
|
|
bf1f90a96a | ||
|
|
2d6200231a | ||
|
|
032cd23304 | ||
|
|
de4c0a9e1c | ||
|
|
e33f8e8920 | ||
|
|
22615c7921 | ||
|
|
9d8809c580 | ||
|
|
96b92c98ff | ||
|
|
07939acecd | ||
|
|
30abcb2563 | ||
|
|
35ce8f2b8d | ||
|
|
d6453eab38 | ||
|
|
e0964d07ea | ||
|
|
fc359f1956 | ||
|
|
322261d65d | ||
|
|
bd1163c439 | ||
|
|
e203a8c706 | ||
|
|
6a1ba2af74 | ||
|
|
22569e64df | ||
|
|
dcafe41cde | ||
|
|
dd2adc08a3 | ||
|
|
d7534d2673 | ||
|
|
0a59920025 | ||
|
|
77602a8de4 | ||
|
|
65b3fde97c | ||
|
|
b690148452 | ||
|
|
4c7bc9ada6 | ||
|
|
432651489f | ||
|
|
82aa232a37 | ||
|
|
19b13bf7a7 | ||
|
|
f7e25d807d | ||
|
|
cf05316b95 | ||
|
|
001c4386b5 | ||
|
|
572527f8cb | ||
|
|
b4252beda6 | ||
|
|
d82ee16e0c | ||
|
|
e4d65c07ce | ||
|
|
86fcb78cc3 | ||
|
|
5beb422d75 | ||
|
|
53679879ca | ||
|
|
a8ad766182 | ||
|
|
cbb2d30f79 | ||
|
|
c5e00bcec6 | ||
|
|
51535d374d | ||
|
|
1e057e6c35 | ||
|
|
b23e8ab862 | ||
|
|
0f7f13dfb2 | ||
|
|
aa19ccda1d | ||
|
|
cd0129e780 | ||
|
|
506c9023e6 | ||
|
|
d47c25ea4c | ||
|
|
010651073c | ||
|
|
76364e3799 | ||
|
|
f9fd0a0203 | ||
|
|
edbff83fd6 | ||
|
|
8dfbde5d16 | ||
|
|
888991f8c1 | ||
|
|
ece03922d6 | ||
|
|
47bb827e6e | ||
|
|
a56003d847 | ||
|
|
61022c398c | ||
|
|
00bd8cc525 | ||
|
|
cf6a232aef | ||
|
|
59d1a45ef0 | ||
|
|
0b5f9fcb48 | ||
|
|
f713ffd6a1 | ||
|
|
22ba9d81d4 | ||
|
|
309bc98d7f | ||
|
|
9b8646a583 | ||
|
|
48d1b87ab8 | ||
|
|
c5f849d846 | ||
|
|
31fbb6e4f5 | ||
|
|
4d9a88e999 | ||
|
|
252e8484a8 | ||
|
|
1b89203932 | ||
|
|
2263c6a618 | ||
|
|
673cb3ee21 | ||
|
|
b4ecd504e3 | ||
|
|
f226f29428 | ||
|
|
b87a284390 | ||
|
|
f63dcd0d9c | ||
|
|
7f5563d581 | ||
|
|
d8a61a920e | ||
|
|
5a4900da8e | ||
|
|
677c30057a | ||
|
|
26113e091b | ||
|
|
1b5e98f593 | ||
|
|
0aa5201947 | ||
|
|
e3951baa3f | ||
|
|
9f9dbbab9e | ||
|
|
d546bbadbd | ||
|
|
2b7f25054f | ||
|
|
bb3f6bcf7e | ||
|
|
41da7175d1 | ||
|
|
446763b58a | ||
|
|
3e9337a0fc | ||
|
|
028806165b | ||
|
|
e4be42edbb | ||
|
|
230fa1f3bb | ||
|
|
d74653bbad | ||
|
|
38049b0897 | ||
|
|
b4af646929 | ||
|
|
b21ec73a52 | ||
|
|
c595844f0e | ||
|
|
fe8ee7c7b3 | ||
|
|
cd382c6bc0 | ||
|
|
e68296c293 | ||
|
|
cc189feae5 | ||
|
|
18e19027a1 | ||
|
|
2d2e0e4757 | ||
|
|
a9f50d79f9 | ||
|
|
0ccd31bee0 | ||
|
|
3ea82b2bcd | ||
|
|
6dad7b3ced | ||
|
|
f96ebd2b07 | ||
|
|
b8d0e7a3ac | ||
|
|
14cca3d497 | ||
|
|
c343ca0cc3 | ||
|
|
527d371bda | ||
|
|
b87a800a9a | ||
|
|
e406993ed1 | ||
|
|
eeff935fc9 | ||
|
|
0791394f1a | ||
|
|
082a407b06 | ||
|
|
8a89b49df1 | ||
|
|
2314b9cbab | ||
|
|
d0cca85c83 | ||
|
|
6a7a5cbcba | ||
|
|
ecccc82cc8 | ||
|
|
02693489fe | ||
|
|
0f5dba5828 | ||
|
|
e528d4c4b7 | ||
|
|
52a3af6acf | ||
|
|
dcefea9958 | ||
|
|
59121ff834 | ||
|
|
7f5bb6d472 | ||
|
|
639c1a508c | ||
|
|
417a26fc64 | ||
|
|
210ccd0063 | ||
|
|
1bf0162d38 | ||
|
|
e93027fd7e | ||
|
|
807060706f | ||
|
|
a317f88d3c | ||
|
|
e17a7f0701 | ||
|
|
db325eb9fe | ||
|
|
b41a4c8c3b | ||
|
|
73b4d11d18 | ||
|
|
8162b87287 | ||
|
|
70e9e4f3ee | ||
|
|
e61ae376b3 | ||
|
|
2d57b0e926 | ||
|
|
ae683af07a | ||
|
|
3c4f6a9171 | ||
|
|
39986e546c | ||
|
|
2e81a80f7b | ||
|
|
fcb3aa38c8 | ||
|
|
00a38d8ec5 | ||
|
|
07a0ab4227 | ||
|
|
d4a9a2c543 | ||
|
|
2b523fc60d | ||
|
|
0c26928236 | ||
|
|
8401e56a22 | ||
|
|
5109f9ae0b | ||
|
|
c9bc06669a | ||
|
|
a83fb2672c | ||
|
|
8f9ecb44d9 | ||
|
|
bfcc09a8de | ||
|
|
f8a8c997db | ||
|
|
132b996f30 | ||
|
|
12f970cdfb | ||
|
|
9afa963225 | ||
|
|
ed368d0d51 | ||
|
|
21f21d34ba | ||
|
|
f37823c809 | ||
|
|
6eaefcff5e | ||
|
|
79235c1cc3 | ||
|
|
29135f014b | ||
|
|
13c998fb8d | ||
|
|
71bfd0d636 | ||
|
|
51e99e0f5a | ||
|
|
66e7beefc4 | ||
|
|
f2b10c35b7 | ||
|
|
e951eba96c | ||
|
|
9fe18da7a3 | ||
|
|
a14fdead14 | ||
|
|
9a671a4991 | ||
|
|
8f5e7b124a | ||
|
|
5f7464d015 | ||
|
|
238dd6c1d0 | ||
|
|
82e4e54edc | ||
|
|
9946cbb9da | ||
|
|
2474adb23a | ||
|
|
f40757bb67 | ||
|
|
bc29479930 | ||
|
|
4ec78edaa3 | ||
|
|
aa0271158d | ||
|
|
c0aa5bfe17 | ||
|
|
3f8e6a8cc8 | ||
|
|
ef0316fc2e | ||
|
|
7274efab15 | ||
|
|
e44b62b6b2 | ||
|
|
31c041d435 | ||
|
|
35f47371ed | ||
|
|
c5412e1620 | ||
|
|
a9b4c52811 | ||
|
|
5ce40b6ac8 | ||
|
|
b93dcbf46f | ||
|
|
8051a2bc98 | ||
|
|
78d8b221fc | ||
|
|
d51cada284 | ||
|
|
389eef9e88 | ||
|
|
270fb0c50d | ||
|
|
e7e9dfee88 | ||
|
|
3bafae276d | ||
|
|
cfebe2927d | ||
|
|
1d4294a845 | ||
|
|
12cfdd9864 | ||
|
|
add930c517 | ||
|
|
32972978be | ||
|
|
c8bad3550e | ||
|
|
ecc55d789d | ||
|
|
88555e2c20 | ||
|
|
ec2bfcd302 | ||
|
|
f1f81ed4c4 | ||
|
|
87933cca26 | ||
|
|
2dcd8624a2 | ||
|
|
7fcef76bbe | ||
|
|
2a5c4e938d | ||
|
|
274eae27ef | ||
|
|
207220bc50 | ||
|
|
fb8c4439c7 | ||
|
|
894be9c41e | ||
|
|
0a4bff8963 | ||
|
|
d515f3e279 |
+19
@@ -1,5 +1,24 @@
|
||||
*.o
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
*~
|
||||
*.so
|
||||
*.gox
|
||||
*.a
|
||||
*.dll
|
||||
*.key
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
/core/config_py.c
|
||||
|
||||
/t/ring/target
|
||||
|
||||
core/dot_h.c
|
||||
|
||||
+# coverity
|
||||
+/cov-int/
|
||||
+uwsgi.tar.xz
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
|
||||
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
|
||||
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
|
||||
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
|
||||
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
|
||||
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
|
||||
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
|
||||
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
|
||||
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
|
||||
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
|
||||
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
|
||||
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
|
||||
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
|
||||
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
|
||||
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
|
||||
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
|
||||
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
|
||||
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
|
||||
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
|
||||
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
|
||||
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
|
||||
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
|
||||
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
|
||||
+9
-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>
|
||||
@@ -22,3 +22,11 @@ Aarni Koskela
|
||||
C Anthony Risinger
|
||||
Stephen Pierce
|
||||
Mingli Yuan
|
||||
Natanael Copa
|
||||
Roberto Leandrini
|
||||
Ryan Petrello
|
||||
Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
Adriano Di Luzio (adriano@unbit.it)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
----------------------------------------------------------------------
|
||||
|
||||
LINKING EXCEPTION
|
||||
|
||||
In addition to the permissions in the GNU General Public License,
|
||||
the authors give you unlimited permission to link the compiled
|
||||
version of this library into combinations with other programs,
|
||||
and to distribute those combinations without any restriction
|
||||
coming from the use of this file. (The General Public License
|
||||
restrictions do apply in other respects; for example, they cover
|
||||
modification of the file, and distribution when not linked into
|
||||
a combined executable.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
PYTHON := python
|
||||
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
$(PYTHON) uwsgiconfig.py --clean
|
||||
|
||||
check:
|
||||
python uwsgiconfig.py --check
|
||||
$(PYTHON) uwsgiconfig.py --check
|
||||
|
||||
plugin.%:
|
||||
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
|
||||
|
||||
%:
|
||||
$(PYTHON) uwsgiconfig.py --build $@
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
surprise i am empty !
|
||||
The uWSGI project
|
||||
|
||||
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
|
||||
For commercial support check: http://unbit.com/
|
||||
|
||||
+124
-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);
|
||||
@@ -217,6 +222,82 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
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
|
||||
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -224,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;
|
||||
@@ -235,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);
|
||||
|
||||
@@ -282,12 +365,13 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int finish = 0;
|
||||
while(!finish) {
|
||||
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))) {
|
||||
|| (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) {
|
||||
@@ -303,21 +387,46 @@ 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);
|
||||
|
||||
// found the last brigade?
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) finish = 1;
|
||||
|
||||
// do not pass chunk if it is zero_sized
|
||||
apr_brigade_length(pass_bb, 0, &readbytes);
|
||||
|
||||
if ((readbytes > 0 && ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS) || c->aborted) {
|
||||
finish = 1;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -337,7 +446,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
|
||||
+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
|
||||
|
||||
@@ -7,7 +7,7 @@ filename = sys.argv[1]
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
os.write(1, f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
os.write(1, (struct.pack("<Q", size)))
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
object file for embedded files will be put here
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy,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
|
||||
+1
-11
@@ -1,29 +1,19 @@
|
||||
[uwsgi]
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
ssl = auto
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
alarm = auto
|
||||
ipv6 = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires, router_metrics, transformation_template, stats_pusher_socket
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi,coroae
|
||||
inherit = base
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
# pypy,jvm,ring,jwsgi
|
||||
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
|
||||
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
|
||||
inherit = base
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gccgo
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
@@ -1,5 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gridfs
|
||||
inherit = base
|
||||
@@ -0,0 +1,29 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
yaml = false
|
||||
json = false
|
||||
ssl = false
|
||||
pcre = false
|
||||
routing = false
|
||||
debug = false
|
||||
unbit = false
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin =
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,29 @@
|
||||
[uwsgi]
|
||||
xml = libxml2
|
||||
yaml = libyaml
|
||||
json = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /usr/lib/libuwsgi.so
|
||||
append_version = ubuntu
|
||||
plugin_dir = /usr/lib/uwsgi
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = pypy
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,6 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
plugins = jvm,ring
|
||||
plugin_dir = .
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rados
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack,rbthreads,fiber
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = jvm,servlet
|
||||
inherit = base
|
||||
+14
-11
@@ -1,26 +1,29 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
xml = expat
|
||||
yaml = embedded
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ldap = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
alarm = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /opt/unbit/bin/uwsgi
|
||||
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
|
||||
append_version = unbit
|
||||
plugin_dir = /opt/unbit/uwsgi_plugins
|
||||
plugin_dir = /opt/unbit/uwsgi19/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
json = false
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_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 =
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = v8
|
||||
inherit = base
|
||||
@@ -1 +0,0 @@
|
||||
the uwsgi handler is included in the official Cherokee distribution
|
||||
@@ -0,0 +1,24 @@
|
||||
require 'socket'
|
||||
require 'openssl'
|
||||
|
||||
secret = 'ciaociao'
|
||||
iv = ''
|
||||
address = '127.0.0.1'
|
||||
port = 1717
|
||||
algo = 'bf-cbc'
|
||||
|
||||
s = UDPSocket.new
|
||||
s.bind(address, port)
|
||||
cipher = OpenSSL::Cipher.new(algo)
|
||||
cipher.decrypt
|
||||
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
|
||||
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
|
||||
|
||||
loop do
|
||||
msg, sender = s.recvfrom(8192)
|
||||
cipher.reset
|
||||
begin
|
||||
puts cipher.update(msg) + cipher.final
|
||||
rescue
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Greenlets support
|
||||
|
||||
simply --pypy-exec this file to enable PyPy's greenlet mode
|
||||
|
||||
Example:
|
||||
|
||||
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
|
||||
"""
|
||||
|
||||
import greenlet
|
||||
|
||||
uwsgi_pypy_greenlets = {}
|
||||
|
||||
def uwsgi_pypy_greenlet_wrapper():
|
||||
lib.async_schedule_to_req_green()
|
||||
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_greenlet_schedule():
|
||||
id = lib.uwsgi.wsgi_req.async_id
|
||||
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
|
||||
|
||||
# generate a new greenlet
|
||||
if not lib.uwsgi.wsgi_req.suspended:
|
||||
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
|
||||
lib.uwsgi.wsgi_req.suspended = 1
|
||||
|
||||
# this is called in the main stack
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
|
||||
|
||||
# let's switch
|
||||
uwsgi_pypy_greenlets[id].switch()
|
||||
|
||||
# back to the main stack
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(ffi.NULL)
|
||||
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_greenlet_switch(wsgi_req):
|
||||
id = wsgi_req.async_id
|
||||
modifier1 = wsgi_req.uh.modifier1;
|
||||
|
||||
# this is called in the current greenlet
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(wsgi_req)
|
||||
|
||||
uwsgi_pypy_main_greenlet.switch()
|
||||
|
||||
# back to the greenlet
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(wsgi_req)
|
||||
|
||||
# update current running greenlet
|
||||
lib.uwsgi.wsgi_req = wsgi_req
|
||||
|
||||
if lib.uwsgi.async <= 1:
|
||||
raise Exception("pypy greenlets require async mode !!!")
|
||||
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
|
||||
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
|
||||
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
|
||||
@@ -0,0 +1,15 @@
|
||||
# uWSGI - Emperor
|
||||
#
|
||||
|
||||
description "uWSGI Emperor"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
env VASSALS=/etc/uwsgi
|
||||
|
||||
exec $BINPATH --emperor $VASSALS --logto $LOGTO
|
||||
@@ -11,7 +11,6 @@ respawn
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
# --die-on-term could be a good idea
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
# --die-on-term is upstart friendly
|
||||
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
|
||||
|
||||
Binary file not shown.
+161
-34
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
|
||||
uwsgi_route_signal(uai->data8);
|
||||
}
|
||||
|
||||
// simply log an alarm
|
||||
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
if (msg[len-1] != '\n') {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_verbose("ALARM: %s %.*s\n", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("ALARM: %.*s\n", len, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_verbose("ALARM: %s %.*s", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("ALARM: %.*s", len, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run a command on alarm
|
||||
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = uai->arg;
|
||||
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
|
||||
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
|
||||
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
|
||||
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
|
||||
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
|
||||
}
|
||||
|
||||
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
|
||||
@@ -160,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
|
||||
// map instances to the log
|
||||
char *list = uwsgi_str(alarms);
|
||||
char *p = strtok(list, ",");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) {
|
||||
free(list);
|
||||
@@ -181,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
else {
|
||||
ual->alarms = uall;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
@@ -189,21 +212,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
|
||||
// add uwsgi_alarm_fd;
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
event_queue_add_fd_read(ut->queue, uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
if (interesting_fd == ut->pipe[1]) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
}
|
||||
}
|
||||
// check for alarm_fd
|
||||
else {
|
||||
uafd = uwsgi.alarm_fds;
|
||||
int fd_read = 0;
|
||||
while(uafd) {
|
||||
if (interesting_fd == uafd->fd) {
|
||||
if (fd_read) goto raise;
|
||||
size_t remains = uafd->buf_len;
|
||||
while(remains) {
|
||||
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("[uwsgi-alarm-fd]/read()");
|
||||
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
|
||||
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
|
||||
break;
|
||||
}
|
||||
remains-=len;
|
||||
}
|
||||
fd_read = 1;
|
||||
raise:
|
||||
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
|
||||
}
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +299,37 @@ void uwsgi_alarms_init() {
|
||||
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
|
||||
// map alarm file descriptors
|
||||
usl = uwsgi.alarm_fd_list;
|
||||
while(usl) {
|
||||
char *space0 = strchr(usl->value, ' ');
|
||||
if (!space0) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space0 = 0;
|
||||
size_t buf_len = 1;
|
||||
char *space1 = strchr(space0+1, ' ');
|
||||
if (!space1) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *colon = strchr(space0+1, ':');
|
||||
if (colon) {
|
||||
buf_len = strtoul(colon+1, NULL, 10);
|
||||
*colon = 0;
|
||||
}
|
||||
int fd = atoi(space0+1);
|
||||
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
|
||||
*space0 = ' ';
|
||||
*space1 = ' ';
|
||||
if (colon) {
|
||||
*colon = ':';
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
@@ -276,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) {
|
||||
@@ -285,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;
|
||||
@@ -310,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;
|
||||
@@ -329,14 +424,46 @@ 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;
|
||||
uwsgi_alarm_trigger_uai(uai, msg, 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()");
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
|
||||
if (!uai) {
|
||||
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!buf_len) buf_len = 1;
|
||||
|
||||
while(uafd) {
|
||||
// check if an equal alarm has been added
|
||||
if (uafd->fd == fd && uafd->alarm == uai) {
|
||||
return uafd;
|
||||
}
|
||||
old_uafd = uafd;
|
||||
uafd = uafd->next;
|
||||
}
|
||||
|
||||
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
|
||||
uafd->fd = fd;
|
||||
uafd->buf = uwsgi_malloc(buf_len);
|
||||
uafd->buf_len = buf_len;
|
||||
uafd->msg = msg;
|
||||
uafd->msg_len = msg_len;
|
||||
uafd->alarm = uai;
|
||||
|
||||
if (!old_uafd) {
|
||||
uwsgi.alarm_fds = uafd;
|
||||
}
|
||||
else {
|
||||
old_uafd->next = uafd;
|
||||
}
|
||||
|
||||
// avoid the fd to be closed
|
||||
uwsgi_add_safe_fd(fd);
|
||||
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
|
||||
|
||||
return uafd;
|
||||
}
|
||||
|
||||
+223
-113
@@ -2,6 +2,24 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general-purpose async loop engine (it expects a coroutine-based approach)
|
||||
|
||||
You can see it as an hub holding the following structures:
|
||||
|
||||
1) the runqueue, cores ready to be run are appended to this list
|
||||
|
||||
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
|
||||
|
||||
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
|
||||
|
||||
|
||||
IMPORTANT: this is not a callback-based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
// this is called whenever a new connection is ready, but there are no cores to handle it
|
||||
void uwsgi_async_queue_is_full(time_t now) {
|
||||
if (now > uwsgi.async_queue_is_full) {
|
||||
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
|
||||
@@ -10,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
|
||||
}
|
||||
|
||||
void uwsgi_async_init() {
|
||||
int i;
|
||||
|
||||
uwsgi.async_queue = event_queue_init();
|
||||
|
||||
@@ -22,13 +39,9 @@ void uwsgi_async_init() {
|
||||
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
// optimization, this array maps file descriptor to requests
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +65,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
if (u_request == uwsgi.async_runqueue) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
|
||||
@@ -61,33 +74,33 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
}
|
||||
|
||||
free(u_request);
|
||||
|
||||
uwsgi.async_runqueue_cnt--;
|
||||
}
|
||||
|
||||
static void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_async_request *uar;
|
||||
// do not push the same request in the runqueue
|
||||
struct uwsgi_async_request *uar = uwsgi.async_runqueue;
|
||||
while(uar) {
|
||||
if (uar->wsgi_req == wsgi_req) return;
|
||||
uar = uar->next;
|
||||
}
|
||||
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = NULL;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
|
||||
if (uwsgi.async_runqueue == NULL) {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
uwsgi.async_runqueue = uar;
|
||||
}
|
||||
else {
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
}
|
||||
|
||||
uwsgi.async_runqueue_cnt++;
|
||||
|
||||
if (uwsgi.async_runqueue_last) {
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
}
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
}
|
||||
|
||||
struct wsgi_request *find_first_available_wsgi_req() {
|
||||
@@ -103,11 +116,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
|
||||
return wsgi_req;
|
||||
}
|
||||
|
||||
void async_reset_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *uaf = wsgi_req->waiting_fds;
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
struct uwsgi_async_fd *current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
}
|
||||
|
||||
static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for (;;) {
|
||||
@@ -121,20 +151,9 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
uaf = wsgi_req->waiting_fds;
|
||||
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
// put th request in the runqueue
|
||||
// reset the request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
@@ -146,12 +165,17 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -179,7 +203,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
|
||||
static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -193,8 +221,49 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
|
||||
// reset already registered fd
|
||||
async_reset_request(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wsgi_req->async_ready_fd) {
|
||||
*fd = wsgi_req->async_last_ready_fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
|
||||
}
|
||||
@@ -203,12 +272,17 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -238,6 +312,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
static int async_wait_fd_write(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_write(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -252,7 +329,80 @@ static int async_wait_fd_write(int fd, int timeout) {
|
||||
}
|
||||
|
||||
void async_schedule_to_req(void) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
// a trick to avoid calling routes again
|
||||
uwsgi.wsgi_req->is_routing = 1;
|
||||
#endif
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
}
|
||||
return;
|
||||
|
||||
end:
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
}
|
||||
|
||||
void async_schedule_to_req_green(void) {
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
if (uwsgi.schedule_fix) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
if (uwsgi.schedule_to_main)
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
end:
|
||||
#endif
|
||||
// re-set the global state
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
async_reset_request(wsgi_req);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
// re-set the global state (routing could have changed it)
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -262,7 +412,6 @@ void async_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *tmp_uaf;
|
||||
int interesting_fd, i;
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
int timeout;
|
||||
@@ -271,16 +420,19 @@ void async_loop() {
|
||||
|
||||
uint64_t now;
|
||||
|
||||
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
|
||||
struct uwsgi_async_request *current_request = NULL;
|
||||
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi_async_init();
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
uwsgi.wait_read2_hook = async_wait_fd_read2;
|
||||
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);
|
||||
@@ -292,13 +444,13 @@ void async_loop() {
|
||||
uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
if (!uwsgi.schedule_to_main) {
|
||||
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
|
||||
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
now = (uint64_t) uwsgi_now();
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
if (uwsgi.async_runqueue) {
|
||||
timeout = 0;
|
||||
}
|
||||
else {
|
||||
@@ -328,16 +480,15 @@ void async_loop() {
|
||||
// manage events
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
// signals are executed in the main stack... in the future we could have dedicated stacks for them
|
||||
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
is_a_new_connection = 0;
|
||||
|
||||
// new request coming in ?
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
|
||||
@@ -351,6 +502,7 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// on error re-insert the request in the queue
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
@@ -364,6 +516,9 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// by default the core is in UWSGI_AGAIN mode
|
||||
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
|
||||
// some protocol (like zeromq) do not need additional parsing, just push it in the runqueue
|
||||
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
}
|
||||
@@ -380,31 +535,28 @@ void async_loop() {
|
||||
if (uwsgi.wsgi_req) {
|
||||
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
|
||||
// reset timeout
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
// put request in the runqueue
|
||||
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
continue;
|
||||
}
|
||||
else if (proto_parser_status < 0) {
|
||||
if (proto_parser_status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
continue;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
// app event
|
||||
// app-registered event
|
||||
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
|
||||
// unknown fd, remove it (for safety)
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
@@ -413,79 +565,37 @@ void async_loop() {
|
||||
}
|
||||
|
||||
// remove all the fd monitors and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_ready_fd = 1;
|
||||
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
|
||||
|
||||
// put the request in the runqueue again
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
// avoid managing other enqueued events...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// event queue managed, give cpu to runqueue
|
||||
if (!current_request)
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
// event queue managed, give cpu to runqueue
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
while(current_request) {
|
||||
|
||||
// current_request could be nulled on error/end of request
|
||||
struct uwsgi_async_request *next_request = current_request->next;
|
||||
|
||||
uwsgi.wsgi_req = current_request->wsgi_req;
|
||||
|
||||
uwsgi.schedule_to_req();
|
||||
uwsgi.wsgi_req->switches++;
|
||||
|
||||
next_async_request = current_request->next;
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
// remove all the monitored fds and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
// remove from the list
|
||||
runqueue_remove(current_request);
|
||||
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
|
||||
// push wsgi_request in the unused stack
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
|
||||
}
|
||||
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove this request from suspended list
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
|
||||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
current_request = next_async_request;
|
||||
|
||||
current_request = next_request;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+97
-7
@@ -3,6 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
|
||||
#ifdef UWSGI_DEBUG_BUFFER
|
||||
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
|
||||
#endif
|
||||
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
|
||||
|
||||
if (len) {
|
||||
@@ -61,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);
|
||||
@@ -71,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);
|
||||
@@ -125,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] == '\\') {
|
||||
@@ -169,6 +181,16 @@ int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
|
||||
uint8_t buf[4];
|
||||
uint32_t *pnum = (uint32_t *) #
|
||||
buf[3] = (uint8_t) (*pnum & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
@@ -191,6 +213,33 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
uint8_t buf[8];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[3] = (uint8_t) ((num >> 24) & 0xff);
|
||||
buf[4] = (uint8_t) ((num >> 32) & 0xff);
|
||||
buf[5] = (uint8_t) ((num >> 40) & 0xff);
|
||||
buf[6] = (uint8_t) ((num >> 48) & 0xff);
|
||||
buf[7] = (uint8_t) ((num >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
|
||||
uint8_t buf[8];
|
||||
uint64_t *pnum = (uint64_t *) #
|
||||
buf[7] = (uint8_t) (*pnum & 0xff);
|
||||
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
@@ -205,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);
|
||||
@@ -228,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;
|
||||
@@ -240,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;
|
||||
@@ -270,6 +319,13 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
|
||||
|
||||
|
||||
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
|
||||
#ifdef UWSGI_DEBUG_BUFFER
|
||||
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
|
||||
if (ub->freed) {
|
||||
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
|
||||
}
|
||||
ub->freed = 1;
|
||||
#endif
|
||||
if (ub->buf)
|
||||
free(ub->buf);
|
||||
free(ub);
|
||||
@@ -293,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) {
|
||||
@@ -328,3 +384,37 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
|
||||
ub->buf[3] = modifier2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
|
||||
struct stat st;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
|
||||
|
||||
ssize_t len = read(fd, ub->buf, st.st_size);
|
||||
close(fd);
|
||||
if (len != st.st_size) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ub->pos = len;
|
||||
return ub;
|
||||
}
|
||||
|
||||
void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
if (ub->buf) {
|
||||
free(ub->buf);
|
||||
}
|
||||
ub->buf = buf;
|
||||
ub->pos = len;
|
||||
ub->len = len;
|
||||
}
|
||||
|
||||
+698
-240
File diff suppressed because it is too large
Load Diff
+162
@@ -0,0 +1,162 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Chunked input implementation
|
||||
|
||||
--chunked-input-limit <bytes> (default 1MB)
|
||||
|
||||
--chunked-input-timeout <s> (default --socket-timeout)
|
||||
|
||||
chunk = uwsgi.chunked_read([timeout])
|
||||
|
||||
timeout = -1 (wait forever)
|
||||
timeout = 0 (default)
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
|
||||
|
||||
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
|
||||
if (timeout == 0) timeout = uwsgi.socket_timeout;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
for(;;) {
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (nb) return -1;
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
|
||||
size_t i;
|
||||
int found = 0;
|
||||
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
|
||||
if (found) {
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
|
||||
// strtoul will stop at \r
|
||||
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
|
||||
return num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0 -> waiting for \r\n
|
||||
1 -> waiting for whole body
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
|
||||
|
||||
if (!wsgi_req->chunked_input_buf) {
|
||||
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
|
||||
}
|
||||
|
||||
// the whole chunk stream has been consumed
|
||||
if (wsgi_req->chunked_input_complete) {
|
||||
*len = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_decapitate > 0) {
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
|
||||
wsgi_req->chunked_input_decapitate = 0;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
|
||||
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
|
||||
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
|
||||
if (rlen <= 0) return NULL;
|
||||
// update buffer position
|
||||
wsgi_req->chunked_input_buf->pos += rlen;
|
||||
if (wsgi_req->chunked_input_need > 0) {
|
||||
if ((size_t)rlen > wsgi_req->chunked_input_need) {
|
||||
wsgi_req->chunked_input_need = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->chunked_input_need -= rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) continue;
|
||||
|
||||
// ok we have a frame, let's parse it
|
||||
if (wsgi_req->chunked_input_buf->pos > 0) {
|
||||
switch(wsgi_req->chunked_input_parser_status) {
|
||||
case 0:
|
||||
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
|
||||
if (wsgi_req->chunked_input_chunk_len == -2) {
|
||||
wsgi_req->chunked_input_need++;
|
||||
break;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len == 0) {
|
||||
*len = 0;
|
||||
wsgi_req->chunked_input_complete = 1;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
// if here the buffer has been already decapitated
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
wsgi_req->chunked_input_parser_status = 1;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
case 1:
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
|
||||
wsgi_req->chunked_input_parser_status = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int main() {}
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
|
||||
return poll(NULL, 0, timeout);
|
||||
}
|
||||
|
||||
|
||||
// in the future we will need to use the best clock source for each os/system
|
||||
time_t uwsgi_now() {
|
||||
return uwsgi.clock->seconds();
|
||||
|
||||
+854
@@ -0,0 +1,854 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
pluggable configuration system
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
|
||||
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (!strcmp(uc->name, name)) {
|
||||
return uc;
|
||||
}
|
||||
old_uc = uc;
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
|
||||
uc->name = name;
|
||||
uc->func = func;
|
||||
|
||||
if (old_uc) {
|
||||
old_uc->next = uc;
|
||||
}
|
||||
else {
|
||||
uwsgi.configurators = uc;
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_exists(char *key, char *value) {
|
||||
|
||||
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_for(char *key, char *value) {
|
||||
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
|
||||
glob_t g;
|
||||
int i;
|
||||
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("uwsgi_logic_opt_for_glob()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int) g.gl_pathc; i++) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
|
||||
}
|
||||
|
||||
globfree(&g);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_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);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_opt(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (!strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_env(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = getenv(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
|
||||
|
||||
// check for env-value syntax
|
||||
char *equal = strchr(uwsgi.logic_opt_data, '=');
|
||||
if (equal)
|
||||
*equal = 0;
|
||||
|
||||
char *p = getenv(uwsgi.logic_opt_data);
|
||||
if (equal)
|
||||
*equal = '=';
|
||||
|
||||
if (p) {
|
||||
if (equal) {
|
||||
if (!strcmp(equal + 1, p))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_reload(char *key, char *value) {
|
||||
if (uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
|
||||
if (!uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_file(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_dir(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
|
||||
|
||||
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
|
||||
|
||||
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
|
||||
|
||||
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_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;
|
||||
int count = 0;
|
||||
|
||||
while ((aopt = uopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
count++;
|
||||
uopt++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int uwsgi_opt_exists(char *name) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) return 1;
|
||||
op++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
avoid loops here !!!
|
||||
*/
|
||||
struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
struct uwsgi_option *op;
|
||||
int round = 0;
|
||||
retry:
|
||||
round++;
|
||||
if (round > 2) goto end;
|
||||
op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) {
|
||||
return op;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
if (uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(name)) goto retry;
|
||||
}
|
||||
|
||||
end:
|
||||
if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
add_exported_option_do(key, value, configured, 0);
|
||||
}
|
||||
|
||||
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
|
||||
|
||||
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
|
||||
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
|
||||
|
||||
while (blacklist) {
|
||||
if (!strcmp(key, blacklist->value)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
blacklist = blacklist->next;
|
||||
}
|
||||
|
||||
if (whitelist) {
|
||||
int allowed = 0;
|
||||
while (whitelist) {
|
||||
if (!strcmp(key, whitelist->value)) {
|
||||
allowed = 1;
|
||||
break;
|
||||
}
|
||||
whitelist = whitelist->next;
|
||||
}
|
||||
if (!allowed) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.blacklist_context) {
|
||||
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.whitelist_context) {
|
||||
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.logic_opt_running)
|
||||
goto add;
|
||||
|
||||
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")
|
||||
|| !strcmp(key, "end-if") || !strcmp(key, "end-for")) {
|
||||
if (uwsgi.logic_opt_data) {
|
||||
free(uwsgi.logic_opt_data);
|
||||
}
|
||||
uwsgi.logic_opt = NULL;
|
||||
uwsgi.logic_opt_arg = NULL;
|
||||
uwsgi.logic_opt_cycles = 0;
|
||||
uwsgi.logic_opt_data = NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.logic_opt) {
|
||||
if (uwsgi.logic_opt_data) {
|
||||
free(uwsgi.logic_opt_data);
|
||||
}
|
||||
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
|
||||
uwsgi.logic_opt_cycles++;
|
||||
uwsgi.logic_opt_running = 1;
|
||||
uwsgi.logic_opt(key, value);
|
||||
uwsgi.logic_opt_running = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
add:
|
||||
|
||||
if (!uwsgi.exported_opts) {
|
||||
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
|
||||
}
|
||||
else {
|
||||
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
|
||||
if (!uwsgi.exported_opts) {
|
||||
uwsgi_error("realloc()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int id = uwsgi.exported_opts_cnt;
|
||||
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
|
||||
uwsgi.exported_opts[id]->key = key;
|
||||
uwsgi.exported_opts[id]->value = value;
|
||||
uwsgi.exported_opts[id]->configured = configured;
|
||||
uwsgi.exported_opts_cnt++;
|
||||
uwsgi.dirty_config = 1;
|
||||
|
||||
if (placeholder_only) {
|
||||
if (uwsgi_opt_exists(key)) {
|
||||
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
// requires master ?
|
||||
if (op->flags & UWSGI_OPT_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
}
|
||||
// requires log_master ?
|
||||
if (op->flags & UWSGI_OPT_LOG_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.log_master = 1;
|
||||
}
|
||||
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi.log_master = 1;
|
||||
uwsgi.req_log_master = 1;
|
||||
}
|
||||
// requires threads ?
|
||||
if (op->flags & UWSGI_OPT_THREADS) {
|
||||
uwsgi.has_threads = 1;
|
||||
}
|
||||
// requires cheaper mode ?
|
||||
if (op->flags & UWSGI_OPT_CHEAPER) {
|
||||
uwsgi.cheaper = 1;
|
||||
}
|
||||
// requires virtualhosting ?
|
||||
if (op->flags & UWSGI_OPT_VHOST) {
|
||||
uwsgi.vhost = 1;
|
||||
}
|
||||
// requires memusage ?
|
||||
if (op->flags & UWSGI_OPT_MEMORY) {
|
||||
uwsgi.force_get_memusage = 1;
|
||||
}
|
||||
// requires auto procname ?
|
||||
if (op->flags & UWSGI_OPT_PROCNAME) {
|
||||
uwsgi.auto_procname = 1;
|
||||
}
|
||||
// requires lazy ?
|
||||
if (op->flags & UWSGI_OPT_LAZY) {
|
||||
uwsgi.lazy = 1;
|
||||
}
|
||||
// requires no_initial ?
|
||||
if (op->flags & UWSGI_OPT_NO_INITIAL) {
|
||||
uwsgi.no_initial_output = 1;
|
||||
}
|
||||
// requires no_server ?
|
||||
if (op->flags & UWSGI_OPT_NO_SERVER) {
|
||||
uwsgi.no_server = 1;
|
||||
}
|
||||
// requires post_buffering ?
|
||||
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
|
||||
if (!uwsgi.post_buffering)
|
||||
uwsgi.post_buffering = 4096;
|
||||
}
|
||||
// requires building mime dict ?
|
||||
if (op->flags & UWSGI_OPT_MIME) {
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
// enable metrics ?
|
||||
if (op->flags & UWSGI_OPT_METRICS) {
|
||||
uwsgi.has_metrics = 1;
|
||||
}
|
||||
// immediate ?
|
||||
if (op->flags & UWSGI_OPT_IMMEDIATE) {
|
||||
op->func(key, value, op->data);
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fallback_config() {
|
||||
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
|
||||
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
|
||||
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
|
||||
char *argv[3];
|
||||
argv[0] = uwsgi.binary_path;
|
||||
argv[1] = uwsgi.fallback_config;
|
||||
argv[2] = NULL;
|
||||
execvp(uwsgi.binary_path, argv);
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_manage_opt(char *key, char *value) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
op->func(key, value, op->data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_configure() {
|
||||
|
||||
int i;
|
||||
|
||||
// and now apply the remaining configs
|
||||
restart:
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (uwsgi.exported_opts[i]->configured)
|
||||
continue;
|
||||
uwsgi.dirty_config = 0;
|
||||
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
|
||||
// some option could cause a dirty config tree
|
||||
if (uwsgi.dirty_config)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_custom(char *key, char *value, void *data ) {
|
||||
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
value_len = strlen(value);
|
||||
off_t pos = 0;
|
||||
char **opt_argv;
|
||||
char *tmp_val = NULL, *p = NULL;
|
||||
|
||||
// now count the number of args
|
||||
for (i = 0; i < value_len; i++) {
|
||||
if (value[i] == ' ') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate a tmp array
|
||||
opt_argv = uwsgi_calloc(sizeof(char *) * count);
|
||||
//make a copy of the value;
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no argument specified
|
||||
opt_argv[0] = "";
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found custom option %s with %d args\n", key, count);
|
||||
#endif
|
||||
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
*equal = '\0';
|
||||
|
||||
// build the key
|
||||
char *new_key = uwsgi_str(p);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_key = new_key;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
|
||||
if (new_key != old_key)
|
||||
free(old_key);
|
||||
free(placeholder);
|
||||
}
|
||||
|
||||
// build the value
|
||||
char *new_value = uwsgi_str(equal + 1);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_value = new_value;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
|
||||
if (new_value != old_value)
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
// ignore return value here
|
||||
uwsgi_manage_opt(new_key, new_value);
|
||||
}
|
||||
|
||||
clear:
|
||||
free(tmp_val);
|
||||
free(tmp_opt);
|
||||
free(opt_argv);
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_get_exported_opt(char *key) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
|
||||
return uwsgi.exported_opts[i]->value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_get_optname_by_index(int index) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (op->shortcut == index) {
|
||||
return op->name;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
this works as a pipeline
|
||||
|
||||
processes = 2
|
||||
cpu_cores = 8
|
||||
foobar = %(processes cpu_cores + 2)
|
||||
|
||||
translate as:
|
||||
|
||||
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
|
||||
|
||||
step1 + = step1_apply_func_plus (func token)
|
||||
|
||||
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_manage_placeholder(char *key) {
|
||||
enum {
|
||||
concat = 0,
|
||||
sum,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
} state;
|
||||
|
||||
state = concat;
|
||||
char *current_value = NULL;
|
||||
|
||||
char *space = strchr(key, ' ');
|
||||
if (!space) {
|
||||
return uwsgi_get_exported_opt(key);
|
||||
}
|
||||
// let's start the heavy metal here
|
||||
char *tmp_value = uwsgi_str(key);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
|
||||
char *value = NULL;
|
||||
if (is_a_number(p)) {
|
||||
value = uwsgi_str(p);
|
||||
}
|
||||
else if (!strcmp(p, "+")) {
|
||||
state = sum;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "-")) {
|
||||
state = sub;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "*")) {
|
||||
state = mul;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "/")) {
|
||||
state = div;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "++")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_num+1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "--")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_num-1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
// find the option
|
||||
else {
|
||||
char *ov = uwsgi_get_exported_opt(p);
|
||||
if (!ov) ov = "";
|
||||
value = uwsgi_str(ov);
|
||||
}
|
||||
|
||||
int64_t arg1n = 0, arg2n = 0;
|
||||
char *arg1 = "", *arg2 = "";
|
||||
|
||||
switch(state) {
|
||||
case concat:
|
||||
if (current_value) arg1 = current_value;
|
||||
if (value) arg2 = value;
|
||||
char *ret = uwsgi_concat2(arg1, arg2);
|
||||
if (current_value) free(current_value);
|
||||
current_value = ret;
|
||||
break;
|
||||
case sum:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n + arg2n);
|
||||
break;
|
||||
case sub:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n - arg2n);
|
||||
break;
|
||||
case mul:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n * arg2n);
|
||||
break;
|
||||
case div:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
// avoid division by zero
|
||||
if (arg2n == 0) {
|
||||
current_value = uwsgi_64bit2str(0);
|
||||
}
|
||||
else {
|
||||
current_value = uwsgi_64bit2str(arg1n / arg2n);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// over engineering
|
||||
if (value)
|
||||
free(value);
|
||||
|
||||
// reset state to concat
|
||||
state = concat;
|
||||
}
|
||||
free(tmp_value);
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
cookie management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t orig_cookie_len = cookie_len-1;
|
||||
// first lstrip white spaces
|
||||
char *ptr = cookie;
|
||||
uint16_t i;
|
||||
for(i=0;i<cookie_len;i++) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie++;
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then rstrip (skipping the first char...)
|
||||
for(i=orig_cookie_len;i>0;i--) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the first equal sign
|
||||
char *equal = memchr(cookie, '=', cookie_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie_len -= (equal-cookie)+1;
|
||||
if (cookie_len == 0) return NULL;
|
||||
|
||||
*vallen = cookie_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *cookie = wsgi_req->cookie;
|
||||
uint16_t cookie_len = 0;
|
||||
char *ptr = wsgi_req->cookie;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->cookie_len;i++) {
|
||||
if (!cookie) {
|
||||
cookie = ptr + i;
|
||||
}
|
||||
if (ptr[i] == ';') {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
cookie_len = 0;
|
||||
cookie = NULL;
|
||||
}
|
||||
else {
|
||||
cookie_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie_len > 0) {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
|
||||
int i;
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = crontab + i;
|
||||
uc->pid = -1;
|
||||
return uc;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
uwsgi_cron_add(value);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(value);
|
||||
uc->unique = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
uc->unique = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *c_minute = NULL;
|
||||
char *c_hour = NULL;
|
||||
char *c_day = NULL;
|
||||
char *c_month = NULL;
|
||||
char *c_week = NULL;
|
||||
char *c_unique = NULL;
|
||||
char *c_harakiri = NULL;
|
||||
char *c_legion = NULL;
|
||||
|
||||
char *c_command = value;
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (space) {
|
||||
if (uwsgi_str_contains(value, space - value, '=')) {
|
||||
// --cron2 key=val command
|
||||
*space = 0;
|
||||
c_command = space + 1;
|
||||
}
|
||||
|
||||
// no point in parsing key=val list if there is none
|
||||
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
|
||||
"minute", &c_minute,
|
||||
"hour", &c_hour,
|
||||
"day", &c_day,
|
||||
"month", &c_month,
|
||||
"week", &c_week,
|
||||
"unique", &c_unique,
|
||||
"harakiri", &c_harakiri,
|
||||
"legion", &c_legion,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_str_contains(value, strlen(value), '=')) {
|
||||
// --cron2 key=val
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
uc->command = c_command;
|
||||
if (!uc->command) {
|
||||
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// defaults
|
||||
uc->minute = -1;
|
||||
uc->hour = -1;
|
||||
uc->day = -1;
|
||||
uc->month = -1;
|
||||
uc->week = -1;
|
||||
|
||||
uc->unique = 0;
|
||||
uc->mercy = 0;
|
||||
uc->harakiri = 0;
|
||||
uc->pid = -1;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uc->legion = c_legion;
|
||||
#endif
|
||||
|
||||
if (c_minute)
|
||||
uc->minute = atoi(c_minute);
|
||||
|
||||
if (c_hour)
|
||||
uc->hour = atoi(c_hour);
|
||||
|
||||
if (c_day)
|
||||
uc->day = atoi(c_day);
|
||||
|
||||
if (c_month)
|
||||
uc->month = atoi(c_month);
|
||||
|
||||
if (c_week)
|
||||
uc->week = atoi(c_week);
|
||||
|
||||
if (c_unique)
|
||||
uc->unique = atoi(c_unique);
|
||||
|
||||
if (c_harakiri) {
|
||||
if (atoi(c_harakiri)) {
|
||||
// harakiri > 0
|
||||
uc->mercy = atoi(c_harakiri);
|
||||
}
|
||||
else {
|
||||
// harakiri == 0
|
||||
uc->mercy = -1;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.cron_harakiri) {
|
||||
uc->harakiri = uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job >= 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// check for legion cron
|
||||
if (current_cron->legion) {
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
|
||||
goto next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// skip unique crons that are still running
|
||||
if (current_cron->unique && current_cron->pid >= 0)
|
||||
goto next;
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job >= 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (current_cron->func) {
|
||||
current_cron->func(current_cron, now);
|
||||
}
|
||||
else {
|
||||
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
|
||||
if (pid >= 0) {
|
||||
current_cron->pid = pid;
|
||||
current_cron->started_at = now;
|
||||
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
|
||||
if (current_cron->mercy) {
|
||||
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
|
||||
if (current_cron->mercy > 0)
|
||||
current_cron->harakiri = now + current_cron->mercy;
|
||||
}
|
||||
else if (uwsgi.cron_harakiri)
|
||||
current_cron->harakiri = now + uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
}
|
||||
|
||||
+331
-45
@@ -1,4 +1,4 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
External uwsgi daemons
|
||||
|
||||
There are 3 kind of daemons (read: external applications) that can be managed
|
||||
There are 3 kinds of daemons (read: external applications) that can be managed
|
||||
by uWSGI.
|
||||
|
||||
1) dumb daemons (attached with --attach-daemon)
|
||||
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
|
||||
and the process is respawned
|
||||
2) smart daemons with daemonization
|
||||
you specify a pidfile and a command
|
||||
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
|
||||
the daemon is respawned
|
||||
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master check - if the pidfile does not exist or if it points to a non-existent pid
|
||||
the daemon is respawned
|
||||
3) smart daemons without daemonization
|
||||
same as 2, but the daemonization and pidfile creation is managed by uWSGI
|
||||
same as 2, but the daemonization and pidfile creation are managed by uWSGI
|
||||
|
||||
status:
|
||||
|
||||
@@ -42,6 +42,31 @@ void uwsgi_daemons_smart_check() {
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion) {
|
||||
if (uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// lord, spawn if not running
|
||||
if (ud->pid <= 0) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// not lord, kill daemon if running
|
||||
if (ud->pid > 0) {
|
||||
if (!kill(ud->pid, 0)) {
|
||||
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
ud->pid = -1;
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -52,8 +77,14 @@ void uwsgi_daemons_smart_check() {
|
||||
else {
|
||||
ud->pidfile_checks++;
|
||||
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
if (!ud->has_daemonized) {
|
||||
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
|
||||
ud->pidfile_checks = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,13 +101,24 @@ void uwsgi_daemons_smart_check() {
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a dumb daemon dies and we do not wat to respawn it
|
||||
// this function is called when a dumb daemon dies and we do not want to respawn it
|
||||
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
return -1;
|
||||
if (ud->pid == diedpid) {
|
||||
if (!ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!ud->has_daemonized) {
|
||||
ud->has_daemonized = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -87,7 +129,20 @@ int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->pid == diedpid && ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion but not lord, don't respawn
|
||||
ud->pid = -1;
|
||||
uwsgi_log("uwsgi-daemons] legion \"%s\" daemon \"%s\" (pid: %d) annihilated\n", ud->legion, ud->command, (int) diedpid);
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
if (ud->control) {
|
||||
gracefully_kill_them_all(0);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
}
|
||||
@@ -133,6 +188,20 @@ void uwsgi_daemons_spawn_all() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (!ud->registered) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion, register but don't spawn it yet
|
||||
if (ud->pidfile) {
|
||||
ud->pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (ud->pid > 0)
|
||||
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
|
||||
}
|
||||
ud->registered = 1;
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ud->registered = 1;
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -146,7 +215,6 @@ void uwsgi_daemons_spawn_all() {
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -156,20 +224,53 @@ void uwsgi_daemons_spawn_all() {
|
||||
void uwsgi_detach_daemons() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && !ud->pidfile)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
#ifdef UWSGI_SSL
|
||||
// stop any legion daemon, doesn't matter if dumb or smart
|
||||
if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
|
||||
#else
|
||||
// stop only dumb daemons
|
||||
if (ud->pid > 0 && !ud->pidfile) {
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
// try to stop daemon gracefully, kill it if it won't die
|
||||
// if mercy is not set then wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
if (uwsgi_instance_is_reloading && ud->reload_signal > 0) {
|
||||
kill(-(ud->pid), ud->reload_signal);
|
||||
}
|
||||
else {
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
sleep(1);
|
||||
waitpid(ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
kill(-(ud->pid), SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// unregister daemon to prevent it from being respawned
|
||||
ud->registered = 0;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int daemon_spawn(void *);
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
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 (ud->throttle <= 0) ud->throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -179,6 +280,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->has_daemonized = 0;
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
ud->pidfile_checks = 0;
|
||||
@@ -195,9 +297,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);
|
||||
@@ -208,18 +375,9 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -228,7 +386,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()");
|
||||
}
|
||||
@@ -236,20 +394,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(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,11 +414,28 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
char *pidfile = NULL;
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
char *space = NULL;
|
||||
int stop_signal = SIGTERM;
|
||||
int reload_signal = 0;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
|
||||
char *space = strchr(command, ' ');
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion = NULL;
|
||||
if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid legion daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
legion = command;
|
||||
command = space+1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
@@ -277,13 +449,13 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
freq = atoi(comma + 1);
|
||||
}
|
||||
command = space + 1;
|
||||
if (!strcmp(opt, "smart-attach-daemon2")) {
|
||||
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
daemonize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi.daemons;
|
||||
}
|
||||
else {
|
||||
@@ -292,7 +464,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;
|
||||
}
|
||||
|
||||
@@ -306,7 +478,121 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
uwsgi_ud->control = 0;
|
||||
uwsgi_ud->stop_signal = stop_signal;
|
||||
uwsgi_ud->reload_signal = reload_signal;
|
||||
if (!strcmp(opt, "attach-control-daemon")) {
|
||||
uwsgi_ud->control = 1;
|
||||
}
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = legion;
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1299
-294
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,30 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
struct stat st;
|
||||
if (!stat(usl->value, &st)) {
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// generate internal server error message
|
||||
void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
|
||||
}
|
||||
|
||||
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
|
||||
}
|
||||
@@ -18,10 +40,19 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
+271
-20
@@ -2,6 +2,233 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_POLL
|
||||
#define UWSGI_EVENT_IN POLLIN
|
||||
#define UWSGI_EVENT_OUT POLLOUT
|
||||
|
||||
int uwsgi_poll_event_queue_max = 0;
|
||||
struct uwsgi_poll_event {
|
||||
int nevents;
|
||||
int max_events;
|
||||
pthread_mutex_t lock;
|
||||
struct pollfd *poll;
|
||||
};
|
||||
|
||||
struct uwsgi_poll_event **uwsgi_poll_event_queue;
|
||||
|
||||
// all of the public functions must be heavy locked
|
||||
|
||||
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
|
||||
int pos = upe->nevents;
|
||||
if (pos > upe->max_events) return -1;
|
||||
upe->poll[pos].fd = fd;
|
||||
upe->poll[pos].events = event;
|
||||
upe->nevents++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
if (i < upe->nevents-1) {
|
||||
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
|
||||
}
|
||||
upe->nevents--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
|
||||
// we need to check if some file descriptor is no more valid
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
|
||||
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
*interesting_fd = upe->poll[i].fd;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int event_queue_init() {
|
||||
if (!uwsgi_poll_event_queue) {
|
||||
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
|
||||
}
|
||||
int eq = uwsgi_poll_event_queue_max;
|
||||
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
|
||||
uwsgi_poll_event_queue_max++;
|
||||
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
|
||||
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
|
||||
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
|
||||
return eq;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN|POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
return event_queue_fd_write_to_readwrite(eq, fd);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int ret = uwsgi_poll_fd_del(upe, fd);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
int cnt = 0;
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[cnt];
|
||||
upoll->fd = upe->poll[i].fd;
|
||||
upoll->revents = upe->poll[i].revents;
|
||||
upoll->events = upe->poll[i].events;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
if (ret <= 0) return ret;
|
||||
return cnt;
|
||||
}
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
return upoll->fd;
|
||||
}
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
|
||||
#include <port.h>
|
||||
@@ -33,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -44,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -55,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -66,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -77,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -88,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -124,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -134,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -149,12 +376,16 @@ void *event_queue_alloc(int nevents) {
|
||||
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
int eq = (long) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
@@ -183,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;
|
||||
@@ -196,7 +427,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
@@ -221,23 +452,28 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
else {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_get()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
*interesting_fd = (long) pe.portev_user;
|
||||
}
|
||||
else {
|
||||
@@ -712,7 +948,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct timespec ts;
|
||||
struct kevent ev;
|
||||
|
||||
if (timeout <= 0) {
|
||||
if (timeout < 0) {
|
||||
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
|
||||
}
|
||||
else {
|
||||
@@ -745,6 +981,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
|
||||
struct file_obj fo;
|
||||
@@ -805,6 +1042,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
return -1;
|
||||
}
|
||||
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -987,6 +1232,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#elif defined(__arm__)
|
||||
return syscall(350, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
@@ -997,6 +1244,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__arm__)
|
||||
return syscall(353, __ufd, __flags, __utmr, __otmr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
|
||||
|
||||
if (do_exit) goto check_catch;
|
||||
|
||||
if (wsgi_req && uwsgi.exception_handlers_instance) {
|
||||
if (uwsgi.exception_handlers_instance) {
|
||||
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
|
||||
if (ehi) {
|
||||
uwsgi_exception_run_handlers(ehi);
|
||||
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
|
||||
}
|
||||
|
||||
void uwsgi_exceptions_handler_thread_start() {
|
||||
|
||||
if (!uwsgi.exception_handlers_instance) return;
|
||||
// start the exception_handler_thread
|
||||
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
|
||||
if (!uwsgi.exception_handler_thread) {
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
the --master-fifo option create a unix named pipe (fifo) you can use to send management
|
||||
commands to the master:
|
||||
|
||||
echo r > myfifo
|
||||
|
||||
*/
|
||||
|
||||
// this var can be accessed by plugins and hooks
|
||||
void (*uwsgi_fifo_table[256])(int);
|
||||
|
||||
static char *uwsgi_fifo_by_slot() {
|
||||
int count = 0;
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.master_fifo) {
|
||||
if (count == uwsgi.master_fifo_slot) return usl->value;
|
||||
count++;
|
||||
}
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
|
||||
|
||||
static void subscriptions_blocker() {
|
||||
if (uwsgi.subscriptions_blocked) {
|
||||
uwsgi_log_verbose("subscriptions re-enabled\n");
|
||||
uwsgi.subscriptions_blocked = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.subscriptions_blocked = 1;
|
||||
uwsgi_log_verbose("subscriptions blocked\n");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
void uwsgi_master_fifo_prepare() {
|
||||
int i;
|
||||
for(i=0;i<256;i++) {
|
||||
uwsgi_fifo_table[i] = NULL;
|
||||
}
|
||||
|
||||
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
|
||||
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
|
||||
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
|
||||
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
|
||||
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
|
||||
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
|
||||
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
|
||||
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
|
||||
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
|
||||
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['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;
|
||||
uwsgi_fifo_table['p'] = suspend_resume_them_all;
|
||||
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
|
||||
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
|
||||
uwsgi_fifo_table['Q'] = kill_them_all;
|
||||
uwsgi_fifo_table['r'] = grace_them_all;
|
||||
uwsgi_fifo_table['R'] = reap_them_all;
|
||||
uwsgi_fifo_table['s'] = stats;
|
||||
uwsgi_fifo_table['S'] = subscriptions_blocker;
|
||||
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
|
||||
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo() {
|
||||
|
||||
char *path = uwsgi_fifo_by_slot();
|
||||
|
||||
unlink(path);
|
||||
|
||||
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_master_fifo()/open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
unsigned char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_master_fifo_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_fifo_table[(int) cmd]) {
|
||||
uwsgi_fifo_table[(int) cmd](0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
#ifndef OBSOLETE_LINUX_KERNEL
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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("fsmon_add()/inotify_init()");
|
||||
return -1;
|
||||
}
|
||||
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
|
||||
uwsgi_error("fsmon_add()/event_queue_add_fd_read()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
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("fsmon_add()/inotify_add_watch()");
|
||||
return -1;
|
||||
}
|
||||
fs->fd = inotify_fd;
|
||||
fs->id = wd;
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
|
||||
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("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 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);
|
||||
}
|
||||
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(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(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
|
||||
return found_fs;
|
||||
}
|
||||
|
||||
int uwsgi_fsmon_event(int interesting_fd) {
|
||||
|
||||
struct uwsgi_fsmon *fs = uwsgi_fsmon_ack(interesting_fd);
|
||||
if (!fs)
|
||||
return 0;
|
||||
|
||||
uwsgi_log_verbose("[uwsgi-fsmon] detected event on \"%s\"\n", fs->path);
|
||||
fs->func(fs);
|
||||
return 1;
|
||||
}
|
||||
+32
-2
@@ -18,7 +18,9 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
}
|
||||
}
|
||||
|
||||
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
|
||||
char *str = uwsgi_num2str(num);
|
||||
char *fullname = uwsgi_concat3(name, " ", str);
|
||||
free(str);
|
||||
|
||||
ug = &ushared->gateways[ushared->gateways_cnt];
|
||||
ug->pid = 0;
|
||||
@@ -27,12 +29,21 @@ 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)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
||||
|
||||
if (!uwsgi.master_process && !uwsgi.force_gateway)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
ushared->gateways_cnt++;
|
||||
@@ -61,6 +72,7 @@ void gateway_respawn(int id) {
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
uwsgi_close_all_sockets();
|
||||
if (uwsgi.master_as_root)
|
||||
uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
@@ -80,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);
|
||||
|
||||
+21
-1
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
|
||||
|
||||
// Murmur2 hash Copyright (C) Austin Appleby
|
||||
// adapted from nginx
|
||||
uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
|
||||
uint32_t h, k;
|
||||
uint8_t *ukey = (uint8_t *) key;
|
||||
@@ -56,6 +56,23 @@ uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32_t random_hash(char *key, uint64_t keylen) {
|
||||
return (uint32_t) rand();
|
||||
}
|
||||
|
||||
/*
|
||||
not atomic, avoid its use in multithreaded modes
|
||||
*/
|
||||
static uint32_t rr_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t rr = 0;
|
||||
uint32_t max_value = uwsgi_str_num(key, keylen);
|
||||
uint32_t ret = rr;
|
||||
rr++;
|
||||
if (rr > max_value) {
|
||||
rr = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
|
||||
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
|
||||
@@ -90,4 +107,7 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
|
||||
void uwsgi_hash_algo_register_all() {
|
||||
uwsgi_hash_algo_register("djb33x", djb33x_hash);
|
||||
uwsgi_hash_algo_register("murmur2", murmur2_hash);
|
||||
uwsgi_hash_algo_register("random", random_hash);
|
||||
uwsgi_hash_algo_register("rand", random_hash);
|
||||
uwsgi_hash_algo_register("rr", rr_hash);
|
||||
}
|
||||
|
||||
+649
@@ -0,0 +1,649 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
advanced (pluggable) hooks
|
||||
|
||||
they are executed before the other hooks, and can be extended by plugins
|
||||
|
||||
if a plugin tries to register an hook with a name already available in the list, its function
|
||||
will be overridden
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
|
||||
struct uwsgi_hook *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
return uh;
|
||||
}
|
||||
uh = uh->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
uh->func = func;
|
||||
return;
|
||||
}
|
||||
old_uh = uh;
|
||||
uh = uh->next;
|
||||
}
|
||||
|
||||
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
|
||||
uh->name = name;
|
||||
uh->func = func;
|
||||
|
||||
if (old_uh) {
|
||||
old_uh->next = uh;
|
||||
}
|
||||
else {
|
||||
uwsgi.hooks = uh;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_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) {
|
||||
uwsgi_error("uwsgi_hook_chdir()");
|
||||
}
|
||||
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) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exit(char *arg) {
|
||||
int exit_code = 0;
|
||||
if (strlen(arg) > 1) {
|
||||
exit_code = atoi(arg);
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_print(char *arg) {
|
||||
char *line = uwsgi_concat2(arg, "\n");
|
||||
uwsgi_log(line);
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_unlink(char *arg) {
|
||||
int ret = unlink(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_unlink()/unlink()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_writefifo(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
if (errno == ENODEV) return 0;
|
||||
#ifdef ENXIO
|
||||
if (errno == ENXIO) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_writefifo()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_write(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 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_write()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
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)
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
if (space)
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
if (!space) {
|
||||
// simple newline
|
||||
if (write(fd, "\n", 1) != 1) {
|
||||
uwsgi_error("uwsgi_hook_appendn()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*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, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(num);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_call(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(space + 1);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callintret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(num);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(space + 1);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uwsgi_register_hook("mount", uwsgi_mount_hook);
|
||||
uwsgi_register_hook("umount", uwsgi_umount_hook);
|
||||
|
||||
uwsgi_register_hook("call", uwsgi_hook_call);
|
||||
uwsgi_register_hook("callret", uwsgi_hook_callret);
|
||||
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
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) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
char *colon = strchr(usl->value, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid hook syntax, must be hook:args\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
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 action not found: %s\n", action);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-6
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_INI
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
|
||||
This memory must not be freed for all the server lifecycle
|
||||
*/
|
||||
|
||||
static char *last_file = NULL;
|
||||
|
||||
void ini_rstrip(char *line) {
|
||||
|
||||
off_t i;
|
||||
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
int got_section = 0;
|
||||
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
@@ -106,13 +107,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
if (colon[1] != 0) {
|
||||
section_asked = colon + 1;
|
||||
}
|
||||
|
||||
if (colon == file) {
|
||||
file = last_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (file[0] != 0) {
|
||||
if (file[0] != 0 && file != last_file) {
|
||||
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
if (file != last_file) {
|
||||
if (last_file) {
|
||||
free(last_file);
|
||||
}
|
||||
last_file = uwsgi_str(file);
|
||||
}
|
||||
|
||||
while (len) {
|
||||
ini_line = ini_get_line(ini, len);
|
||||
@@ -137,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
val = ini_get_key(key);
|
||||
|
||||
if (!strcmp(section, section_asked)) {
|
||||
got_section = 1;
|
||||
ini_rstrip(key);
|
||||
val = ini_lstrip(val);
|
||||
ini_rstrip(val);
|
||||
@@ -151,11 +163,13 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
}
|
||||
|
||||
if (!got_section) {
|
||||
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+65
-24
@@ -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 */
|
||||
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{"509", "Bandwidth Limit Exceeded"},
|
||||
{"", NULL},
|
||||
};
|
||||
|
||||
@@ -72,13 +73,15 @@ 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;
|
||||
// default emperor scan frequency
|
||||
uwsgi.emperor_freq = 3;
|
||||
uwsgi.emperor_throttle = 1000;
|
||||
uwsgi.emperor_heartbeat = 30;
|
||||
uwsgi.emperor_curse_tolerance = 30;
|
||||
// max 3 minutes throttling
|
||||
uwsgi.emperor_max_throttle = 1000 * 180;
|
||||
uwsgi.emperor_pid = -1;
|
||||
@@ -110,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;
|
||||
@@ -161,10 +165,27 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.empty = "";
|
||||
|
||||
#ifdef __linux__
|
||||
uwsgi.cgroup_dir_mode = "0700";
|
||||
#endif
|
||||
|
||||
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
|
||||
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
|
||||
// clear reforked status
|
||||
uwsgi.master_is_reforked = 0;
|
||||
|
||||
uwsgi.master_fifo_fd = -1;
|
||||
uwsgi_master_fifo_prepare();
|
||||
|
||||
uwsgi.notify_socket_fd = -1;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -178,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()");
|
||||
@@ -209,21 +230,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
|
||||
p = original_proc_name;
|
||||
p = strstr(p, "uwsgi_");
|
||||
if (p != NULL) {
|
||||
plugins_requested = strtok(uwsgi_str(p + 6), "_");
|
||||
while (plugins_requested) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
|
||||
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
|
||||
uwsgi_load_plugin(-1, plugins_requested, NULL);
|
||||
plugins_requested = strtok(NULL, "_");
|
||||
}
|
||||
}
|
||||
|
||||
plugins_requested = getenv("UWSGI_PLUGINS");
|
||||
if (plugins_requested) {
|
||||
plugins_requested = uwsgi_concat2(plugins_requested, "");
|
||||
char *p = strtok(plugins_requested, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
|
||||
uwsgi_load_plugin(-1, p, NULL);
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +351,6 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.workers[i].signal_pipe[0] = -1;
|
||||
uwsgi.workers[i].signal_pipe[1] = -1;
|
||||
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
|
||||
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
|
||||
}
|
||||
|
||||
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
|
||||
@@ -347,6 +365,13 @@ void uwsgi_setup_workers() {
|
||||
// allocate signal table
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.response_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
pid_t uwsgi_daemonize2() {
|
||||
@@ -374,6 +399,8 @@ pid_t uwsgi_daemonize2() {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) uwsgi_setup_log_master();
|
||||
|
||||
return uwsgi.mypid;
|
||||
}
|
||||
|
||||
@@ -389,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");
|
||||
}
|
||||
@@ -425,17 +452,31 @@ void sanitize_args() {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
|
||||
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
|
||||
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.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);
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* here we try to choose if thunder lock is a good thing */
|
||||
#ifdef UNBIT
|
||||
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
|
||||
uwsgi.use_thunder_lock = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
|
||||
|
||||
+201
-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;
|
||||
@@ -106,6 +300,9 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
config_iter = json_object_iter_next(config, config_iter);
|
||||
}
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
-370
@@ -1,370 +0,0 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
#ifndef LDAP_OPT_SUCCESS
|
||||
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
|
||||
#endif
|
||||
|
||||
#ifndef ldap_unbind_ext_s
|
||||
#define ldap_unbind_ext_s ldap_unbind_ext
|
||||
#endif
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
char *ptr = uwsginame;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int) strlen(ldapname); i++) {
|
||||
if (isupper((int) ldapname[i])) {
|
||||
*ptr++ = '-';
|
||||
*ptr++ = tolower((int) ldapname[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++ = ldapname[i];
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
for (i = 0; i < (int) strlen(name); i++) {
|
||||
if (isupper((int) name[i])) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return strlen(name) + counter;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry {
|
||||
int num;
|
||||
char names[1024];
|
||||
int has_arg;
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
int i;
|
||||
char *ptr = dst;
|
||||
|
||||
memset(dst, 0, 1024);
|
||||
|
||||
strcat(dst, " 'uWSGI");
|
||||
|
||||
ptr += 7;
|
||||
|
||||
for (i = 0; i < (int) strlen(src); i++) {
|
||||
if (src[i] == '-') {
|
||||
i++;
|
||||
*ptr++ = toupper((int) src[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
strcat(dst, "'");
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (uwsgi_list_has_str(ule->names, name + 1)) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
char ldap_name[1024];
|
||||
|
||||
*count = 0;
|
||||
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
|
||||
|
||||
while (op && op->name) {
|
||||
|
||||
uwsgi_name_to_ldap((char *) op->name, ldap_name);
|
||||
|
||||
entry = search_ldap_cache(ule, ldap_name, *count);
|
||||
|
||||
if (entry)
|
||||
goto next;
|
||||
|
||||
entry = &ule[*count];
|
||||
entry->num = *count;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count + 1;
|
||||
|
||||
entry->has_arg = op->type;
|
||||
|
||||
next:
|
||||
op++;
|
||||
}
|
||||
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
|
||||
uwsgi_log("\n");
|
||||
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
|
||||
uwsgi_log("objectClass: olcSchemaConfig\n");
|
||||
uwsgi_log("cn: uwsgi\n");
|
||||
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
|
||||
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
uwsgi_log("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
BerElement *ber;
|
||||
struct berval **bervalues;
|
||||
char *attr;
|
||||
char *uwsgi_attr;
|
||||
|
||||
char *url_slash;
|
||||
|
||||
int desired_version = LDAP_VERSION3;
|
||||
int ret;
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (!ldap_is_ldap_url(url)) {
|
||||
uwsgi_log("invalid LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
|
||||
uwsgi_log("unable to parse LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
|
||||
|
||||
url_slash = strchr(url, '/');
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
if (url_slash) {
|
||||
url_slash[0] = 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP URL: %s\n", url);
|
||||
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
|
||||
#endif
|
||||
|
||||
#if LDAP_API_VERSION >= 3000
|
||||
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
|
||||
uwsgi_error("ldap_init()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP connection initialized %p\n", ldp);
|
||||
#endif
|
||||
|
||||
free(ldap_url);
|
||||
|
||||
if (ldap_count_entries(ldp, results) < 1) {
|
||||
uwsgi_log("no LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(ldp, results);
|
||||
|
||||
int found = 0;
|
||||
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
|
||||
if (!strncmp(attr, "uWSGI", 5)) {
|
||||
|
||||
found = 1;
|
||||
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
|
||||
if (!uwsgi_attr) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ldap2uwsgi(attr + 5, uwsgi_attr);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
|
||||
#endif
|
||||
bervalues = ldap_get_values_len(ldp, entry, attr);
|
||||
if (bervalues) {
|
||||
// do not free uwsgi_attr/uwsgi_val;
|
||||
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
|
||||
if (!uwsgi_val) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
|
||||
uwsgi_val[bervalues[0]->bv_len] = 0;
|
||||
|
||||
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
|
||||
free(bervalues);
|
||||
}
|
||||
else {
|
||||
free(uwsgi_attr);
|
||||
}
|
||||
}
|
||||
free(attr);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_log("no uWSGI LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(ber);
|
||||
free(results);
|
||||
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
+279
-47
@@ -79,6 +79,40 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
|
||||
ul->scroll = value;
|
||||
ul->scroll_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "dead", 4)) {
|
||||
ul->dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a node is added or removed (heavy locking is needed)
|
||||
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
|
||||
uint64_t max_size = ul->scrolls_max_size;
|
||||
|
||||
// first, try to add myself
|
||||
if (ul->scroll_len + (uint64_t) 2 > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
ul->scroll_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char *ptr = ul->scrolls;
|
||||
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
|
||||
ul->scrolls_len = 2 + ul->scroll_len;
|
||||
// ok start adding nodes;
|
||||
struct uwsgi_legion_node *uln = ul->nodes_head;
|
||||
while(uln) {
|
||||
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
return;
|
||||
}
|
||||
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
|
||||
ul->scrolls_len += 2 + uln->scroll_len;
|
||||
uln = uln->next;
|
||||
}
|
||||
}
|
||||
|
||||
// critical section (remember to lock when you use it)
|
||||
@@ -104,6 +138,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
|
||||
ul->nodes_head = node;
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
|
||||
|
||||
@@ -141,6 +176,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
|
||||
}
|
||||
|
||||
free(node);
|
||||
|
||||
legion_rebuild_scrolls(ul);
|
||||
}
|
||||
|
||||
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
@@ -169,14 +206,22 @@ static void legions_check_nodes() {
|
||||
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
// trigger node_left hooks
|
||||
struct uwsgi_string_list *usl = legion->node_left_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_left", legion, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -190,12 +235,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
|
||||
|
||||
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
while (nodes) {
|
||||
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
nodes = nodes->next;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
|
||||
}
|
||||
|
||||
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
|
||||
@@ -231,11 +276,19 @@ static void legions_check_nodes_step2() {
|
||||
best_valor = node->valor;
|
||||
memcpy(best_uuid, node->uuid, 36);
|
||||
}
|
||||
else {
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
// 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
|
||||
memset(best_uuid, 0, 36);
|
||||
}
|
||||
|
||||
// calculate the checksum
|
||||
@@ -268,6 +321,18 @@ static void legions_check_nodes_step2() {
|
||||
|
||||
// we have quorum !!!
|
||||
if (votes > 0 && votes >= ul->quorum) {
|
||||
if (!ul->joined) {
|
||||
// triggering join hooks
|
||||
struct uwsgi_string_list *usl = ul->join_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("join", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->joined = 1;
|
||||
}
|
||||
// something changed ???
|
||||
if (ul->changed) {
|
||||
legions_report_quorum(ul, best_valor, best_uuid, votes);
|
||||
@@ -275,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;
|
||||
}
|
||||
@@ -294,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);
|
||||
@@ -303,9 +376,9 @@ static void legions_check_nodes_step2() {
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
|
||||
if (ul->lord_scroll_len > 0) {
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n");
|
||||
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
|
||||
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
|
||||
}
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
@@ -322,9 +395,23 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
|
||||
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
|
||||
// no more quorum, leave the Lord state
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("unlord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->i_am_the_lord = 0;
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
}
|
||||
@@ -341,6 +428,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
while (nodes) {
|
||||
// skip arbiters
|
||||
if (nodes->valor == 0) goto next;
|
||||
if (nodes->valor > best_valor) {
|
||||
best_node = nodes;
|
||||
best_valor = nodes->valor;
|
||||
@@ -353,11 +442,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
memcpy(best_uuid, nodes->uuid, 36);
|
||||
}
|
||||
}
|
||||
next:
|
||||
nodes = nodes->next;
|
||||
}
|
||||
|
||||
// first round ?
|
||||
if (ul->lord_valor == 0) {
|
||||
// first round ? (skip first round if arbiter)
|
||||
if (ul->valor > 0 && ul->lord_valor == 0) {
|
||||
ul->changed = 1;
|
||||
}
|
||||
else if (best_valor != ul->lord_valor) {
|
||||
@@ -417,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;
|
||||
@@ -512,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);
|
||||
@@ -521,8 +620,27 @@ static void *legion_loop(void *foobar) {
|
||||
node->scroll_len = legion_msg.scroll_len;
|
||||
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
|
||||
}
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
// remove node announcing death
|
||||
else if (legion_msg.dead) {
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s announced its death to Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_wlock(ul->lock);
|
||||
uwsgi_legion_remove_node(ul, node);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
@@ -550,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);
|
||||
}
|
||||
|
||||
@@ -569,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;
|
||||
|
||||
@@ -577,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;
|
||||
@@ -638,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;
|
||||
@@ -665,10 +808,13 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
|
||||
goto err;
|
||||
}
|
||||
#ifdef UWSGI_UUID
|
||||
#endif
|
||||
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
if (ul->dead) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
|
||||
goto err;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -707,9 +853,26 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
return 0;
|
||||
err:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
free(encrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
uwsgi_opt_legion(opt, value, foobar);
|
||||
char *legion = uwsgi_str(value);
|
||||
char *space = strchr(legion, ' ');
|
||||
// over engineering
|
||||
if (!space) exit(1);
|
||||
*space = 0;
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
free(legion);
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
@@ -727,15 +890,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
|
||||
char *port = strchr(usl->value, ':');
|
||||
uwsgi_legion_register_node(ul, space + 1);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
|
||||
char *port = strchr(addr, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom = socket_to_in_addr(addr, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
}
|
||||
|
||||
@@ -787,51 +955,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *event = strchr(opt, '-');
|
||||
if (!event) {
|
||||
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_legion_register_hook(ul, event + 1, space + 1);
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
if (!strcmp(opt, "legion-lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
|
||||
if (!strcmp(event, "lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
|
||||
else if (!strcmp(event, "unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
|
||||
else if (!strcmp(event, "setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
|
||||
else if (!strcmp(event, "death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "join")) {
|
||||
usl = uwsgi_string_new_list(&ul->join_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-joined")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-left")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
|
||||
}
|
||||
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!usl)
|
||||
return;
|
||||
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
|
||||
char *hook = strchr(action, ':');
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// pointer to action plugin
|
||||
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
|
||||
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
|
||||
// add that to check the plugin value
|
||||
usl->custom = port - usl->value + 1;
|
||||
}
|
||||
usl->custom = hook - action + 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -869,6 +1062,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
*colon = 0;
|
||||
char *secret = colon + 1;
|
||||
|
||||
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
|
||||
}
|
||||
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
|
||||
char *iv = strchr(secret, ' ');
|
||||
if (iv) {
|
||||
*iv = 0;
|
||||
@@ -882,9 +1079,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -937,10 +1134,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
uwsgi.legion_scroll_max_size = 4096;
|
||||
}
|
||||
|
||||
if (!uwsgi.legion_scroll_list_max_size) {
|
||||
uwsgi.legion_scroll_list_max_size = 32768;
|
||||
}
|
||||
|
||||
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
|
||||
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
|
||||
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
@@ -954,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;
|
||||
@@ -976,8 +1182,18 @@ 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) {
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
while (legion) {
|
||||
legion->dead = 1;
|
||||
uwsgi_legion_announce(legion);
|
||||
legion = legion->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_legion_atexit(void) {
|
||||
struct uwsgi_legion *legion = uwsgi.legions;
|
||||
@@ -996,6 +1212,10 @@ next:
|
||||
legion = legion->next;
|
||||
}
|
||||
|
||||
// this must be called only by the master !!!
|
||||
if (!uwsgi.workers) return;
|
||||
if (uwsgi.workers[0].pid != getpid()) return;
|
||||
uwsgi_legion_announce_death();
|
||||
}
|
||||
|
||||
int uwsgi_legion_i_am_the_lord(char *name) {
|
||||
@@ -1020,3 +1240,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (!legion) return NULL;
|
||||
uwsgi_rlock(legion->lock);
|
||||
buf = uwsgi_malloc(legion->scrolls_len);
|
||||
memcpy(buf, legion->scrolls, legion->scrolls_len);
|
||||
*rlen = legion->scrolls_len;
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
+137
-14
@@ -401,6 +401,60 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
|
||||
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
|
||||
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
struct _SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = 1;
|
||||
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
WaitForSingleObject(uli->lock_ptr, INFINITE);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
ReleaseMutex(uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
return uwsgi_lock_fast_init(id);
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
@@ -420,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
@@ -441,7 +493,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
@@ -452,7 +504,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
}
|
||||
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
@@ -460,7 +512,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -480,7 +532,13 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +555,13 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -522,6 +586,8 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
if (uwsgi.persistent_ipcsem) return;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers)
|
||||
@@ -542,12 +608,27 @@ clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
#ifdef GETPID
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
int ret = semctl(semid, 0, GETPID);
|
||||
if (ret > 0) {
|
||||
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
|
||||
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
uli = uwsgi.registered_locks;
|
||||
#endif
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
@@ -558,6 +639,33 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_ipcsem_check(uli);
|
||||
}
|
||||
|
||||
#ifdef UNBIT
|
||||
/*
|
||||
Unbit-specific workaround for robust-mutexes
|
||||
*/
|
||||
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
|
||||
for(;;) {
|
||||
uwsgi_lock(uwsgi.the_thunder_lock);
|
||||
uwsgi_unlock(uwsgi.the_thunder_lock);
|
||||
sleep(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void uwsgi_robust_mutexes_watchdog() {
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
// 32K should be more than enough...
|
||||
pthread_attr_setstacksize(&attr, 32 * 1024);
|
||||
|
||||
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
|
||||
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void uwsgi_setup_locking() {
|
||||
|
||||
@@ -607,7 +715,9 @@ ready:
|
||||
// application generic lock
|
||||
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
|
||||
for (i = 0; i < uwsgi.locks + 1; i++) {
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
|
||||
char *num = uwsgi_num2str(i);
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
|
||||
free(num);
|
||||
}
|
||||
|
||||
// event queue lock (mitigate same event on multiple queues)
|
||||
@@ -625,9 +735,6 @@ ready:
|
||||
// timer table lock
|
||||
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
|
||||
|
||||
// probe table lock
|
||||
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
|
||||
|
||||
// rb_timer table lock
|
||||
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
|
||||
|
||||
@@ -638,6 +745,14 @@ ready:
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
// process shared thunder lock
|
||||
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
|
||||
#ifdef UNBIT
|
||||
// we have a serious bug on Unbit (and very probably on older libc)
|
||||
// when all of the workers die in the same moment the pthread robust mutes is left
|
||||
// in inconsistent state and we have no way to recover
|
||||
// we span a thread in the master constantly ensuring the lock is ok
|
||||
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
|
||||
uwsgi_robust_mutexes_watchdog();
|
||||
#endif
|
||||
}
|
||||
|
||||
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
|
||||
@@ -713,10 +828,18 @@ nextlock:
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_user_lock(int lock_num) {
|
||||
int uwsgi_user_lock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_user_unlock(int lock_num) {
|
||||
int uwsgi_user_unlock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+843
-346
File diff suppressed because it is too large
Load Diff
+390
-220
@@ -2,15 +2,40 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_restore_auto_snapshot(int signum) {
|
||||
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) {
|
||||
if (uwsgi_worker_is_busy(i) == 0) {
|
||||
idle_workers++;
|
||||
}
|
||||
else {
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.workers[1].snapshot > 0) {
|
||||
uwsgi.restore_snapshot = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[WARNING] no snapshot available\n");
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
ushared->idle_workers = idle_workers;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_block_signal(int signum) {
|
||||
@@ -32,24 +57,25 @@ void uwsgi_unblock_signal(int signum) {
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_udp(int udp_fd) {
|
||||
char buf[4096];
|
||||
struct sockaddr_in udp_client;
|
||||
char udp_client_addr[16];
|
||||
int i;
|
||||
|
||||
socklen_t udp_len = sizeof(udp_client);
|
||||
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
|
||||
memset(udp_client_addr, 0, 16);
|
||||
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
|
||||
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
}
|
||||
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
else if (buf[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -57,7 +83,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
int udp_managed = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->manage_udp) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
|
||||
udp_managed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -66,74 +92,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
|
||||
// else a simple udp logger
|
||||
if (!udp_managed) {
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("inet_ntop()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_restore_snapshot() {
|
||||
int i, waitpid_status;
|
||||
uwsgi_log("[snapshot] restoring workers...\n");
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGURG);
|
||||
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.restore_snapshot = 0;
|
||||
}
|
||||
|
||||
void suspend_resume_them_all(int signum) {
|
||||
|
||||
int i;
|
||||
@@ -176,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -209,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
|
||||
}
|
||||
|
||||
|
||||
@@ -268,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,7 +318,6 @@ int master_loop(char **argv, char **environ) {
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
uwsgi_set_processname(uwsgi.procname_master);
|
||||
}
|
||||
@@ -332,9 +343,6 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
uwsgi_unix_signal(SIGINT, kill_them_all);
|
||||
uwsgi_unix_signal(SIGUSR1, stats);
|
||||
if (uwsgi.auto_snapshot) {
|
||||
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
|
||||
}
|
||||
|
||||
atexit(uwsgi_master_cleanup_hooks);
|
||||
|
||||
@@ -346,6 +354,17 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
if (uwsgi.master_fifo) {
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.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]);
|
||||
}
|
||||
@@ -374,6 +393,9 @@ int master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_start_legions();
|
||||
#endif
|
||||
uwsgi_metrics_start_collector();
|
||||
|
||||
uwsgi_add_reload_fds();
|
||||
|
||||
uwsgi_cache_start_sweepers();
|
||||
uwsgi_cache_start_sync_servers();
|
||||
@@ -381,9 +403,32 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
if (uwsgi.emperor_proxy) {
|
||||
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
|
||||
if (uwsgi.emperor_fd_proxy < 0) exit(1);
|
||||
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("[emperor-proxy] chmod()");
|
||||
exit(1);
|
||||
}
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
|
||||
}
|
||||
else {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
}
|
||||
}
|
||||
|
||||
#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);
|
||||
@@ -391,7 +436,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
if (uwsgi.stats) {
|
||||
char *tcp_port = strchr(uwsgi.stats, ':');
|
||||
char *tcp_port = strrchr(uwsgi.stats, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
@@ -473,6 +518,73 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
|
||||
// update exec touches
|
||||
struct uwsgi_string_list *usl = uwsgi.touch_exec;
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
// 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();
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
@@ -495,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);
|
||||
@@ -527,21 +640,6 @@ int master_loop(char **argv, char **environ) {
|
||||
// check for daemons (smart and dumb)
|
||||
uwsgi_daemons_smart_check();
|
||||
|
||||
|
||||
if (uwsgi.respawn_snapshots) {
|
||||
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
}
|
||||
|
||||
uwsgi.respawn_snapshots = 0;
|
||||
}
|
||||
|
||||
if (uwsgi.restore_snapshot) {
|
||||
uwsgi_master_restore_snapshot();
|
||||
continue;
|
||||
}
|
||||
|
||||
// cheaper management
|
||||
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (!uwsgi_calc_cheaper())
|
||||
@@ -570,9 +668,11 @@ 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];
|
||||
if (!check_interval)
|
||||
check_interval = uwsgi.master_interval;
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.master_interval = 1;
|
||||
}
|
||||
|
||||
|
||||
// add unregistered file monitors
|
||||
@@ -607,14 +707,14 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (ushared->rb_timers_cnt > 0) {
|
||||
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
}
|
||||
else {
|
||||
check_interval = min_timeout->value - uwsgi_now();
|
||||
if (check_interval <= 0) {
|
||||
if (min_timeout) {
|
||||
int delta = min_timeout->value - uwsgi_now();
|
||||
if (delta <= 0) {
|
||||
expire_rb_timeouts(rb_timers);
|
||||
check_interval = 0;
|
||||
}
|
||||
// if the timer expires before the check_interval, override it
|
||||
else if (delta < check_interval) {
|
||||
check_interval = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,6 +728,9 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// update load counter
|
||||
uwsgi_update_load_counters();
|
||||
|
||||
|
||||
// check uwsgi-cron table
|
||||
if (ushared->cron_cnt) {
|
||||
@@ -638,22 +741,6 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_manage_command_cron(uwsgi_now());
|
||||
}
|
||||
|
||||
|
||||
// check for probes
|
||||
if (ushared->probes_cnt > 0) {
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
for (i = 0; i < ushared->probes_cnt; i++) {
|
||||
if (interesting_fd == -1) {
|
||||
// increment cycles
|
||||
ushared->probes[i].cycles++;
|
||||
}
|
||||
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
|
||||
uwsgi_route_signal(ushared->probes[i].sig);
|
||||
}
|
||||
}
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
}
|
||||
|
||||
// some event returned
|
||||
if (rlen > 0) {
|
||||
// if the following function returns -1, a new worker has just spawned
|
||||
@@ -683,33 +770,26 @@ int master_loop(char **argv, char **environ) {
|
||||
// check for idle
|
||||
uwsgi_master_check_idle();
|
||||
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
check_interval = uwsgi.master_interval;
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
|
||||
|
||||
// get listen_queue status
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
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
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
uwsgi.master_interval = 1;
|
||||
}
|
||||
|
||||
// check if some worker has to die (harakiri, evil checks...)
|
||||
uwsgi_master_check_workers_deadline();
|
||||
|
||||
uwsgi_master_check_gateways_deadline();
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
// check listen_queue status
|
||||
master_check_listen_queue();
|
||||
|
||||
int someone_killed = 0;
|
||||
// check if some worker has to die (harakiri, evil checks...)
|
||||
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++;
|
||||
|
||||
// this could trigger a complete exit...
|
||||
uwsgi_master_check_mountpoints();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
@@ -720,7 +800,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
|
||||
// resubscribe every 10 cycles by default
|
||||
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
uwsgi_subscribe_all(0, 0);
|
||||
}
|
||||
|
||||
@@ -744,28 +824,63 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
continue;
|
||||
}
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_reload_workers();
|
||||
continue;
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
if (touched) {
|
||||
if (uwsgi.status.chain_reloading == 0) {
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
}
|
||||
}
|
||||
|
||||
// be sure to run it as the last touch check
|
||||
touched = uwsgi_check_touches(uwsgi.touch_exec);
|
||||
if (touched) {
|
||||
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
// killing process group failed, try to kill by process id
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -780,11 +895,18 @@ int master_loop(char **argv, char **environ) {
|
||||
// reload gateways and daemons only on normal workflow (+outworld status)
|
||||
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
|
||||
|
||||
if (uwsgi_master_check_emperor_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_emperor_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -798,8 +920,8 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
*/
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
int thewid = find_worker_id(diedpid);
|
||||
if (thewid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -813,6 +935,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;
|
||||
}
|
||||
}
|
||||
@@ -842,50 +965,66 @@ next:
|
||||
|
||||
|
||||
// ok a worker died...
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi.workers[thewid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[thewid].harakiri = 0;
|
||||
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
|
||||
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
|
||||
if (!uwsgi.workers[thewid].cursed_at)
|
||||
uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are stopping workers, just end here
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
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", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_BRUTAL_RELOAD_CODE) {
|
||||
uwsgi_log("!!! inconsistent state reported by worker %d (pid: %d) !!!\n", thewid, (int) diedpid);
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (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", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
|
||||
else if (uwsgi.workers[thewid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
|
||||
}
|
||||
// manage_next_request is zero, but killed by signal...
|
||||
else if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
if (uwsgi.workers[thewid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -909,12 +1048,12 @@ next:
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
|
||||
// are we chain reloading it ?
|
||||
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
|
||||
if (uwsgi.status.chain_reloading == thewid) {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
|
||||
// respawn the worker (if needed)
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid))
|
||||
if (uwsgi_respawn_worker(thewid))
|
||||
return 0;
|
||||
|
||||
// end of the loop
|
||||
@@ -922,3 +1061,34 @@ next:
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
void uwsgi_reload_workers() {
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
void uwsgi_chain_reload() {
|
||||
if (!uwsgi.status.chain_reloading) {
|
||||
uwsgi_log_verbose("chain reload starting...\n");
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("chain reload already running...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_brutally_reload_workers() {
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+133
-13
@@ -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,18 +40,44 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
|
||||
// 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;
|
||||
}
|
||||
int i;
|
||||
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -107,11 +138,29 @@ void uwsgi_master_check_idle() {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
// first send SIGINT
|
||||
kill(uwsgi.workers[i].pid, SIGINT);
|
||||
// and start waiting upto 3 seconds
|
||||
int j;
|
||||
for(j=0;j<3;j++) {
|
||||
sleep(1);
|
||||
int ret = waitpid(uwsgi.workers[i].pid, &waitpid_status, WNOHANG);
|
||||
if (ret == 0) continue;
|
||||
if (ret == (int) uwsgi.workers[i].pid) goto done;
|
||||
// on error, directly send SIGKILL
|
||||
break;
|
||||
}
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
done:
|
||||
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);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
@@ -120,19 +169,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
|
||||
@@ -141,6 +193,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) {
|
||||
@@ -148,15 +201,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,28 +220,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) {
|
||||
@@ -194,21 +253,41 @@ 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
|
||||
if (uwsgi.mules[i].user_harakiri > 0) {
|
||||
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].user_harakiri = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +348,7 @@ int uwsgi_master_check_daemons_death(int diedpid) {
|
||||
|
||||
int uwsgi_worker_is_busy(int wid) {
|
||||
int i;
|
||||
if (uwsgi.workers[uwsgi.mywid].sig) return 1;
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
if (uwsgi.workers[wid].cores[i].in_request) {
|
||||
return 1;
|
||||
@@ -276,3 +356,43 @@ int uwsgi_worker_is_busy(int wid) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_cron_death(int diedpid) {
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid == (pid_t) diedpid) {
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
|
||||
uc->pid = -1;
|
||||
uc->started_at = 0;
|
||||
return -1;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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() {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
|
||||
if (uwsgi_check_mountpoint(usl->value)) {
|
||||
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
|
||||
uwsgi_nuclear_blast();
|
||||
//never here
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,14 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -36,12 +44,97 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
|
||||
// emperor event ?
|
||||
if (uwsgi.has_emperor) {
|
||||
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
|
||||
uwsgi_master_manage_emperor_proxy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (interesting_fd == uwsgi.emperor_fd) {
|
||||
uwsgi_master_manage_emperor();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
// reload on fd
|
||||
if (uwsgi.reload_on_fd) {
|
||||
// custom -> fd
|
||||
// custom2 -> len (optional, default 1)
|
||||
// custom_ptr -> log message (optional)
|
||||
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
|
||||
while(usl) {
|
||||
if (interesting_fd == (int) usl->custom) {
|
||||
char stack_tmp[8];
|
||||
char *tmp = stack_tmp;
|
||||
if (usl->custom2 > 8) {
|
||||
tmp = uwsgi_malloc(usl->custom2);
|
||||
}
|
||||
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
|
||||
uwsgi_error("[reload-on-fd] read()");
|
||||
}
|
||||
if (usl->custom_ptr) {
|
||||
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
|
||||
}
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
// brutal reload on fd
|
||||
if (uwsgi.brutal_reload_on_fd) {
|
||||
// custom -> fd
|
||||
// custom2 -> len (optional, default 1)
|
||||
// custom_ptr -> log message (optional)
|
||||
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
|
||||
while(usl) {
|
||||
if (interesting_fd == (int) usl->custom) {
|
||||
char stack_tmp[8];
|
||||
char *tmp = stack_tmp;
|
||||
if (usl->custom2 > 8) {
|
||||
tmp = uwsgi_malloc(usl->custom2);
|
||||
}
|
||||
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
|
||||
uwsgi_error("[brutal-reload-on-fd] read()");
|
||||
}
|
||||
if (usl->custom_ptr) {
|
||||
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
|
||||
}
|
||||
if (uwsgi.die_on_term) {
|
||||
uwsgi_block_signal(SIGQUIT);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGQUIT);
|
||||
}
|
||||
else {
|
||||
uwsgi_block_signal(SIGTERM);
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
if (usl->custom2 > 8) free(tmp);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wakeup from cheap mode ?
|
||||
if (uwsgi.status.is_cheap) {
|
||||
|
||||
+603
-226
File diff suppressed because it is too large
Load Diff
+1081
File diff suppressed because it is too large
Load Diff
+262
@@ -0,0 +1,262 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
|
||||
|
||||
to simplify setups (expecially because the mount command could not be available in
|
||||
the initial phase of jailing, we need an api to mount/umount filesystems
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, int flags);
|
||||
int uwsgi_umount(char *where, int flags);
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
char *key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_BIND
|
||||
{"bind", MS_BIND},
|
||||
#endif
|
||||
#ifdef MS_DIRSYNC
|
||||
{"dirsync", MS_DIRSYNC},
|
||||
#endif
|
||||
#ifdef MS_MANDLOCK
|
||||
{"mandlock", MS_MANDLOCK},
|
||||
#endif
|
||||
#ifdef MS_MOVE
|
||||
{"move", MS_MOVE},
|
||||
#endif
|
||||
#ifdef MS_NOATIME
|
||||
{"noatime", MS_NOATIME},
|
||||
#endif
|
||||
#ifdef MS_NODEV
|
||||
{"nodev", MS_NODEV},
|
||||
#endif
|
||||
#ifdef MS_NOEXEC
|
||||
{"noexec", MS_NOEXEC},
|
||||
#endif
|
||||
#ifdef MS_RDONLY
|
||||
{"rdonly", MS_RDONLY},
|
||||
{"readonly", MS_RDONLY},
|
||||
{"ro", MS_RDONLY},
|
||||
#endif
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_NOSUID
|
||||
{"nosuid", MS_NOSUID},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
#ifdef MNT_FORCE
|
||||
{"force", MNT_FORCE},
|
||||
#endif
|
||||
#ifdef MNT_DETACH
|
||||
{"detach", MNT_DETACH},
|
||||
#endif
|
||||
#ifdef MS_REC
|
||||
{"rec", MS_REC},
|
||||
{"recursive", MS_REC},
|
||||
#endif
|
||||
#ifdef MS_PRIVATE
|
||||
{"private", MS_PRIVATE},
|
||||
#endif
|
||||
#ifdef MS_SHARED
|
||||
{"shared", MS_SHARED},
|
||||
#endif
|
||||
#ifdef MNT_RDONLY
|
||||
{"rdonly", MNT_RDONLY},
|
||||
{"readonly", MNT_RDONLY},
|
||||
{"ro", MNT_RDONLY},
|
||||
#endif
|
||||
#ifdef MNT_NOEXEC
|
||||
{"noexec", MNT_NOEXEC},
|
||||
#endif
|
||||
#ifdef MNT_NOSUID
|
||||
{"nosuid", MNT_NOSUID},
|
||||
#endif
|
||||
#ifdef MNT_NOATIME
|
||||
{"noatime", MNT_NOATIME},
|
||||
#endif
|
||||
#ifdef MNT_SNAPSHOT
|
||||
{"snapshot", MNT_SNAPSHOT},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
struct uwsgi_mount_flag *umf = umflags;
|
||||
while(umf->key) {
|
||||
if (!strcmp(umf->key, mflag)) return umf->value;
|
||||
umf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags, char *data) {
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown mount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, data);
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
iov[1].iov_base = fs;
|
||||
iov[1].iov_len = strlen(fs) + 1;
|
||||
|
||||
iov[2].iov_base = "fspath";
|
||||
iov[2].iov_len = 7;
|
||||
iov[3].iov_base = where;
|
||||
iov[3].iov_len = strlen(where) + 1;
|
||||
|
||||
iov[4].iov_base = "target";
|
||||
iov[4].iov_len = 7;
|
||||
iov[5].iov_base = what;
|
||||
iov[5].iov_len = strlen(what) + 1;
|
||||
|
||||
return nmount(iov, 6, (int) mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount(char *where, char *flags) {
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown umount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
// we need a special case for recursive umount
|
||||
if (mountflags & MS_REC) {
|
||||
mountflags &= ~MS_REC;
|
||||
int unmounted = 1;
|
||||
char *slashed = uwsgi_concat2(where, "/");
|
||||
while (unmounted) {
|
||||
unmounted = 0;
|
||||
FILE *procmounts = fopen("/proc/self/mounts", "r");
|
||||
if (!procmounts) {
|
||||
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
char line[1024];
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
char *delim0 = strchr(line, ' ');
|
||||
if (!delim0) continue;
|
||||
delim0++;
|
||||
char *delim1 = strchr(delim0, ' ');
|
||||
if (!delim1) continue;
|
||||
*delim1 = 0;
|
||||
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
|
||||
continue;
|
||||
unmountable:
|
||||
if (!umount2(delim0, mountflags)) unmounted++;
|
||||
}
|
||||
fclose(procmounts);
|
||||
}
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
return unmount(where, mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_mount_hook(char *arg) {
|
||||
char *data = NULL;
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *fs = tmp_arg;
|
||||
char *what = strchr(fs, ' ');
|
||||
if (!what) goto error;
|
||||
*what = 0; what++;
|
||||
char *where = strchr(what, ' ');
|
||||
if (!where) goto error;
|
||||
*where = 0; where++;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
data = strchr(flags, ' ');
|
||||
if (data) {
|
||||
*data = 0; data++;
|
||||
}
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags, data)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
error:
|
||||
free(tmp_arg);
|
||||
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *where = tmp_arg;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_umount(where, flags)) {
|
||||
uwsgi_error("uwsgi_umount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_check_mountpoint(char *mountpoint) {
|
||||
#ifdef __linux__
|
||||
struct statfs sfs;
|
||||
int ret = statfs(mountpoint, &sfs);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
uwsgi_log("this platform does not support mountpoints check !!!\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
+40
-28
@@ -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);
|
||||
@@ -77,19 +77,9 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
|
||||
uwsgi_mule_run();
|
||||
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
@@ -98,6 +88,23 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_run() {
|
||||
int id = uwsgi.muleid;
|
||||
int i;
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
@@ -184,6 +191,7 @@ void uwsgi_mule_handler() {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -197,7 +205,9 @@ void uwsgi_mule_handler() {
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("uwsgi_mule_handler/read()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i, found = 0;
|
||||
@@ -319,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);
|
||||
}
|
||||
@@ -343,6 +355,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
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);
|
||||
}
|
||||
@@ -350,7 +363,7 @@ next:
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
@@ -369,6 +382,7 @@ next:
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
@@ -406,12 +420,12 @@ void uwsgi_setup_mules_and_farms() {
|
||||
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
|
||||
|
||||
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
|
||||
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
|
||||
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.mules[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.mules[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
uwsgi.mules[i].id = i + 1;
|
||||
|
||||
@@ -437,14 +451,14 @@ void uwsgi_setup_mules_and_farms() {
|
||||
mules_list++;
|
||||
|
||||
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
|
||||
free(farm_value);
|
||||
|
||||
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.farms[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mules_list, ",", p, ctx) {
|
||||
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
|
||||
if (!um) {
|
||||
uwsgi_log("invalid mule id: %s\n", p);
|
||||
@@ -452,13 +466,11 @@ void uwsgi_setup_mules_and_farms() {
|
||||
}
|
||||
|
||||
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
|
||||
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
|
||||
|
||||
farm_name = farm_name->next;
|
||||
|
||||
free(farm_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-1
@@ -1,4 +1,4 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+199
-4
@@ -55,9 +55,45 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] created session %p\n", uor);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offload engine:
|
||||
fd -> the file descriptor to read from
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (uor->fd < 0 || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
memory offload engine:
|
||||
buf -> pointer to the memory to transfer (memory is freed at the end)
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->buf || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
transfer offload engine:
|
||||
@@ -66,13 +102,13 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
|
||||
uor->fd = uwsgi_connect(uor->name, 0, 1);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error("u_offload_transfer_prepare()/connect()");
|
||||
return -1;
|
||||
@@ -126,6 +162,12 @@ static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsg
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
|
||||
// call the free function asap
|
||||
if (uor->free) {
|
||||
uor->free(uor);
|
||||
}
|
||||
|
||||
// close the socket and the file descriptor
|
||||
if (uor->takeover && uor->s > -1) {
|
||||
close(uor->s);
|
||||
@@ -164,12 +206,41 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
|
||||
uwsgi_buffer_destroy(uor->ubuf);
|
||||
}
|
||||
|
||||
if (uor->ubuf1) {
|
||||
uwsgi_buffer_destroy(uor->ubuf1);
|
||||
}
|
||||
if (uor->ubuf2) {
|
||||
uwsgi_buffer_destroy(uor->ubuf2);
|
||||
}
|
||||
if (uor->ubuf3) {
|
||||
uwsgi_buffer_destroy(uor->ubuf3);
|
||||
}
|
||||
if (uor->ubuf4) {
|
||||
uwsgi_buffer_destroy(uor->ubuf4);
|
||||
}
|
||||
if (uor->ubuf5) {
|
||||
uwsgi_buffer_destroy(uor->ubuf5);
|
||||
}
|
||||
if (uor->ubuf6) {
|
||||
uwsgi_buffer_destroy(uor->ubuf6);
|
||||
}
|
||||
if (uor->ubuf7) {
|
||||
uwsgi_buffer_destroy(uor->ubuf7);
|
||||
}
|
||||
if (uor->ubuf8) {
|
||||
uwsgi_buffer_destroy(uor->ubuf8);
|
||||
}
|
||||
|
||||
if (uor->pipe[0] != -1) {
|
||||
close(uor->pipe[1]);
|
||||
close(uor->pipe[0]);
|
||||
}
|
||||
|
||||
free(uor);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] destroyed session %p\n", uor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
@@ -204,6 +275,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);
|
||||
@@ -240,6 +312,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
|
||||
return uwsgi_thread_new(uwsgi_offload_loop);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
offload memory transfer
|
||||
|
||||
uor->len -> the size of the memory chunk
|
||||
uor->buf -> the memory to transfer
|
||||
uor->written -> written bytes
|
||||
|
||||
status: none
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
if (fd == -1) {
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
return 0;
|
||||
}
|
||||
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
|
||||
if (rlen > 0) {
|
||||
uor->written += rlen;
|
||||
if (uor->written >= uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_memory_do()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
the offload task starts after having acquired the file fd
|
||||
@@ -257,7 +362,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
|
||||
return 0;
|
||||
}
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
@@ -279,7 +384,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_sendfile_do()");
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
|
||||
off_t len = 0;
|
||||
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
|
||||
// transfer finished
|
||||
@@ -293,6 +398,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offloading
|
||||
status:
|
||||
0 -> waiting for data on fd
|
||||
1 -> waiting for write to s
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
// setup
|
||||
if (fd == -1) {
|
||||
event_queue_add_fd_read(ut->queue, uor->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(uor->status) {
|
||||
// read event from fd
|
||||
case 0:
|
||||
if (!uor->buf) {
|
||||
uor->buf = uwsgi_malloc(4096);
|
||||
}
|
||||
rlen = read(uor->fd, uor->buf, 4096);
|
||||
if (rlen > 0) {
|
||||
uor->to_write = rlen;
|
||||
uor->pos = 0;
|
||||
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
uor->status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> read()");
|
||||
}
|
||||
return -1;
|
||||
// write event on s
|
||||
case 1:
|
||||
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
|
||||
if (rlen > 0) {
|
||||
uor->to_write -= rlen;
|
||||
uor->pos += rlen;
|
||||
if (uor->to_write == 0) {
|
||||
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
|
||||
uor->status = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> write()");
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
the offload task starts soon after the call to connect()
|
||||
|
||||
@@ -325,6 +495,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;
|
||||
@@ -490,6 +667,8 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
|
||||
void uwsgi_offload_engines_register_all() {
|
||||
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
|
||||
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
|
||||
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
|
||||
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
@@ -507,3 +686,19 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
|
||||
uor.ubuf = ubuf;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
|
||||
uor.buf = buf;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
|
||||
uor.fd = fd;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
+27
-6
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
if (!strcmp(p, "requires")) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
if (!plugin_already_loaded(equal+1)) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
@@ -24,7 +26,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int plugin_already_loaded(const char *plugin) {
|
||||
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
@@ -33,7 +35,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
@@ -41,7 +43,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +55,7 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
@@ -61,14 +63,21 @@ int plugin_already_loaded(const char *plugin) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
return uwsgi.p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int plugin_already_loaded(const char *plugin) {
|
||||
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
|
||||
if (up) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
@@ -91,6 +100,12 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
char *init_func = strchr(plugin_name, '|');
|
||||
if (init_func) {
|
||||
init_func[0] = 0;
|
||||
init_func++;
|
||||
}
|
||||
|
||||
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
|
||||
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
|
||||
need_free = 1;
|
||||
@@ -150,6 +165,12 @@ success:
|
||||
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
|
||||
}
|
||||
else {
|
||||
if (init_func) {
|
||||
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
|
||||
if (plugin_init_func) {
|
||||
plugin_init_func();
|
||||
}
|
||||
}
|
||||
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
if (!up) {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
|
||||
|
||||
/*
|
||||
|
||||
steps:
|
||||
|
||||
mkdir(.uwsgi_plugin_builder)
|
||||
generate .uwsgi_plugin_builder/uwsgi.h
|
||||
generate .uwsgi_plugin_builder/uwsgiconfig.py
|
||||
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
|
||||
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
|
||||
|
||||
*/
|
||||
|
||||
void uwsgi_build_plugin(char *directory) {
|
||||
|
||||
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
|
||||
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
|
||||
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *dot_h = uwsgi_get_dot_h();
|
||||
if (!dot_h) {
|
||||
uwsgi_log("unable to generate uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(dot_h) == 0) {
|
||||
free(dot_h);
|
||||
uwsgi_log("invalid uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (dot_h_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
|
||||
free(dot_h);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
|
||||
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *config_py = uwsgi_get_config_py();
|
||||
if (!config_py) {
|
||||
uwsgi_log("unable to generate uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(config_py) == 0) {
|
||||
uwsgi_log("invalid uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (config_py_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t config_py_len = (ssize_t) strlen(config_py);
|
||||
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *cflags = uwsgi_get_cflags();
|
||||
if (!cflags) {
|
||||
uwsgi_log("unable to find cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (strlen(cflags) == 0) {
|
||||
uwsgi_log("invalid cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
|
||||
uwsgi_error("uwsgi_build_plugin()/setenv()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// now run the python script
|
||||
char *argv[6];
|
||||
|
||||
argv[0] = getenv("PYTHON");
|
||||
if (!argv[0]) argv[0] = "python";
|
||||
|
||||
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
|
||||
argv[2] = "--extra-plugin";
|
||||
char *space = strchr(directory, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
argv[3] = directory;
|
||||
argv[4] = space+1;
|
||||
argv[5] = NULL;
|
||||
}
|
||||
else {
|
||||
argv[3] = directory;
|
||||
argv[4] = NULL;
|
||||
}
|
||||
|
||||
execvp(argv[0], argv);
|
||||
// never here...
|
||||
_exit(1);
|
||||
}
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
+196
-101
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this is line uwsgi_str_num but with security checks
|
||||
// this is like uwsgi_str_num but with security checks
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0;
|
||||
@@ -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("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;
|
||||
@@ -303,8 +228,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
uint16_t rlen = 0;
|
||||
uint16_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == ',') break;
|
||||
rlen++;
|
||||
}
|
||||
|
||||
// bytes=X-
|
||||
if (rlen < 8) return;
|
||||
char *equal = memchr(buf, '=', rlen);
|
||||
if (!equal) return;
|
||||
if (equal-buf != 5) return;
|
||||
if (memcmp(buf, "bytes", 5)) return;
|
||||
char *range = equal+1;
|
||||
rlen -= 6;
|
||||
char *dash = memchr(range, '-', rlen);
|
||||
if (!dash) return;
|
||||
*from = uwsgi_str_num(range, dash-range);
|
||||
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
|
||||
if (*to > 0 && *from > *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
|
||||
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
|
||||
wsgi_req->file = buf;
|
||||
wsgi_req->file_len = len;
|
||||
@@ -312,6 +270,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,6 +318,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
|
||||
wsgi_req->cookie = buf;
|
||||
wsgi_req->cookie_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
|
||||
wsgi_req->appid = buf;
|
||||
wsgi_req->appid_len = len;
|
||||
@@ -366,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;
|
||||
}
|
||||
|
||||
@@ -409,8 +386,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
|
||||
wsgi_req->pyhome = buf;
|
||||
wsgi_req->pyhome_len = len;
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -517,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;
|
||||
@@ -543,9 +520,33 @@ 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;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_X_FORWARDED_PROTO", 22)) {
|
||||
wsgi_req->scheme = buf;
|
||||
wsgi_req->scheme_len = len;
|
||||
}
|
||||
|
||||
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++) {
|
||||
@@ -563,6 +564,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -693,7 +695,7 @@ next:
|
||||
// check if data are available in the local cache
|
||||
if (wsgi_req->cache_get_len > 0) {
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -704,7 +706,7 @@ next:
|
||||
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
|
||||
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -734,25 +736,40 @@ next:
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
|
||||
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
|
||||
best_found = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
char* mountpoint = uwsgi_apps[i].mountpoint;
|
||||
int mountpoint_len = uwsgi_apps[i].mountpoint_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
// Ignore trailing mountpoint slashes
|
||||
if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') {
|
||||
mountpoint_len -= 1;
|
||||
}
|
||||
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
|
||||
// Check if mountpoint could be a possible candidate
|
||||
if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info
|
||||
mountpoint_len <= best_found || // it should be better than the previous found
|
||||
// should have the same prefix of path_info
|
||||
uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) ||
|
||||
// and should not be "misleading"
|
||||
(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
best_found = mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -962,8 +979,77 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
|
||||
}
|
||||
|
||||
|
||||
// this functions transform a raw HTTP response to a uWSGI-managed response
|
||||
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
|
||||
char *line = body;
|
||||
size_t line_len = 0;
|
||||
size_t i;
|
||||
int status_managed = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (body[i] == '\n') {
|
||||
// invalid line
|
||||
if (line_len < 1) {
|
||||
return -1;
|
||||
}
|
||||
if (line[line_len-1] != '\r') {
|
||||
return -1;
|
||||
}
|
||||
// end of the headers
|
||||
if (line_len == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status_managed) {
|
||||
char *colon = memchr(line, ':', line_len-1);
|
||||
if (!colon) return -1;
|
||||
if (colon[1] != ' ') return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
|
||||
}
|
||||
else {
|
||||
char *space = memchr(line, ' ', line_len-1);
|
||||
if (!space) return -1;
|
||||
if ((line_len-1) - ((space+1)-line) < 3) return -1;
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
|
||||
status_managed = 1;
|
||||
}
|
||||
line = NULL;
|
||||
line_len = 0;
|
||||
}
|
||||
else {
|
||||
if (!line) {
|
||||
line = body + i;
|
||||
}
|
||||
line_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i+1) < len) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
|
||||
|
||||
In such a case, allocate a proto_parser_buf and move data there
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
|
||||
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
|
||||
return NULL;
|
||||
@@ -985,7 +1071,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
wsgi_req->var_cnt++;
|
||||
ptr += keylen;
|
||||
|
||||
|
||||
|
||||
|
||||
*ptr++ = (uint8_t) (vallen & 0xff);
|
||||
*ptr++ = (uint8_t) ((vallen >> 8) & 0xff);
|
||||
@@ -1001,6 +1087,15 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
}
|
||||
|
||||
int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t need_slash = 0;
|
||||
if (wsgi_req->path_info_len > 0) {
|
||||
if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
|
||||
@@ -1043,13 +1138,13 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
|
||||
*ptr ++= '/';
|
||||
}
|
||||
memcpy(ptr, index, index_len);
|
||||
|
||||
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
|
||||
wsgi_req->var_cnt++;
|
||||
|
||||
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
|
||||
wsgi_req->path_info = new_path_info;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
QUERY_STRING management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
// search for the equal sign
|
||||
char *equal = memchr(qs, '=', qs_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qs_len -= (equal-qs)+1;
|
||||
if (qs_len == 0) return NULL;
|
||||
|
||||
*vallen = qs_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *qs = wsgi_req->query_string;
|
||||
uint16_t qs_len = 0;
|
||||
char *ptr = wsgi_req->query_string;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->query_string_len;i++) {
|
||||
if (!qs) {
|
||||
qs = ptr + i;
|
||||
}
|
||||
if (ptr[i] == '&') {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
qs_len = 0;
|
||||
qs = NULL;
|
||||
}
|
||||
else {
|
||||
qs_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qs_len > 0) {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+1
-1
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
|
||||
uwsgi.queue_header->pos = 0;
|
||||
uwsgi.queue_header->pull_pos = 0;
|
||||
}
|
||||
if (!uwsgi.queue) {
|
||||
if (uwsgi.queue == MAP_FAILED) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+89
-32
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
|
||||
struct pollfd upoll[2];
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll[0].fd = fd0;
|
||||
upoll[0].events = POLLIN;
|
||||
upoll[0].revents = 0;
|
||||
|
||||
upoll[1].fd = fd1;
|
||||
upoll[1].events = POLLIN;
|
||||
upoll[1].revents = 0;
|
||||
|
||||
int ret = poll(upoll, 2, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll[0].revents & POLLIN) {
|
||||
*fd = fd0;
|
||||
return 1;
|
||||
}
|
||||
if (upoll[1].revents & POLLIN) {
|
||||
*fd = fd1;
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
seek()/rewind() language-independent implementations.
|
||||
*/
|
||||
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
if (wsgi_req->post_file) {
|
||||
if (pos < 0) {
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
@@ -47,7 +82,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
|
||||
if (uwsgi.post_buffering) {
|
||||
if (pos < 0) {
|
||||
if (pos > (off_t) wsgi_req->post_pos) {
|
||||
if ((off_t) wsgi_req->post_pos - pos < 0) {
|
||||
wsgi_req->post_pos = 0;
|
||||
return;
|
||||
}
|
||||
@@ -88,14 +123,14 @@ 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 ?
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("consume_body_for_readline()/realloc()");
|
||||
uwsgi_req_error("consume_body_for_readline()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_readline_buf = tmp_buf;
|
||||
@@ -108,64 +143,69 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
|
||||
// read from a file
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
uwsgi_req_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read from post_buffering memory
|
||||
if (uwsgi.post_buffering) {
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from socket
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_timeout(remains);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -203,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
|
||||
wsgi_req->post_readline_buf = malloc(amount);
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
uwsgi_error("uwsgi_request_body_readline()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -216,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
|
||||
|
||||
if (consume_body_for_readline(wsgi_req)) {
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -271,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (avail > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
@@ -319,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
wsgi_req->post_read_buf = malloc(remains);
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -330,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -347,8 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_log("%llu\n", remains);
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/fread()");
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
*rlen += remains;
|
||||
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wait:
|
||||
@@ -389,6 +435,8 @@ wait:
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
|
||||
goto wait;
|
||||
}
|
||||
*rlen = -1;
|
||||
if (len == 0) {
|
||||
@@ -396,6 +444,7 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -407,6 +456,7 @@ wait:
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -426,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);
|
||||
@@ -445,6 +495,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -460,6 +511,7 @@ wait:
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -478,9 +530,10 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
int upload_progress_fd = -1;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
wsgi_req->post_file = tmpfile();
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
|
||||
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -497,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....
|
||||
@@ -516,6 +569,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -529,11 +583,13 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -541,7 +597,8 @@ wait:
|
||||
|
||||
write:
|
||||
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
+1372
-62
File diff suppressed because it is too large
Load Diff
+49
-16
@@ -1,8 +1,8 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
|
||||
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
|
||||
|
||||
struct uwsgi_rpc *urpc;
|
||||
int ret = -1;
|
||||
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
||||
already:
|
||||
memcpy(urpc->name, name, strlen(name));
|
||||
urpc->modifier1 = modifier1;
|
||||
urpc->plugin = plugin;
|
||||
urpc->args = args;
|
||||
urpc->func = func;
|
||||
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
||||
@@ -59,11 +59,11 @@ already:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
||||
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
|
||||
|
||||
struct uwsgi_rpc *urpc = NULL;
|
||||
uint64_t i;
|
||||
uint16_t ret = 0;
|
||||
uint64_t ret = 0;
|
||||
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max);
|
||||
|
||||
@@ -77,16 +77,23 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
}
|
||||
|
||||
if (urpc) {
|
||||
if (uwsgi.p[urpc->modifier1]->rpc) {
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
|
||||
if (urpc->plugin->rpc) {
|
||||
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
|
||||
size_t *r = (size_t *) data;
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
|
||||
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
|
||||
*r = uwsgi_str_num(value, vl);
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
@@ -97,9 +104,14 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(UMAX16);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
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)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,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;
|
||||
@@ -147,26 +159,47 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
// ok the reuqest is ready, let's send it in non blocking way
|
||||
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
// ok the request is ready, let's send it in non blocking way
|
||||
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;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uint8_t modifier2 = 0;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.socket_timeout, NULL, &modifier2)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// 64bit response ?
|
||||
if (modifier2 == 5) {
|
||||
size_t content_len = 0;
|
||||
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
|
||||
|
||||
if (content_len > rlen) {
|
||||
char *tmp_buf = realloc(buffer, content_len);
|
||||
if (!tmp_buf) goto error;
|
||||
buffer = tmp_buf;
|
||||
}
|
||||
|
||||
rlen = content_len;
|
||||
|
||||
// read the raw value from the socket
|
||||
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.socket_timeout)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
goto error;
|
||||
goto error2;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
error2:
|
||||
free(buffer);
|
||||
return NULL;
|
||||
|
||||
|
||||
+57
-8
@@ -4,26 +4,39 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
// sendfile() abstraction
|
||||
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
|
||||
if (uwsgi.disable_sendfile) goto no_sendfile;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sf_len = len;
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
|
||||
off_t sf_len = len;
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
#elif defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#else
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
#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:
|
||||
if (pos > 0) {
|
||||
if (lseek(filefd, pos, SEEK_SET)) {
|
||||
if (lseek(filefd, pos, SEEK_SET) < 0) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/seek()");
|
||||
return -1;
|
||||
}
|
||||
@@ -34,6 +47,42 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
return write(sockfd, buf, rlen);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
simple non blocking sendfile implementation
|
||||
(generally used as fallback)
|
||||
*/
|
||||
|
||||
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_sendfile()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
|
||||
//now close all the unbound fd
|
||||
for (j = 3; j < (int) uwsgi.max_fd; j++) {
|
||||
int useless = 1;
|
||||
|
||||
if (uwsgi_fd_is_safe(j)) continue;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (j == uwsgi.emperor_fd)
|
||||
continue;
|
||||
@@ -123,6 +126,16 @@ void uwsgi_setup_inherited_sockets() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (j == uwsgi.original_log_fd)
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is an high-performance memory area shared by all workers/cores/threads
|
||||
|
||||
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
|
||||
|
||||
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
|
||||
the language object.
|
||||
|
||||
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
|
||||
|
||||
You can configure multiple areas specifying multiple --sharedarea options
|
||||
|
||||
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
|
||||
if (id > uwsgi.sharedareas_cnt-1) return NULL;
|
||||
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
|
||||
if (pos > sa->max_pos) return NULL;
|
||||
return sa;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_update(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
sa->updates++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_rlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_wlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_unlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
if (len == 0) len = (sa->max_pos + 1) - pos;
|
||||
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
|
||||
uwsgi_rlock(sa->lock);
|
||||
memcpy(blob, sa->area + pos, len);
|
||||
sa->hits++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
memcpy(sa->area + pos, blob, len);
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
|
||||
return rlen == 8 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
|
||||
return rlen == 1 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
|
||||
return rlen == 2 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
|
||||
return rlen == 4 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
returns:
|
||||
0 -> on updates
|
||||
-1 -> on error
|
||||
-2 -> on timeout
|
||||
*/
|
||||
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
int waiting = 0;
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
if (!freq) freq = 100;
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || 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);
|
||||
if (sa->updates != updates) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
// unlock sa
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_new_id() {
|
||||
int id = uwsgi.sharedareas_cnt;
|
||||
uwsgi.sharedareas_cnt++;
|
||||
if (!uwsgi.sharedareas) {
|
||||
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
|
||||
}
|
||||
else {
|
||||
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
|
||||
if (!usa) {
|
||||
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas = usa;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_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));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = pages;
|
||||
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = area;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_pages = NULL;
|
||||
char *s_file = NULL;
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 (fd > -1) {
|
||||
sa = uwsgi_sharedarea_init_fd(fd, len, offset);
|
||||
}
|
||||
else if (area) {
|
||||
sa = uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sharedareas_init() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
|
||||
char *is_keyval = strchr(usl->value, '=');
|
||||
if (!is_keyval) {
|
||||
uwsgi_sharedarea_init(atoi(usl->value));
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_keyval(usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
-158
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
if (!uwsgi.master_process) {
|
||||
uwsgi_log("you cannot register signals without a master\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
||||
uwsgi_log("only the master and the workers can register signal handlers\n");
|
||||
@@ -137,7 +140,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
int pos = (i * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,89 +180,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
|
||||
if (!uwsgi_up) {
|
||||
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
uwsgi_up = *up;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_up) {
|
||||
old_up = uwsgi_up;
|
||||
uwsgi_up = uwsgi_up->next;
|
||||
}
|
||||
|
||||
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
|
||||
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
|
||||
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
|
||||
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while (up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fill the probe table
|
||||
ushared->probes[ushared->probes_cnt].func = up->func;
|
||||
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
|
||||
ushared->probes[ushared->probes_cnt].registered = 0;
|
||||
ushared->probes[ushared->probes_cnt].sig = sig;
|
||||
ushared->probes[ushared->probes_cnt].fd = -1;
|
||||
ushared->probes[ushared->probes_cnt].state = 0;
|
||||
ushared->probes[ushared->probes_cnt].last_event = 0;
|
||||
ushared->probes[ushared->probes_cnt].data = NULL;
|
||||
ushared->probes[ushared->probes_cnt].cycles = 0;
|
||||
ushared->probes[ushared->probes_cnt].bad = 0;
|
||||
|
||||
if (!timeout) {
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].timeout = timeout;
|
||||
if (!freq) {
|
||||
freq = 1;
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].freq = freq;
|
||||
ushared->probes_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
|
||||
if (ushared->timers_cnt < 64) {
|
||||
@@ -282,63 +206,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value + i;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
@@ -402,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;
|
||||
|
||||
}
|
||||
|
||||
@@ -434,8 +303,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
uwsgi.shared->unrouted_signals++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi.shared->routed_signals++;
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -460,6 +331,16 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// send to al lactive workers
|
||||
else if (!strcmp(use->receiver, "active-workers")) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && !uwsgi.workers[i].cheaped && !uwsgi.workers[i].suspended) {
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// route to specific worker
|
||||
else if (!strncmp(use->receiver, "worker", 6)) {
|
||||
i = atoi(use->receiver + 6);
|
||||
@@ -595,7 +476,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
+55
-14
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
|
||||
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
|
||||
|
||||
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
uwsgi_debug("SNMP version: %d\n", version);
|
||||
#endif
|
||||
|
||||
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
|
||||
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
|
||||
if (*ptr != SNMP_STRING)
|
||||
return;
|
||||
ptr++;
|
||||
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
ptr++;
|
||||
|
||||
oidlen = *ptr;
|
||||
if (oidlen != 11)
|
||||
if (oidlen < 11)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
|
||||
oid_part[0] = *ptr;
|
||||
|
||||
if (oid_part[0] != 1 && oid_part[0] != 2)
|
||||
return;
|
||||
ptr++;
|
||||
// old-style SNMP metrics
|
||||
if (oid_part[0] == 1 || oid_part[0] == 2) {
|
||||
ptr++;
|
||||
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
// metrics subsystem
|
||||
else {
|
||||
size_t metric_asn_len = oidlen - 9;
|
||||
char *metric_asn = (char *) ptr;
|
||||
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
|
||||
if (!um) return;
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int64_t value = *um->value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
|
||||
if (size > 0) {
|
||||
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
uint8_t tlen;
|
||||
int i, j;
|
||||
uint8_t *ptr = (uint8_t *) & snmp_val;
|
||||
int32_t val32 = (int32_t) snmp_val;
|
||||
|
||||
// check for counter, counter64 or gauge
|
||||
|
||||
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
}
|
||||
else {
|
||||
tlen = 4;
|
||||
ptr = (uint8_t *) &val32;
|
||||
}
|
||||
|
||||
buffer[0] = tlen;
|
||||
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
|
||||
|
||||
}
|
||||
|
||||
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
|
||||
uint8_t oid_sz;
|
||||
|
||||
if (type == UWSGI_METRIC_GAUGE) {
|
||||
buffer[size - 2] = SNMP_GAUGE;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
|
||||
}
|
||||
else {
|
||||
buffer[size - 2] = SNMP_COUNTER64;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
|
||||
}
|
||||
|
||||
if (oid_sz < 1)
|
||||
return -1;
|
||||
|
||||
oid_sz--;
|
||||
|
||||
buffer[1] += oid_sz;
|
||||
*seq1 += oid_sz;
|
||||
*seq2 += oid_sz;
|
||||
*seq3 += oid_sz;
|
||||
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
|
||||
uwsgi.snmp = 1;
|
||||
if (value) {
|
||||
|
||||
+299
-182
@@ -2,6 +2,43 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int connect_to_unix(char *, int, int);
|
||||
static int connect_to_tcp(char *, int, int, int);
|
||||
static int connect_to_udp(char *, int);
|
||||
|
||||
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
|
||||
if (!protocol) protocol = "uwsgi";
|
||||
struct uwsgi_protocol *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(protocol, up->name)) {
|
||||
up->func(uwsgi_sock);
|
||||
return;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to find protocol %s\n", protocol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
|
||||
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
|
||||
sock1 += 7;
|
||||
sock1_len = strlen(sock1);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
|
||||
sock2 += 7;
|
||||
sock2_len = strlen(sock2);
|
||||
}
|
||||
|
||||
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
|
||||
}
|
||||
|
||||
char *uwsgi_getsockname(int fd) {
|
||||
|
||||
socklen_t socket_type_len = sizeof(struct sockaddr_un);
|
||||
@@ -39,20 +76,69 @@ 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();
|
||||
}
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_DGRAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
}
|
||||
|
||||
uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
|
||||
@@ -68,6 +154,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
@@ -83,6 +170,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (strlen(socket_name) > 102) {
|
||||
uwsgi_log("invalid socket name\n");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socket_name[0] == '@') {
|
||||
@@ -96,17 +184,18 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (uws_addr == NULL) {
|
||||
uwsgi_error("malloc()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
free(uws_addr);
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,12 +229,13 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
@@ -173,7 +263,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;
|
||||
|
||||
@@ -218,15 +307,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
|
||||
@@ -270,36 +352,46 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_connect_do(char *socket_name, int timeout, int async) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
return connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
}
|
||||
|
||||
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
|
||||
|
||||
int fd;
|
||||
|
||||
char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
|
||||
fd = uwsgi_connect(zeroed_socket_name, timeout, async);
|
||||
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_connect(char *socket_name, int timeout, int async) {
|
||||
|
||||
int ret;
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
ret = connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
// reset the socket name
|
||||
tcp_port--;
|
||||
tcp_port[0] = ':';
|
||||
return ret;
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
int uwsgi_connect_udp(char *socket_name) {
|
||||
int fd = -1;
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
char *udp_port = strchr(zeroed_socket_name, ':');
|
||||
if (!udp_port) goto end;
|
||||
*udp_port = 0;
|
||||
udp_port++;
|
||||
fd = connect_to_udp(zeroed_socket_name, atoi(udp_port));
|
||||
end:
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_un uws_addr;
|
||||
@@ -344,7 +436,7 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_in uws_addr;
|
||||
@@ -361,15 +453,13 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
socket_name[strlen(socket_name)] = ':';
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_error("connect_to_tcp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -385,6 +475,38 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
static int connect_to_udp(char *socket_name, int port) {
|
||||
|
||||
struct sockaddr_in uws_addr;
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("connect_to_udp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *generate_socket_name(char *socket_name) {
|
||||
|
||||
char *asterisk = strchr(socket_name, '*');
|
||||
@@ -444,6 +566,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
ifa = ifap;
|
||||
while (ifa) {
|
||||
memset(new_addr, 0, 16);
|
||||
if (!ifa->ifa_addr) goto next;
|
||||
sin = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if (inet_ntop(AF_INET, (void *) &sin->sin_addr.s_addr, new_addr, 16)) {
|
||||
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
|
||||
@@ -456,6 +579,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
|
||||
}
|
||||
|
||||
next:
|
||||
ifaf = ifa;
|
||||
ifa = ifaf->ifa_next;
|
||||
|
||||
@@ -539,7 +663,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);
|
||||
|
||||
@@ -557,17 +680,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();
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
serverfd = create_server_socket(family, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef IP_FREEBIND
|
||||
#define IP_FREEBIND 15
|
||||
@@ -576,6 +691,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("IP_FREEBIND setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -585,6 +701,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEPORT setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
@@ -611,13 +728,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
|
||||
uwsgi_error("SO_SNDTIMEO setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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 !!!
|
||||
@@ -645,19 +763,13 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
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();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1246,7 +1358,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
|
||||
}
|
||||
else if (uwsgi_sock->fd > -1) {
|
||||
@@ -1440,6 +1552,9 @@ void uwsgi_setup_shared_sockets() {
|
||||
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
shared_sock->family = AF_UNIX;
|
||||
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
@@ -1476,7 +1591,7 @@ void uwsgi_setup_shared_sockets() {
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
char *sock = uwsgi_getsockname(i);
|
||||
if (sock) {
|
||||
if (!strcmp(sock, shared_sock->name)) {
|
||||
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
|
||||
if (strchr(sock, ':')) {
|
||||
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
|
||||
shared_sock->family = AF_INET;
|
||||
@@ -1530,8 +1645,8 @@ void uwsgi_map_sockets() {
|
||||
}
|
||||
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
|
||||
enabled = 0;
|
||||
char *p = strtok(colon + 1, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
|
||||
int w = atoi(p);
|
||||
if (w < 1 || w > uwsgi.numproc) {
|
||||
uwsgi_log("invalid worker num: %d\n", w);
|
||||
@@ -1542,7 +1657,6 @@ void uwsgi_map_sockets() {
|
||||
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
|
||||
break;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1551,18 +1665,7 @@ void uwsgi_map_sockets() {
|
||||
|
||||
if (!enabled) {
|
||||
close(uwsgi_sock->fd);
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (fd != uwsgi_sock->fd) {
|
||||
if (dup2(fd, uwsgi_sock->fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
|
||||
uwsgi_sock->disabled = 1;
|
||||
}
|
||||
|
||||
@@ -1592,6 +1695,10 @@ void uwsgi_bind_sockets() {
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
|
||||
char *tcp_port = strrchr(uwsgi_sock->name, ':');
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
if (uwsgi_sock->no_defer) {
|
||||
uwsgi.no_defer_accept = 1;
|
||||
}
|
||||
if (tcp_port == NULL) {
|
||||
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -1599,6 +1706,10 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
|
||||
struct stat st;
|
||||
if (uwsgi_sock->name[0] != '@' && !stat(uwsgi_sock->name, &st)) {
|
||||
uwsgi_sock->inode = st.st_ino;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
@@ -1621,18 +1732,12 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
int zero_used = 0;
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1653,6 +1758,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));
|
||||
@@ -1666,7 +1789,8 @@ void uwsgi_bind_sockets() {
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
uwsgi_log("WARNING: unable to remap stdin, /dev/null not available\n");
|
||||
goto stdin_done;
|
||||
}
|
||||
if (fd != 0) {
|
||||
if (dup2(fd, 0) < 0) {
|
||||
@@ -1684,6 +1808,15 @@ 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) {
|
||||
@@ -1730,96 +1863,8 @@ void uwsgi_set_sockets_protocols() {
|
||||
|
||||
|
||||
setup_proto:
|
||||
if (!requested_protocol) {
|
||||
requested_protocol = uwsgi.protocol;
|
||||
}
|
||||
|
||||
if (requested_protocol && !strcmp("http", requested_protocol)) {
|
||||
uwsgi_sock->proto = uwsgi_proto_http_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
|
||||
uwsgi.zeromq = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
if (!requested_protocol) requested_protocol = uwsgi.protocol;
|
||||
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
@@ -1836,3 +1881,75 @@ void uwsgi_tcp_nodelay(int fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_accept(int server_fd) {
|
||||
struct sockaddr_un client_src;
|
||||
memset(&client_src, 0, sizeof(struct sockaddr_un));
|
||||
socklen_t client_src_len = 0;
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
return accept4(server_fd, (struct sockaddr *) &client_src, &client_src_len, SOCK_NONBLOCK);
|
||||
#elif defined(__linux__)
|
||||
int client_fd = accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd >= 0) {
|
||||
uwsgi_socket_nb(client_fd);
|
||||
}
|
||||
return client_fd;
|
||||
#else
|
||||
return accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
|
||||
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(name, up->name)) {
|
||||
goto found;
|
||||
}
|
||||
old_up = up;
|
||||
up = up->next;
|
||||
}
|
||||
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
|
||||
up->name = name;
|
||||
if (old_up) {
|
||||
old_up->next = up;
|
||||
}
|
||||
else {
|
||||
uwsgi.protocols = up;
|
||||
}
|
||||
found:
|
||||
up->func = func;
|
||||
return up;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
|
||||
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
|
||||
#endif
|
||||
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
|
||||
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
|
||||
|
||||
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
|
||||
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
|
||||
|
||||
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
|
||||
}
|
||||
|
||||
+150
-50
@@ -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;
|
||||
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
// avoid race conditions !!!
|
||||
@@ -123,21 +122,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
|
||||
@@ -146,6 +131,26 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
void uwsgi_spooler_run() {
|
||||
int i;
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
}
|
||||
|
||||
void destroy_spool(char *dir, char *file) {
|
||||
|
||||
if (chdir(dir)) {
|
||||
@@ -162,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
|
||||
@@ -210,51 +293,67 @@ 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
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_log("[spooler] unable to write header for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, size) != size) {
|
||||
if (write(fd, buf, len) != (ssize_t) len) {
|
||||
uwsgi_log("[spooler] unable to write args for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (body && body_len > 0) {
|
||||
if ((size_t) write(fd, body, body_len) != body_len) {
|
||||
uwsgi_log("[spooler] unable to write body for %s\n", filename);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
if (at > 0) {
|
||||
if (sr.at > 0) {
|
||||
#ifdef __UCLIBC__
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = sr.at;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = sr.at;
|
||||
ts[1].tv_nsec = 0;
|
||||
if (futimens(fd, ts)) {
|
||||
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
|
||||
}
|
||||
|
||||
// here the file will be unlocked too
|
||||
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);
|
||||
@@ -274,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -348,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;
|
||||
}
|
||||
@@ -375,7 +475,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
|
||||
|
||||
struct dirent **tasklist;
|
||||
int n;
|
||||
int n, i;
|
||||
|
||||
if (!dir)
|
||||
dir = uspool->dir;
|
||||
@@ -386,9 +486,9 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (n--) {
|
||||
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
|
||||
free(tasklist[n]);
|
||||
for (i = 0; i < n; i++) {
|
||||
spooler_manage_task(uspool, dir, tasklist[i]->d_name);
|
||||
free(tasklist[i]);
|
||||
}
|
||||
|
||||
free(tasklist);
|
||||
@@ -533,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)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef UWSGI_SQLITE3
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+181
-21
@@ -1,5 +1,7 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
/*
|
||||
@@ -69,7 +71,11 @@ SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen,
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
|
||||
#else
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
|
||||
#endif
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return sess;
|
||||
}
|
||||
@@ -89,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;
|
||||
@@ -120,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:
|
||||
@@ -134,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);
|
||||
@@ -156,15 +210,35 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
ssloptions |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
if (!uwsgi.sslv3) {
|
||||
ssloptions |= SSL_OP_NO_SSLv3;
|
||||
}
|
||||
|
||||
// release/reuse buffers as soon as possibile
|
||||
#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
|
||||
@@ -173,26 +247,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) {
|
||||
@@ -220,19 +311,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -252,8 +361,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
|
||||
if (!uwsgi.ssl_sessions_cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
// check for default cache
|
||||
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
|
||||
uwsgi.ssl_sessions_cache = uwsgi.caches;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.ssl_sessions_cache->max_items) {
|
||||
@@ -285,6 +400,11 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.ssl_options) {
|
||||
ssloptions |= atoi(usl->value);
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ctx, ssloptions);
|
||||
|
||||
|
||||
@@ -406,8 +526,9 @@ char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
|
||||
}
|
||||
|
||||
char *uwsgi_ssl_rand(size_t len) {
|
||||
unsigned char *buf = uwsgi_calloc(len+1);
|
||||
unsigned char *buf = uwsgi_calloc(len);
|
||||
if (RAND_bytes(buf, len) <= 0) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
return (char *) buf;
|
||||
@@ -421,6 +542,14 @@ char *uwsgi_sha1(char *src, size_t len, char *dst) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_md5(char *src, size_t len, char *dst) {
|
||||
MD5_CTX md5;
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, src, len);
|
||||
MD5_Final((unsigned char *)dst, &md5);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
|
||||
SHA_CTX sha;
|
||||
SHA1_Init(&sha);
|
||||
@@ -490,10 +619,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);
|
||||
}
|
||||
|
||||
+76
-37
@@ -2,9 +2,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
|
||||
// check for filename size
|
||||
if (filename_len + 4 > PATH_MAX) return 0;
|
||||
if (*filename_len + 4 > PATH_MAX) return 0;
|
||||
// check for supported encodings
|
||||
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
|
||||
|
||||
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for dirs/prefix
|
||||
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
|
||||
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for ext/suffix
|
||||
usl = uwsgi.static_gzip_ext;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for regexp
|
||||
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
|
||||
goto gzip;
|
||||
}
|
||||
url = url->next;
|
||||
@@ -43,19 +43,19 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
|
||||
gzip:
|
||||
|
||||
memcpy(filename + filename_len, ".gz\0", 4);
|
||||
filename_len += 3;
|
||||
memcpy(filename + *filename_len, ".gz\0", 4);
|
||||
*filename_len += 3;
|
||||
|
||||
if (stat(filename, st)) {
|
||||
filename_len -= 3;
|
||||
filename[filename_len] = 0;
|
||||
*filename_len -= 3;
|
||||
filename[*filename_len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_http_date(time_t t, char *dst) {
|
||||
int uwsgi_http_date(time_t t, char *dst) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -429,21 +438,20 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
int use_gzip = 0;
|
||||
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -451,8 +459,34 @@ 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) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
@@ -460,6 +494,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_add_expires_uri(wsgi_req, st);
|
||||
#endif
|
||||
|
||||
if (use_gzip) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
|
||||
@@ -474,25 +512,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// apache
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// raw
|
||||
else {
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
// set Content-Length (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use the original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
|
||||
}
|
||||
// set Content-Length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
// if it is a HEAD request just skip transfer
|
||||
@@ -506,7 +544,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
int fd = open(real_filename, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
// fd will be closed in the following function
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
@@ -544,6 +582,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
if (item && item_len > 0 && item_len <= PATH_MAX) {
|
||||
memcpy(real_filename, item, item_len);
|
||||
real_filename_len = item_len;
|
||||
real_filename[real_filename_len] = 0;
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
goto found;
|
||||
}
|
||||
@@ -609,7 +648,7 @@ safe:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user