mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
edbff83fd6 |
@@ -1,3 +1,19 @@
|
||||
----------------------------------------------------------------------
|
||||
|
||||
LINKING EXCEPTION
|
||||
|
||||
In addition to the permissions in the GNU General Public License,
|
||||
the authors give you unlimited permission to link the compiled
|
||||
version of this library into combinations with other programs,
|
||||
and to distribute those combinations without any restriction
|
||||
coming from the use of this file. (The General Public License
|
||||
restrictions do apply in other respects; for example, they cover
|
||||
modification of the file, and distribution when not linked into
|
||||
a combined executable.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
PYTHON := python
|
||||
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
$(PYTHON) uwsgiconfig.py --clean
|
||||
|
||||
check:
|
||||
python uwsgiconfig.py --check
|
||||
$(PYTHON) uwsgiconfig.py --check
|
||||
|
||||
plugin.%:
|
||||
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
|
||||
|
||||
%:
|
||||
$(PYTHON) uwsgiconfig.py --build $@
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
surprise i am empty !
|
||||
The uWSGI project
|
||||
|
||||
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
|
||||
For commercial support check: http://unbit.com/
|
||||
|
||||
@@ -7,7 +7,7 @@ filename = sys.argv[1]
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
os.write(1, f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
os.write(1, (struct.pack("<Q", size)))
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
|
||||
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
|
||||
|
||||
+1
-5
@@ -2,22 +2,18 @@
|
||||
xml = auto
|
||||
yaml = true
|
||||
json = auto
|
||||
zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
matheval = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
matheval = false
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -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 = psgi
|
||||
inherit = minimal
|
||||
+2
-5
@@ -1,15 +1,12 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
xml = libxml2
|
||||
yaml = libyaml
|
||||
json = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = libyaml
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = pypy
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack
|
||||
inherit = minimal
|
||||
+2
-5
@@ -1,15 +1,12 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
xml = expat
|
||||
yaml = embedded
|
||||
json = false
|
||||
zeromq = false
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
[uwsgi]
|
||||
xml = expat
|
||||
yaml = embedded
|
||||
json = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = /opt/unbit/uwsgi/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
+88
-38
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general purpose async loop engine (it expects a coroutine based approach)
|
||||
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 in this list
|
||||
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 aftert he specified number of seconds (unless an event cancel it)
|
||||
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 !!!
|
||||
IMPORTANT: this is not a callback-based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
|
||||
}
|
||||
|
||||
void uwsgi_async_init() {
|
||||
int i;
|
||||
|
||||
uwsgi.async_queue = event_queue_init();
|
||||
|
||||
@@ -40,16 +39,9 @@ void uwsgi_async_init() {
|
||||
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
// a stack of unused cores
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
// fill it with default values
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
// the first available core is the last one
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -159,7 +151,7 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
// reset teh request
|
||||
// reset the request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
@@ -173,6 +165,11 @@ 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)
|
||||
@@ -224,8 +221,47 @@ 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) {
|
||||
@@ -236,6 +272,11 @@ 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)
|
||||
@@ -295,9 +336,8 @@ void async_schedule_to_req(void) {
|
||||
// a trick to avoid calling routes again
|
||||
uwsgi.wsgi_req->is_routing = 1;
|
||||
#endif
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
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);
|
||||
@@ -308,29 +348,43 @@ 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(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
uwsgi.wsgi_req->switches++;
|
||||
wsgi_req->switches++;
|
||||
if (uwsgi.schedule_fix) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
end:
|
||||
#endif
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
// re-set the global state
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
async_reset_request(wsgi_req);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
// re-set the global state (routing could have changed it)
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
|
||||
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
@@ -353,10 +407,13 @@ void async_loop() {
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi_async_init();
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
uwsgi.wait_read2_hook = async_wait_fd_read2;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
@@ -465,7 +522,8 @@ void async_loop() {
|
||||
// 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;
|
||||
}
|
||||
@@ -475,7 +533,7 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
// re-add timer
|
||||
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
async_add_timeout(uwsgi.wsgi_req, uwsgi.socket_timeout);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -511,19 +569,11 @@ void async_loop() {
|
||||
uwsgi.wsgi_req->switches++;
|
||||
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
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);
|
||||
// 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 the runqueue
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
current_request = next_request;
|
||||
}
|
||||
|
||||
|
||||
+19
-6
@@ -64,7 +64,7 @@ int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len)
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
if (ret <= 0 || ret >= 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_insert(ub, pos, chunked, ret);
|
||||
@@ -74,7 +74,7 @@ int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
|
||||
// 0xFFFFFFFFFFFFFFFF\r\n\0
|
||||
char chunked[19];
|
||||
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
|
||||
if (ret <= 0 || ret > 19) {
|
||||
if (ret <= 0 || ret >= 19) {
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_buffer_append(ub, chunked, ret);
|
||||
@@ -204,6 +204,19 @@ 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];
|
||||
@@ -232,7 +245,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);
|
||||
@@ -255,7 +268,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;
|
||||
@@ -267,7 +280,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;
|
||||
@@ -327,7 +340,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) {
|
||||
|
||||
+20
-20
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* how the cache bitmap works:
|
||||
|
||||
a bitmap is a shared mempry area allocated when requested by the user with --cache2
|
||||
a bitmap is a shared memory area allocated when requested by the user with --cache2
|
||||
|
||||
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
|
||||
the block is usable otherwise the block scanner will search for the next one.
|
||||
@@ -325,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
exit(1);
|
||||
}
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
|
||||
exit(1);
|
||||
}
|
||||
@@ -335,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
else {
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -773,7 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
}
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
@@ -1432,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
// ok now wait for the response, using the same buffer of the request
|
||||
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
|
||||
// try to fix the buffer to maintain size info
|
||||
ub->pos = rlen;
|
||||
|
||||
@@ -1483,7 +1483,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return NULL;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
@@ -1495,7 +1495,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
@@ -1526,7 +1526,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
}
|
||||
|
||||
// read the raw value from the socket
|
||||
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_whole_true_nb(fd, ub->buf, ucmc.size, uwsgi.socket_timeout)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
@@ -1585,7 +1585,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return 0;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
@@ -1597,7 +1597,7 @@ int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
@@ -1652,7 +1652,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1670,7 +1670,7 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, value, vallen, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1730,7 +1730,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1742,7 +1742,7 @@ int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1803,7 +1803,7 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
int fd = uwsgi_connect(cache_server, 0, 1);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_write_hook(fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
@@ -1815,7 +1815,7 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) {
|
||||
if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.socket_timeout, &ucmc)) {
|
||||
close(fd);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
@@ -1859,7 +1859,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.socket_timeout)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
@@ -1867,7 +1867,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.socket_timeout, NULL, NULL)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
@@ -1876,7 +1876,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, rlen, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.socket_timeout)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ extern struct uwsgi_server uwsgi;
|
||||
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
|
||||
|
||||
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
|
||||
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
if (timeout == 0) timeout = uwsgi.socket_timeout;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
+328
-6
@@ -293,8 +293,25 @@ int uwsgi_count_options(struct uwsgi_option *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 = uwsgi.options;
|
||||
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)) {
|
||||
@@ -303,10 +320,26 @@ struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
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;
|
||||
@@ -394,6 +427,15 @@ add:
|
||||
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 ?
|
||||
@@ -451,17 +493,16 @@ add:
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", key);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_fallback_config() {
|
||||
@@ -477,3 +518,284 @@ void uwsgi_fallback_config() {
|
||||
// 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;
|
||||
}
|
||||
|
||||
+145
-29
@@ -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:
|
||||
|
||||
@@ -55,7 +55,7 @@ void uwsgi_daemons_smart_check() {
|
||||
if (ud->pid > 0) {
|
||||
if (!kill(ud->pid, 0)) {
|
||||
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
|
||||
kill(-ud->pid, SIGTERM);
|
||||
kill(-ud->pid, ud->stop_signal);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
@@ -139,6 +139,10 @@ int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
}
|
||||
#endif
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
if (ud->control) {
|
||||
gracefully_kill_them_all(0);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
}
|
||||
@@ -228,14 +232,16 @@ void uwsgi_detach_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 gracefully stop daemon, kill it if it won't die
|
||||
// if mercy is not set than wait up to 3 seconds
|
||||
// try to stop daemon gracefully, kill it if it won't die
|
||||
// if mercy is not set then wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, SIGTERM);
|
||||
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 died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
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;
|
||||
}
|
||||
@@ -253,11 +259,12 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
// if ud->respawns == 0 then we can end up with throttle < 0
|
||||
if (throttle <= 0) throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -284,6 +291,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_close_all_sockets();
|
||||
uwsgi_close_all_fds();
|
||||
|
||||
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();
|
||||
@@ -297,20 +318,9 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -329,10 +339,10 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep(throttle);
|
||||
sleep((unsigned int) throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
|
||||
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);
|
||||
|
||||
@@ -351,6 +361,8 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
char *space = NULL;
|
||||
int stop_signal = SIGTERM;
|
||||
int reload_signal = 0;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
@@ -389,7 +401,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
}
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi.daemons;
|
||||
}
|
||||
else {
|
||||
@@ -398,7 +410,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;
|
||||
}
|
||||
|
||||
@@ -412,6 +424,12 @@ 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
|
||||
@@ -419,3 +437,101 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
|
||||
|
||||
char *d_command = NULL;
|
||||
char *d_freq = NULL;
|
||||
char *d_pidfile = NULL;
|
||||
char *d_control = NULL;
|
||||
char *d_legion = NULL;
|
||||
char *d_daemonize = NULL;
|
||||
char *d_touch = NULL;
|
||||
char *d_stopsignal = NULL;
|
||||
char *d_reloadsignal = NULL;
|
||||
char *d_stdin = NULL;
|
||||
char *d_uid = NULL;
|
||||
char *d_gid = NULL;
|
||||
|
||||
char *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,
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+316
-70
@@ -59,12 +59,12 @@ void uwsgi_emperor_blacklist_add(char *id) {
|
||||
uebi->throttle_level += (uwsgi.emperor_throttle * 1000);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uwsgi_log_verbose("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uebi->throttle_level = uebi->throttle_level / 2;
|
||||
}
|
||||
uebi->attempt++;
|
||||
if (uebi->attempt == 2) {
|
||||
uwsgi_log("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
uwsgi_log_verbose("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -339,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
struct stat st;
|
||||
struct uwsgi_instance *ui_current;
|
||||
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("glob()");
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -598,7 +603,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi_log("[emperor] %s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
|
||||
}
|
||||
|
||||
uwsgi_log("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
// put the instance in the blacklist (or update its throttling value)
|
||||
if (!c_ui->loyal) {
|
||||
uwsgi_emperor_blacklist_add(c_ui->name);
|
||||
@@ -617,6 +622,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// remove uWSGI instance
|
||||
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
@@ -624,10 +630,23 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_curse(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// curse uWSGI instance
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log_verbose("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
@@ -656,8 +675,12 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
c_ui->last_run = uwsgi_now();
|
||||
// reset readyness
|
||||
c_ui->ready = 0;
|
||||
// reset accepting
|
||||
c_ui->accepting = 0;
|
||||
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
|
||||
@@ -678,12 +701,12 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
int now = tv.tv_sec;
|
||||
uint64_t micros = (tv.tv_sec * 1000 * 1000) + tv.tv_usec;
|
||||
uint64_t micros = (tv.tv_sec * 1000ULL * 1000ULL) + tv.tv_usec;
|
||||
|
||||
// blacklist check
|
||||
struct uwsgi_emperor_blacklist_item *uebi = uwsgi_emperor_blacklist_check(name);
|
||||
if (uebi) {
|
||||
uint64_t i_micros = (uebi->last_attempt.tv_sec * 1000 * 1000) + uebi->last_attempt.tv_usec + uebi->throttle_level;
|
||||
uint64_t i_micros = (uebi->last_attempt.tv_sec * 1000ULL * 1000ULL) + uebi->last_attempt.tv_usec + uebi->throttle_level;
|
||||
if (i_micros > micros) {
|
||||
return;
|
||||
}
|
||||
@@ -744,6 +767,9 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->uid = uid;
|
||||
n_ui->gid = gid;
|
||||
n_ui->last_mod = born;
|
||||
// start non-ready
|
||||
n_ui->last_ready = 0;
|
||||
n_ui->ready = 0;
|
||||
// start without loyalty
|
||||
n_ui->last_loyal = 0;
|
||||
n_ui->loyal = 0;
|
||||
@@ -817,7 +843,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
// TODO pre-start hook
|
||||
|
||||
// a new uWSGI instance will start
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
|
||||
if (uwsgi.emperor_clone) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
|
||||
@@ -825,7 +851,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
else {
|
||||
#endif
|
||||
pid = fork();
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
|
||||
}
|
||||
#endif
|
||||
if (pid < 0) {
|
||||
@@ -940,6 +966,61 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#ifdef CLONE_NEWUSER
|
||||
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
|
||||
if (setuid(0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
|
||||
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
|
||||
int i;
|
||||
for(i=0;i<=CAP_LAST_CAP;i++) {
|
||||
|
||||
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
|
||||
if (has_cap == 1) {
|
||||
if (i == CAP_SETPCAP) continue;
|
||||
int j;int found = 0;
|
||||
for(j=0;j<uwsgi.emperor_cap_count;j++) {
|
||||
if (uwsgi.emperor_cap[j] == (int) i) {
|
||||
found = 1; break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
|
||||
uwsgi_log_verbose("unable to drop capability %lu\n", i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// just for being paranoid
|
||||
#ifdef SECBIT_KEEP_CAPS
|
||||
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
|
||||
if (setgid(n_ui->gid)) {
|
||||
@@ -1025,24 +1106,39 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
int counter = 4;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
struct uwsgi_string_list *uct;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
|
||||
|
||||
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
|
||||
|
||||
char *colon = NULL;
|
||||
// reset counter
|
||||
counter = 1;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_set) {
|
||||
vassal_argv[counter] = "--set";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
char *colon = NULL;
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
@@ -1050,62 +1146,58 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
vassal_argv[counter] = "--inherit";
|
||||
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
vassal_argv[counter] = "--xml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
vassal_argv[counter] = "--ini";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
vassal_argv[counter] = "--json";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
vassal_argv[counter] = "--json";
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
vassal_argv[counter] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
// start config filename...
|
||||
counter++;
|
||||
|
||||
|
||||
vassal_argv[2] = n_ui->name;
|
||||
vassal_argv[counter] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
// start templates,includes,inherit...
|
||||
counter++;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv[counter] = NULL;
|
||||
@@ -1121,18 +1213,7 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
@@ -1471,13 +1552,14 @@ void emperor_loop() {
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
|
||||
emperor_curse(ui_current);
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
ui_current->loyal = 1;
|
||||
ui_current->last_loyal = uwsgi_now();
|
||||
uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
// remove it from the blacklist
|
||||
uwsgi_emperor_blacklist_remove(ui_current->name);
|
||||
// TODO post-start hook
|
||||
@@ -1490,12 +1572,22 @@ void emperor_loop() {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
// here we discard socket name as broodlord/zerg cannot be on demand
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
|
||||
free(zerg_name);
|
||||
}
|
||||
else if (byte == 5) {
|
||||
ui_current->accepting = 1;
|
||||
ui_current->last_accepting = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s is ready to accept requests\n", ui_current->name);
|
||||
}
|
||||
else if (byte == 1) {
|
||||
ui_current->ready = 1;
|
||||
ui_current->last_ready = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1577,14 +1669,8 @@ void emperor_loop() {
|
||||
ui_current = ui;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->status == 1) {
|
||||
if (ui_current->config)
|
||||
free(ui_current->config);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (ui_current->pid == diedpid) {
|
||||
time_t now = uwsgi_now();
|
||||
if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
|
||||
@@ -1607,6 +1693,13 @@ void emperor_loop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
|
||||
ui_current->cursed_at = now;
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1653,7 +1746,8 @@ void emperor_send_stats(int fd) {
|
||||
goto end0;
|
||||
struct uwsgi_emperor_scanner *ues = emperor_scanners;
|
||||
while (ues) {
|
||||
uwsgi_stats_str(us, ues->arg);
|
||||
if (uwsgi_stats_str(us, ues->arg))
|
||||
goto end0;
|
||||
ues = ues->next;
|
||||
if (ues) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
@@ -1697,12 +1791,22 @@ void emperor_send_stats(int fd) {
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "loyal", (unsigned long long) c_ui->loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "ready", (unsigned long long) c_ui->ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) c_ui->accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_loyal", (unsigned long long) c_ui->last_loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_ready", (unsigned long long) c_ui->last_ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_accepting", (unsigned long long) c_ui->last_accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "first_run", (unsigned long long) c_ui->first_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
@@ -1786,7 +1890,7 @@ void emperor_send_stats(int fd) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
@@ -1846,6 +1950,46 @@ void uwsgi_emperor_start() {
|
||||
}
|
||||
|
||||
void uwsgi_check_emperor() {
|
||||
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
|
||||
if (emperor_fd_pass) {
|
||||
for(;;) {
|
||||
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
|
||||
if (proxy_fd < 0) {
|
||||
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
int count = 2;
|
||||
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
|
||||
if (fds && count > 0) {
|
||||
char *env_emperor_fd = uwsgi_num2str(fds[0]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
|
||||
free(env_emperor_fd);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd);
|
||||
if (count > 1) {
|
||||
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
|
||||
free(env_emperor_fd_config);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd_config);
|
||||
}
|
||||
break;
|
||||
}
|
||||
next:
|
||||
if (fds) free(fds);
|
||||
close(proxy_fd);
|
||||
sleep(1);
|
||||
}
|
||||
unsetenv("UWSGI_EMPEROR_PROXY");
|
||||
}
|
||||
|
||||
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
|
||||
if (emperor_env) {
|
||||
uwsgi.has_emperor = 1;
|
||||
@@ -1901,3 +2045,105 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
uwsgi_hooks_run(uwsgi.hook_emperor_stop, "emperor-stop", 0);
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
uwsgi_hooks_run(uwsgi.hook_emperor_reload, "emperor-reload", 0);
|
||||
// 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");
|
||||
uwsgi_hooks_run(uwsgi.hook_emperor_lost, "emperor-lost", 0);
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor_proxy() {
|
||||
|
||||
struct sockaddr_un epsun;
|
||||
socklen_t epsun_len = sizeof(struct sockaddr_un);
|
||||
|
||||
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
|
||||
if (ep_client < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
int num_fds = 1;
|
||||
if (uwsgi.emperor_fd_config > -1) num_fds++;
|
||||
|
||||
struct msghdr ep_msg;
|
||||
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
|
||||
struct iovec ep_iov[2];
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ep_iov[0].iov_base = "uwsgi-emperor";
|
||||
ep_iov[0].iov_len = 13;
|
||||
ep_iov[1].iov_base = &num_fds;
|
||||
ep_iov[1].iov_len = sizeof(int);
|
||||
|
||||
ep_msg.msg_name = NULL;
|
||||
ep_msg.msg_namelen = 0;
|
||||
|
||||
ep_msg.msg_iov = ep_iov;
|
||||
ep_msg.msg_iovlen = 2;
|
||||
|
||||
ep_msg.msg_flags = 0;
|
||||
ep_msg.msg_control = ep_msg_control;
|
||||
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&ep_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
|
||||
|
||||
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
|
||||
if (num_fds > 1) {
|
||||
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
|
||||
}
|
||||
|
||||
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
|
||||
}
|
||||
|
||||
free(ep_msg_control);
|
||||
|
||||
close(ep_client);
|
||||
}
|
||||
|
||||
static void emperor_notify_ready() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
char byte = 1;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("emperor_notify_ready()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_setup_emperor() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
uwsgi.notify_ready = emperor_notify_ready;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
struct stat st;
|
||||
if (!stat(usl->value, &st)) {
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// generate internal server error message
|
||||
void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
|
||||
}
|
||||
|
||||
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
|
||||
}
|
||||
@@ -18,6 +40,7 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
@@ -1231,6 +1231,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#elif defined(__arm__)
|
||||
return syscall(350, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
@@ -1241,6 +1243,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__arm__)
|
||||
return syscall(353, __ufd, __flags, __utmr, __otmr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
+25
-11
@@ -24,16 +24,29 @@ static char *uwsgi_fifo_by_slot() {
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
|
||||
#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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -71,6 +84,7 @@ void uwsgi_master_fifo_prepare() {
|
||||
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;
|
||||
|
||||
@@ -99,7 +113,7 @@ int uwsgi_master_fifo() {
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
char cmd;
|
||||
unsigned char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
|
||||
@@ -38,6 +38,7 @@ void uwsgi_fsmon_setup() {
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
free(copy);
|
||||
goto next;
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
@@ -29,6 +29,8 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
ug->num = num;
|
||||
ug->fullname = fullname;
|
||||
ug->data = data;
|
||||
ug->uid = 0;
|
||||
ug->gid = 0;
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
||||
@@ -70,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__
|
||||
@@ -89,6 +92,22 @@ void gateway_respawn(int id) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+305
-3
@@ -55,6 +55,22 @@ static int uwsgi_hook_chdir(char *arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_mkdir(char *arg) {
|
||||
int ret = mkdir(arg, 0777);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_mkdir()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_putenv(char *arg) {
|
||||
int ret = putenv(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_putenv()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
@@ -78,6 +94,263 @@ static int uwsgi_hook_print(char *arg) {
|
||||
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_append(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook append syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_append()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_writen(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook writen syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
memcpy(buf, space+1, l);
|
||||
buf[l] = '\n';
|
||||
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
|
||||
uwsgi_error("uwsgi_hook_writen()/write()");
|
||||
free(buf);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
free(buf);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_appendn(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
memcpy(buf, space+1, l);
|
||||
buf[l] = '\n';
|
||||
if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
|
||||
uwsgi_error("uwsgi_hook_appendn()/write()");
|
||||
free(buf);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
free(buf);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int uwsgi_hook_chmod(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook chmod syntax, must be: <file> <mode>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int error = 0;
|
||||
mode_t mask = uwsgi_mode_t(space+1, &error);
|
||||
if (error) {
|
||||
uwsgi_log("invalid hook chmod mask: %s\n", space+1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = chmod(arg, mask);
|
||||
*space = ' ';
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chmod()/chmod()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_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;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
@@ -175,8 +448,23 @@ static int uwsgi_hook_callret(char *arg) {
|
||||
|
||||
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("exec", uwsgi_hook_exec);
|
||||
|
||||
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);
|
||||
|
||||
@@ -186,6 +474,8 @@ void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
uwsgi_register_hook("hostname", uwsgi_hook_hostname);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
@@ -200,14 +490,26 @@ void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
|
||||
int private = 0;
|
||||
char *action = usl->value;
|
||||
// private hook ?
|
||||
if (action[0] == '!') {
|
||||
action++;
|
||||
private = 1;
|
||||
}
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(action);
|
||||
if (!uh) {
|
||||
uwsgi_log("hook not found: %s\n", usl->value);
|
||||
uwsgi_log("hook action not found: %s\n", action);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
if (private) {
|
||||
uwsgi_log("running --- PRIVATE HOOK --- (%s)...\n", phase);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
}
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
|
||||
+14
-15
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{"509", "Bandwidth Limit Exceeded"},
|
||||
{"", NULL},
|
||||
};
|
||||
|
||||
@@ -75,10 +76,12 @@ void uwsgi_init_default() {
|
||||
uwsgi.original_log_fd = -1;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
// default emperor scan frequency
|
||||
uwsgi.emperor_freq = 3;
|
||||
uwsgi.emperor_throttle = 1000;
|
||||
uwsgi.emperor_heartbeat = 30;
|
||||
uwsgi.emperor_curse_tolerance = 30;
|
||||
// max 3 minutes throttling
|
||||
uwsgi.emperor_max_throttle = 1000 * 180;
|
||||
uwsgi.emperor_pid = -1;
|
||||
@@ -114,11 +117,11 @@ void uwsgi_init_default() {
|
||||
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;
|
||||
|
||||
@@ -167,6 +170,8 @@ void uwsgi_init_default() {
|
||||
|
||||
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();
|
||||
|
||||
@@ -191,7 +196,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()");
|
||||
@@ -343,7 +348,6 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.workers[i].signal_pipe[0] = -1;
|
||||
uwsgi.workers[i].signal_pipe[1] = -1;
|
||||
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
|
||||
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
|
||||
}
|
||||
|
||||
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
|
||||
@@ -409,7 +413,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");
|
||||
}
|
||||
@@ -445,18 +449,13 @@ 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.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.logging_options.memory_report != 1 && uwsgi.force_get_memusage != 1) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -464,7 +463,7 @@ void sanitize_args() {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ int uwsgi_waitfd_event(int fd, int timeout, int event) {
|
||||
struct pollfd upoll;
|
||||
|
||||
if (!timeout)
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
timeout = uwsgi.socket_timeout;
|
||||
|
||||
timeout = timeout * 1000;
|
||||
if (timeout < 0)
|
||||
@@ -116,48 +116,31 @@ end:
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
extremely complex function for reading resources (files, url...)
|
||||
need a lot of refactoring...
|
||||
*/
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
|
||||
int fd = atoi(url);
|
||||
return uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
|
||||
int fd;
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url, NULL, cpipe[1]);
|
||||
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
|
||||
char byte;
|
||||
ssize_t len;
|
||||
char *uri, *colon;
|
||||
char *domain;
|
||||
char *ip;
|
||||
int body = 0;
|
||||
char *magic_buf;
|
||||
int body = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
}
|
||||
// fd ?
|
||||
else if (!strncmp("fd://", url, 5)) {
|
||||
fd = atoi(url + 5);
|
||||
buffer = uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
// exec ?
|
||||
else if (!strncmp("exec://", url, 5)) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url + 7, NULL, cpipe[1]);
|
||||
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
}
|
||||
// http url ?
|
||||
else if (!strncmp("http://", url, 7)) {
|
||||
domain = url + 7;
|
||||
uri = strchr(domain, '/');
|
||||
char *domain = url;
|
||||
char *uri = strchr(domain, '/');
|
||||
if (!uri) {
|
||||
uwsgi_log("invalid http url\n");
|
||||
exit(1);
|
||||
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
uri[0] = 0;
|
||||
uwsgi_log("domain: %s\n", domain);
|
||||
|
||||
colon = uwsgi_get_last_char(domain, ':');
|
||||
char *colon = uwsgi_get_last_char(domain, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
ip = uwsgi_resolve_ip(domain);
|
||||
char *ip = uwsgi_resolve_ip(domain);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve address %s\n", domain);
|
||||
exit(1);
|
||||
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
ip = uwsgi_concat2(ip, ":80");
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(ip, 0, 0);
|
||||
int fd = uwsgi_connect(ip, 0, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_scheme_http()/connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "GET ", 4);
|
||||
len = write(fd, uri, strlen(uri));
|
||||
len = write(fd, " HTTP/1.0\r\n", 11);
|
||||
len = write(fd, "Host: ", 6);
|
||||
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
uri[0] = 0;
|
||||
len = write(fd, domain, strlen(domain));
|
||||
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
|
||||
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
|
||||
len = write(fd, "\r\n\r\n", 4);
|
||||
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
int http_status_code_ptr = 0;
|
||||
|
||||
@@ -264,57 +248,233 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer[*size - 1] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
|
||||
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (!strncmp("emperor://", url, 10)) {
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
ssize_t rlen;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ssize_t rlen;
|
||||
*size = 0;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
|
||||
char *buffer = NULL;
|
||||
int fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -8, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
|
||||
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *s = func();
|
||||
if (!s) {
|
||||
uwsgi_log("called symbol %s did not return a string\n", url);
|
||||
exit(1);
|
||||
}
|
||||
*size = strlen(s);
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, s, strlen(s));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
|
||||
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
|
||||
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
|
||||
if (raw_symbol) {
|
||||
sym_start_ptr = *raw_symbol;
|
||||
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
|
||||
goto found;
|
||||
}
|
||||
char *symbol = uwsgi_concat3("_binary_", url, "_start");
|
||||
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url, "_end");
|
||||
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
|
||||
found:
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
|
||||
#ifdef UWSGI_ELF
|
||||
size_t s_len = 0;
|
||||
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
return buffer;
|
||||
#else
|
||||
uwsgi_log("section:// scheme not supported on this platform\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
if (!strcmp(usl->value, name)) goto found;
|
||||
}
|
||||
|
||||
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
|
||||
|
||||
found:
|
||||
usl->custom_ptr = func;
|
||||
return usl;
|
||||
}
|
||||
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
ssize_t len;
|
||||
char *magic_buf;
|
||||
int fd;
|
||||
|
||||
*size = 0;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
goto end;
|
||||
}
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
else if (url[0] == 0) {
|
||||
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
|
||||
@@ -324,108 +484,22 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
else if (!strncmp("data://", url, 7)) {
|
||||
fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url + 7);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -9, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp("sym://", url, 6)) {
|
||||
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
|
||||
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
|
||||
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
|
||||
if (!usl) goto fallback;
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
}
|
||||
#ifdef UWSGI_ELF
|
||||
else if (!strncmp("section://", url, 10)) {
|
||||
size_t s_len = 0;
|
||||
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
}
|
||||
#endif
|
||||
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
|
||||
buffer = func(url + usl->len + 3, size, add_zero);
|
||||
if (buffer) goto end;
|
||||
// never here !!!
|
||||
uwsgi_log("unable to parse config file %s\n", url);
|
||||
exit(1);
|
||||
|
||||
// fallback to file
|
||||
else {
|
||||
fallback:
|
||||
fd = open(url, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(url);
|
||||
@@ -457,7 +531,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
if (add_zero)
|
||||
buffer[sb.st_size] = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@@ -513,11 +586,13 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
|
||||
len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recvmsg()");
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (code && code_len > 0) {
|
||||
if (uwsgi_strncmp(id, code_len, code, code_len)) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -533,15 +608,19 @@ int *uwsgi_attach_fd(int fd, int *count_ptr, char *code, size_t code_len) {
|
||||
}
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg)
|
||||
if (!cmsg) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((size_t) (cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) > (size_t) (sizeof(int) * (count + 1))) {
|
||||
uwsgi_log("not enough space for sockets data, consider increasing it\n");
|
||||
free(msg_control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -683,11 +762,12 @@ int uwsgi_write_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
int ret;
|
||||
|
||||
while(remains > 0) {
|
||||
errno = 0;
|
||||
ssize_t len = write(fd, ptr, remains);
|
||||
if (len > 0) goto written;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -838,7 +918,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
|
||||
}
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
}
|
||||
return -1;
|
||||
wait:
|
||||
@@ -870,12 +950,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
}
|
||||
|
||||
/*
|
||||
this is a pretty magic function used for read a full uwsgi response
|
||||
this is a pretty magic function used for reading a full uwsgi response
|
||||
it is true non blocking, so you can use it in request plugins
|
||||
buffer is expected to be at least 4 bytes, rlen is a get/set value
|
||||
*/
|
||||
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
|
||||
if (*rlen < 4) return -1;
|
||||
char *buf = *buffer;
|
||||
int ret;
|
||||
@@ -888,7 +968,7 @@ int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
|
||||
if (len > 0) goto readok;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -906,6 +986,10 @@ readok:
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (modifier1)
|
||||
*modifier1 = uh->modifier1;
|
||||
if (modifier2)
|
||||
*modifier2 = uh->modifier2;
|
||||
|
||||
if (pktsize > *rlen) {
|
||||
char *tmp_buf = realloc(buf, pktsize);
|
||||
@@ -926,7 +1010,7 @@ readok:
|
||||
if (len > 0) goto readok2;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
|
||||
if (uwsgi_is_again()) goto wait2;
|
||||
return -1;
|
||||
}
|
||||
wait2:
|
||||
@@ -1097,3 +1181,245 @@ int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_setup_schemes() {
|
||||
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
|
||||
uwsgi_register_scheme("http", uwsgi_scheme_http);
|
||||
uwsgi_register_scheme("data", uwsgi_scheme_data);
|
||||
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
|
||||
uwsgi_register_scheme("section", uwsgi_scheme_section);
|
||||
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
|
||||
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
|
||||
uwsgi_register_scheme("call", uwsgi_scheme_call);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
char *url = uwsgi_concat2(usl->value, "://");
|
||||
int ret = uwsgi_startswith(file, url, strlen(url));
|
||||
free(url);
|
||||
if (!ret) return usl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_remap_fd(int fd, char *filename) {
|
||||
|
||||
int fdin = open(filename, O_RDWR);
|
||||
if (fdin < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (fdin != fd) {
|
||||
if (dup2(fdin, fd) < 0) {
|
||||
uwsgi_error("uwsgi_remap_fd()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fdin);
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_is_connected(int fd) {
|
||||
int soopt;
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
return 0;
|
||||
}
|
||||
/* is something bad ? */
|
||||
if (soopt) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_pass_cred(int fd, char *code, size_t code_len) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct msghdr cr_msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec cr_iov;
|
||||
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
cr_iov.iov_base = code;
|
||||
cr_iov.iov_len = code_len;
|
||||
|
||||
cr_msg.msg_name = NULL;
|
||||
cr_msg.msg_namelen = 0;
|
||||
|
||||
cr_msg.msg_iov = &cr_iov;
|
||||
cr_msg.msg_iovlen = 1;
|
||||
|
||||
cr_msg.msg_flags = 0;
|
||||
cr_msg.msg_control = cr_msg_control;
|
||||
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&cr_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_CREDENTIALS;
|
||||
|
||||
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
|
||||
u->pid = getpid();
|
||||
u->uid = getuid();
|
||||
u->gid = getgid();
|
||||
|
||||
if (sendmsg(fd, &cr_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_pass_cred()/sendmsg()");
|
||||
free(cr_msg_control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cr_msg_control);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_pass_cred2(int fd, char *code, size_t code_len, struct sockaddr *addr, size_t addr_len) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct msghdr cr_msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec cr_iov;
|
||||
void *cr_msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
cr_iov.iov_base = code;
|
||||
cr_iov.iov_len = code_len;
|
||||
|
||||
cr_msg.msg_name = addr;
|
||||
cr_msg.msg_namelen = addr_len;
|
||||
|
||||
cr_msg.msg_iov = &cr_iov;
|
||||
cr_msg.msg_iovlen = 1;
|
||||
|
||||
cr_msg.msg_flags = 0;
|
||||
cr_msg.msg_control = cr_msg_control;
|
||||
cr_msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&cr_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_CREDENTIALS;
|
||||
|
||||
struct ucred *u = (struct ucred*) CMSG_DATA(cmsg);
|
||||
u->pid = getpid();
|
||||
u->uid = getuid();
|
||||
u->gid = getgid();
|
||||
|
||||
if (sendmsg(fd, &cr_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_pass_cred2()/sendmsg()");
|
||||
free(cr_msg_control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cr_msg_control);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_recv_cred(int fd, char *code, size_t code_len, pid_t *pid, uid_t *uid, gid_t *gid) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct iovec iov;
|
||||
int ret = -1;
|
||||
|
||||
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
iov.iov_base = uwsgi_malloc(code_len);
|
||||
iov.iov_len = code_len;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
ssize_t len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("uwsgi_recv_cred()/recvmsg()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg) goto clear;
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(code, code_len, iov.iov_base, iov.iov_len)) goto clear;
|
||||
|
||||
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
|
||||
*pid = u->pid;
|
||||
*uid = u->uid;
|
||||
*gid = u->gid;
|
||||
ret = 0;
|
||||
|
||||
clear:
|
||||
free(msg_control);
|
||||
free(iov.iov_base);
|
||||
return ret;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t uwsgi_recv_cred2(int fd, char *buf, size_t buf_len, pid_t *pid, uid_t *uid, gid_t *gid) {
|
||||
#ifdef SCM_CREDENTIALS
|
||||
struct iovec iov;
|
||||
ssize_t ret = -1;
|
||||
|
||||
void *msg_control = uwsgi_calloc(CMSG_SPACE(sizeof(struct ucred)));
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = buf_len;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
|
||||
ssize_t len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("uwsgi_recv_cred2()/recvmsg()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg) goto clear;
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
struct ucred *u = (struct ucred *) CMSG_DATA(cmsg);
|
||||
*pid = u->pid;
|
||||
*uid = u->uid;
|
||||
*gid = u->gid;
|
||||
ret = len;
|
||||
|
||||
clear:
|
||||
free(msg_control);
|
||||
return ret;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+84
-4
@@ -4,13 +4,90 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef 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 +183,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
|
||||
|
||||
+4
-1
@@ -737,6 +737,7 @@ void uwsgi_legion_add(struct uwsgi_legion *ul) {
|
||||
|
||||
int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
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;
|
||||
@@ -769,7 +770,7 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
|
||||
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
|
||||
uwsgi_error("[uwsgi-legion] EVP_EncryptInit_ex()");
|
||||
goto err;
|
||||
@@ -808,6 +809,7 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
return 0;
|
||||
err:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
free(encrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -824,6 +826,7 @@ void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
free(legion);
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -647,6 +647,7 @@ 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;
|
||||
}
|
||||
|
||||
+195
-225
@@ -119,6 +119,36 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
commodity function mainly useful in log rotation
|
||||
*/
|
||||
void uwsgi_logfile_write(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char logpkt[4096];
|
||||
|
||||
struct timeval tv;
|
||||
char ctime_storage[26];
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
#if defined(__sun__) && !defined(__clang__)
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
|
||||
#endif
|
||||
memcpy(logpkt, ctime_storage, 24);
|
||||
memcpy(logpkt + 24, " - ", 3);
|
||||
|
||||
int rlen = 24 + 3;
|
||||
|
||||
va_start(ap, fmt);
|
||||
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
// do not check for errors
|
||||
rlen = write(uwsgi.original_log_fd, logpkt, rlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fix_logpipe_buf(int *fd) {
|
||||
int so_bufsize;
|
||||
@@ -211,49 +241,6 @@ void create_logpipe(void) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
// the zeromq logger
|
||||
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!ul->arg) {
|
||||
uwsgi_log_safe("invalid zeromq syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *ctx = uwsgi_zeromq_init();
|
||||
|
||||
ul->data = zmq_socket(ctx, ZMQ_PUSH);
|
||||
if (ul->data == NULL) {
|
||||
uwsgi_error_safe("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(ul->data, ul->arg) < 0) {
|
||||
uwsgi_error_safe("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
zmq_msg_t msg;
|
||||
if (zmq_msg_init_size(&msg, len) == 0) {
|
||||
memcpy(zmq_msg_data(&msg), message, len);
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_sendmsg(ul->data, &msg, 0);
|
||||
#else
|
||||
zmq_send(ul->data, &msg, 0);
|
||||
#endif
|
||||
zmq_msg_close(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// log to the specified file or udp address
|
||||
void logto(char *logfile) {
|
||||
|
||||
@@ -498,7 +485,7 @@ void uwsgi_check_logrotate(void) {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
@@ -519,7 +506,6 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
@@ -529,24 +515,21 @@ void uwsgi_log_rotate() {
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
@@ -562,7 +545,7 @@ void uwsgi_log_reopen() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (ret > 0 && ret < 1024) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
@@ -575,9 +558,10 @@ void uwsgi_log_reopen() {
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
return;
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (ret > 0 && ret < 1024) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
@@ -589,7 +573,7 @@ void uwsgi_log_reopen() {
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int log_it = uwsgi.shared->options[UWSGI_OPTION_LOGGING];
|
||||
int log_it = uwsgi.logging_options.enabled;
|
||||
|
||||
if (wsgi_req->do_not_log)
|
||||
return;
|
||||
@@ -599,22 +583,25 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
/* conditional logging */
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_ZERO] && wsgi_req->response_size == 0) {
|
||||
if (uwsgi.logging_options.zero && wsgi_req->response_size == 0) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW] && (uint32_t) wsgi_req_time >= uwsgi.shared->options[UWSGI_OPTION_LOG_SLOW]) {
|
||||
if (uwsgi.logging_options.slow && (uint32_t) wsgi_req_time >= uwsgi.logging_options.slow) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_4xx] && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
|
||||
if (uwsgi.logging_options._4xx && (wsgi_req->status >= 400 && wsgi_req->status <= 499)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_5xx] && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
|
||||
if (uwsgi.logging_options._5xx && (wsgi_req->status >= 500 && wsgi_req->status <= 599)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG] && (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG])) {
|
||||
if (uwsgi.logging_options.big && (wsgi_req->response_size >= uwsgi.logging_options.big)) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
if (uwsgi.logging_options.sendfile && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.logging_options.ioerror && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
|
||||
goto logit;
|
||||
}
|
||||
|
||||
@@ -699,7 +686,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
logvecpos++;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
if (uwsgi.logging_options.memory_report == 1) {
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
@@ -980,6 +967,20 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
|
||||
}
|
||||
}
|
||||
// var
|
||||
else if (logchunk->type == 5) {
|
||||
uint16_t value_len = 0;
|
||||
char *value = uwsgi_get_var(wsgi_req, logchunk->ptr, logchunk->len, &value_len);
|
||||
// could be NULL
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = value;
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = (size_t) value_len;
|
||||
}
|
||||
// metric
|
||||
else if (logchunk->type == 4) {
|
||||
int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
|
||||
}
|
||||
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
|
||||
@@ -1005,10 +1006,6 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_logit_lf_strftime(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("lf strftime\n");
|
||||
}
|
||||
|
||||
void uwsgi_build_log_format(char *format) {
|
||||
int state = 0;
|
||||
char *ptr = format;
|
||||
@@ -1132,6 +1129,16 @@ static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_tmsecs(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_64bit2str(wsgi_req->start_of_request / (int64_t) 1000);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_tmicros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_64bit2str(wsgi_req->start_of_request);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
return strlen(*buf);
|
||||
@@ -1207,6 +1214,54 @@ static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_werr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) wsgi_req->write_errors);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_rerr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) wsgi_req->read_errors);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_ioerr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) (wsgi_req->write_errors + wsgi_req->read_errors));
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
struct uwsgi_logchunk *uwsgi_register_logchunk(char *name, ssize_t (*func)(struct wsgi_request *, char **), int need_free) {
|
||||
struct uwsgi_logchunk *old_logchunk = NULL, *logchunk = uwsgi.registered_logchunks;
|
||||
while(logchunk) {
|
||||
if (!strcmp(logchunk->name, name)) goto found;
|
||||
old_logchunk = logchunk;
|
||||
logchunk = logchunk->next;
|
||||
}
|
||||
logchunk = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
|
||||
logchunk->name = name;
|
||||
if (old_logchunk) {
|
||||
old_logchunk->next = logchunk;
|
||||
}
|
||||
else {
|
||||
uwsgi.registered_logchunks = logchunk;
|
||||
}
|
||||
found:
|
||||
logchunk->func = func;
|
||||
logchunk->free = need_free;
|
||||
logchunk->type = 3;
|
||||
return logchunk;
|
||||
}
|
||||
|
||||
struct uwsgi_logchunk *uwsgi_get_logchunk_by_name(char *name, size_t name_len) {
|
||||
struct uwsgi_logchunk *logchunk = uwsgi.registered_logchunks;
|
||||
while(logchunk) {
|
||||
if (!uwsgi_strncmp(name, name_len, logchunk->name, strlen(logchunk->name))) {
|
||||
return logchunk;
|
||||
}
|
||||
logchunk = logchunk->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
|
||||
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
|
||||
@@ -1227,10 +1282,12 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
}
|
||||
|
||||
/*
|
||||
0 -> raw test
|
||||
0 -> raw text
|
||||
1 -> offsetof variable
|
||||
2 -> logvar
|
||||
3 -> func
|
||||
4 -> metric
|
||||
5 -> request variable
|
||||
*/
|
||||
|
||||
logchunk->type = variable;
|
||||
@@ -1240,161 +1297,29 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->len = len;
|
||||
// variable
|
||||
if (variable) {
|
||||
if (!uwsgi_strncmp(ptr, len, "uri", 3)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, uri);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, uri_len);
|
||||
struct uwsgi_logchunk *rlc = uwsgi_get_logchunk_by_name(ptr, len);
|
||||
if (rlc) {
|
||||
if (rlc->type == 1) {
|
||||
logchunk->pos = rlc->pos;
|
||||
logchunk->pos_len = rlc->pos_len;
|
||||
}
|
||||
else if (rlc->type == 3) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = rlc->func;
|
||||
logchunk->free = rlc->free;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "method", 6)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, method);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, method_len);
|
||||
// var
|
||||
else if (!uwsgi_starts_with(ptr, len, "var.", 4)) {
|
||||
logchunk->type = 5;
|
||||
logchunk->ptr = ptr+4;
|
||||
logchunk->len = len-4;
|
||||
logchunk->free = 0;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "user", 4)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, remote_user);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, remote_user_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "addr", 4)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, remote_addr);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, remote_addr_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "host", 4)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, host);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, host_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "proto", 5)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, protocol);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, user_agent);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, referer);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_status;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_hsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_size;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_cl;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_micros;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "msecs", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_msecs;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "time", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_time;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ltime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ftime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ctime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "epoch", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_epoch;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "pid", 3)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_pid;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "wid", 3)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_wid;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "switches", 8)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_switches;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "vars", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_vars;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "core", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_core;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "vsz", 3)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_vsz;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rss", 3)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rss;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "vszM", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_vszM;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rssM", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rssM;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "pktsize", 7)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_pktsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "modifier1", 9)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_modifier1;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "modifier2", 9)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_modifier2;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "headers", 7)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_headers;
|
||||
// metric
|
||||
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
|
||||
logchunk->type = 4;
|
||||
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
|
||||
logchunk->free = 1;
|
||||
}
|
||||
// logvar
|
||||
@@ -1841,7 +1766,7 @@ void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
|
||||
/*
|
||||
// format: foo ${var} bar
|
||||
msg (the logline)
|
||||
msgnl (the logine with newline)
|
||||
msgnl (the logline with newline)
|
||||
unix (the time_t value)
|
||||
micros (current microseconds)
|
||||
strftime (strftime)
|
||||
@@ -1967,6 +1892,51 @@ end:
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define r_logchunk(x) uwsgi_register_logchunk(#x, uwsgi_lf_ ## x, 1)
|
||||
#define r_logchunk_offset(x, y) { struct uwsgi_logchunk *lc = uwsgi_register_logchunk(#x, NULL, 0); lc->pos = offsetof(struct wsgi_request, y); lc->pos_len = offsetof(struct wsgi_request, y ## _len); lc->type = 1; lc->free=0;}
|
||||
void uwsgi_register_logchunks() {
|
||||
// offsets
|
||||
r_logchunk_offset(uri, uri);
|
||||
r_logchunk_offset(method, method);
|
||||
r_logchunk_offset(user, remote_user);
|
||||
r_logchunk_offset(addr, remote_addr);
|
||||
r_logchunk_offset(host, host);
|
||||
r_logchunk_offset(proto, protocol);
|
||||
r_logchunk_offset(uagent, user_agent);
|
||||
r_logchunk_offset(referer, referer);
|
||||
|
||||
// funcs
|
||||
r_logchunk(status);
|
||||
r_logchunk(rsize);
|
||||
r_logchunk(hsize);
|
||||
r_logchunk(size);
|
||||
r_logchunk(cl);
|
||||
r_logchunk(micros);
|
||||
r_logchunk(msecs);
|
||||
r_logchunk(tmsecs);
|
||||
r_logchunk(tmicros);
|
||||
r_logchunk(time);
|
||||
r_logchunk(ltime);
|
||||
r_logchunk(ftime);
|
||||
r_logchunk(ctime);
|
||||
r_logchunk(epoch);
|
||||
r_logchunk(pid);
|
||||
r_logchunk(wid);
|
||||
r_logchunk(switches);
|
||||
r_logchunk(vars);
|
||||
r_logchunk(core);
|
||||
r_logchunk(vsz);
|
||||
r_logchunk(rss);
|
||||
r_logchunk(vszM);
|
||||
r_logchunk(rssM);
|
||||
r_logchunk(pktsize);
|
||||
r_logchunk(modifier1);
|
||||
r_logchunk(modifier2);
|
||||
r_logchunk(headers);
|
||||
r_logchunk(werr);
|
||||
r_logchunk(rerr);
|
||||
r_logchunk(ioerr);
|
||||
}
|
||||
|
||||
void uwsgi_log_encoders_register_embedded() {
|
||||
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
|
||||
|
||||
+191
-171
@@ -2,15 +2,30 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_restore_auto_snapshot(int signum) {
|
||||
void uwsgi_update_load_counters() {
|
||||
|
||||
if (uwsgi.workers[1].snapshot > 0) {
|
||||
uwsgi.restore_snapshot = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[WARNING] no snapshot available\n");
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi_worker_is_busy(i) == 0) {
|
||||
idle_workers++;
|
||||
}
|
||||
else {
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
ushared->idle_workers = idle_workers;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_block_signal(int signum) {
|
||||
@@ -32,24 +47,25 @@ void uwsgi_unblock_signal(int signum) {
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_udp(int udp_fd) {
|
||||
char buf[4096];
|
||||
struct sockaddr_in udp_client;
|
||||
char udp_client_addr[16];
|
||||
int i;
|
||||
|
||||
socklen_t udp_len = sizeof(udp_client);
|
||||
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
|
||||
memset(udp_client_addr, 0, 16);
|
||||
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
|
||||
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
}
|
||||
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
else if (buf[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -57,7 +73,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
int udp_managed = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->manage_udp) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
|
||||
udp_managed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -66,74 +82,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
|
||||
// else a simple udp logger
|
||||
if (!udp_managed) {
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("inet_ntop()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_restore_snapshot() {
|
||||
int i, waitpid_status;
|
||||
uwsgi_log("[snapshot] restoring workers...\n");
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGURG);
|
||||
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.restore_snapshot = 0;
|
||||
}
|
||||
|
||||
void suspend_resume_them_all(int signum) {
|
||||
|
||||
int i;
|
||||
@@ -209,53 +168,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 +208,61 @@ 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);
|
||||
}
|
||||
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
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int master_loop(char **argv, char **environ) {
|
||||
|
||||
@@ -331,9 +307,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);
|
||||
|
||||
@@ -378,6 +351,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_start_legions();
|
||||
#endif
|
||||
uwsgi_metrics_start_collector();
|
||||
|
||||
uwsgi_add_reload_fds();
|
||||
|
||||
@@ -387,9 +361,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);
|
||||
@@ -503,10 +500,40 @@ int master_loop(char **argv, char **environ) {
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
// daemon touches
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->touch) {
|
||||
uwsgi_check_touches(ud->touch);
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (uwsgi.requested_cheaper_algo) {
|
||||
@@ -560,21 +587,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())
|
||||
@@ -603,9 +615,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
|
||||
@@ -640,14 +654,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,6 +675,9 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// update load counter
|
||||
uwsgi_update_load_counters();
|
||||
|
||||
|
||||
// check uwsgi-cron table
|
||||
if (ushared->cron_cnt) {
|
||||
@@ -700,41 +717,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;
|
||||
int tmp_queue = 0;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
|
||||
}
|
||||
#ifdef __linux__
|
||||
#ifdef SIOBKLGQ
|
||||
else if (uwsgi_sock->family == AF_UNIX) {
|
||||
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi_sock->queue > tmp_queue) {
|
||||
tmp_queue = uwsgi_sock->queue;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
uwsgi.master_interval = 1;
|
||||
}
|
||||
// fix queue size on multiple sockets
|
||||
uwsgi.shared->load = tmp_queue;
|
||||
|
||||
|
||||
// check listen_queue status
|
||||
master_check_listen_queue();
|
||||
|
||||
int someone_killed = 0;
|
||||
// check if some worker has to die (harakiri, evil checks...)
|
||||
uwsgi_master_check_workers_deadline();
|
||||
if (uwsgi_master_check_workers_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_gateways_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_mules_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_spoolers_deadline()) someone_killed++;
|
||||
if (uwsgi_master_check_crons_deadline()) someone_killed++;
|
||||
|
||||
uwsgi_master_check_gateways_deadline();
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
uwsgi_master_check_crons_deadline();
|
||||
// this could trigger a complete exit...
|
||||
uwsgi_master_check_mountpoints();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
@@ -797,8 +799,26 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
|
||||
// daemon touches
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && ud->touch) {
|
||||
touched = uwsgi_check_touches(ud->touch);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
|
||||
if (kill(ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// allows the KILL signal to be delivered;
|
||||
if (someone_killed > 0) sleep(1);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
+46
-9
@@ -48,6 +48,8 @@ void uwsgi_master_check_chain() {
|
||||
}
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
// do not curse a worker until the old one is ready
|
||||
if (uwsgi.workers[i].accepting == 0) break;
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
break;
|
||||
@@ -118,6 +120,11 @@ void uwsgi_master_check_idle() {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
@@ -126,19 +133,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
|
||||
@@ -147,6 +157,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) {
|
||||
@@ -154,15 +165,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,29 +184,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) {
|
||||
@@ -201,6 +217,7 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
// user harakiri
|
||||
@@ -209,26 +226,32 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].user_harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_spoolers_deadline() {
|
||||
int uwsgi_master_check_spoolers_deadline() {
|
||||
int ret = 0;
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->user_harakiri = 0;
|
||||
ret = 1;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -311,14 +334,28 @@ int uwsgi_master_check_cron_death(int diedpid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_crons_deadline() {
|
||||
int uwsgi_master_check_crons_deadline() {
|
||||
int ret = 0;
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
|
||||
kill(-uc->pid, SIGKILL);
|
||||
ret = 1;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mountpoints() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,23 @@ 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;
|
||||
}
|
||||
@@ -113,6 +124,7 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
if (usl->custom2 > 8) free(tmp);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
|
||||
+265
-20
@@ -101,7 +101,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
static time_t last_check = 0;
|
||||
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
int check_interval = uwsgi.master_interval;
|
||||
|
||||
if (!last_check)
|
||||
last_check = uwsgi_now();
|
||||
@@ -151,7 +151,13 @@ int uwsgi_calc_cheaper(void) {
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
}
|
||||
|
||||
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
|
||||
// if cheaper limits wants to change worker count, then skip cheaper algo
|
||||
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
|
||||
// safe check to verify if cheaper algo obeyed ignore_algo value
|
||||
if (ignore_algo && needed_workers > 0) {
|
||||
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
|
||||
needed_workers = 0;
|
||||
}
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
@@ -180,6 +186,8 @@ int uwsgi_calc_cheaper(void) {
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].rss_size = 0;
|
||||
uwsgi.workers[oldest_worker].vsz_size = 0;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
uwsgi_curse(oldest_worker, SIGWINCH);
|
||||
}
|
||||
@@ -189,7 +197,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
}
|
||||
|
||||
// fake algo to allow control with the fifo
|
||||
int uwsgi_cheaper_algo_manual(void) {
|
||||
int uwsgi_cheaper_algo_manual(int can_spawn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -228,7 +236,7 @@ int uwsgi_cheaper_algo_manual(void) {
|
||||
*/
|
||||
|
||||
|
||||
int uwsgi_cheaper_algo_spare(void) {
|
||||
int uwsgi_cheaper_algo_spare(int can_spawn) {
|
||||
|
||||
int i;
|
||||
static uint64_t overload_count = 0;
|
||||
@@ -252,7 +260,7 @@ int uwsgi_cheaper_algo_spare(void) {
|
||||
healthy:
|
||||
|
||||
// are we overloaded ?
|
||||
if (overload_count > uwsgi.cheaper_overload) {
|
||||
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("overloaded !!!\n");
|
||||
@@ -320,16 +328,16 @@ healthy:
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_cheaper_algo_backlog(void) {
|
||||
int uwsgi_cheaper_algo_backlog(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.shared->backlog;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int) uwsgi.cheaper_overload) {
|
||||
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
@@ -377,14 +385,14 @@ void uwsgi_reload(char **argv) {
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
}
|
||||
else {
|
||||
@@ -578,6 +586,19 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
|
||||
#ifdef __linux__
|
||||
for(i=0;i<uwsgi.setns_fds_count;i++) {
|
||||
close(uwsgi.setns_fds[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// fd alarms
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
close(uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -586,6 +607,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
// the workers is not accepting (obviously)
|
||||
uwsgi.workers[wid].accepting = 0;
|
||||
// we count the respawns before errors...
|
||||
uwsgi.workers[wid].respawn_count++;
|
||||
// ... same for update time
|
||||
@@ -705,9 +728,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]))
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->backlog))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]))
|
||||
if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->backlog_errors))
|
||||
goto end;
|
||||
#endif
|
||||
|
||||
@@ -865,6 +888,70 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
struct uwsgi_metric *um = uwsgi.metrics;
|
||||
while(um) {
|
||||
int64_t um_val = *um->value;
|
||||
|
||||
if (uwsgi_stats_key(us, um->name)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_open(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_close(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
um = um->next;
|
||||
if (um) {
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_key(us, "sockets"))
|
||||
goto end;
|
||||
|
||||
@@ -885,6 +972,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "max_queue", (unsigned long long) uwsgi_sock->max_queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
|
||||
goto end;
|
||||
|
||||
@@ -920,6 +1010,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
@@ -1006,7 +1098,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
|
||||
goto end;
|
||||
|
||||
if (ua->chdir) {
|
||||
if (*ua->chdir) {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
|
||||
goto end;
|
||||
}
|
||||
@@ -1059,6 +1151,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
@@ -1345,7 +1440,7 @@ end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
|
||||
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
|
||||
@@ -1376,7 +1471,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
|
||||
void trigger_harakiri(int i) {
|
||||
int j;
|
||||
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
|
||||
uwsgi_log_verbose("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
|
||||
if (uwsgi.harakiri_verbose) {
|
||||
#ifdef __linux__
|
||||
int proc_file;
|
||||
@@ -1424,15 +1519,12 @@ void trigger_harakiri(int i) {
|
||||
}
|
||||
}
|
||||
|
||||
kill(uwsgi.workers[i].pid, SIGUSR2);
|
||||
// allow SIGUSR2 to be delivered
|
||||
sleep(1);
|
||||
uwsgi_dump_worker(i, "HARAKIRI");
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (!uwsgi.workers[i].pending_harakiri)
|
||||
uwsgi.workers[i].harakiri_count++;
|
||||
uwsgi.workers[i].pending_harakiri++;
|
||||
}
|
||||
// to avoid races
|
||||
|
||||
}
|
||||
|
||||
@@ -1572,6 +1664,8 @@ void uwsgi_go_cheap() {
|
||||
uwsgi.status.is_cheap = 1;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
@@ -1584,3 +1678,154 @@ void uwsgi_go_cheap() {
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
void uwsgi_setns_preopen() {
|
||||
struct dirent *de;
|
||||
DIR *ns = opendir("/proc/self/ns");
|
||||
if (!ns) {
|
||||
uwsgi_error("uwsgi_setns_preopen()/opendir()");
|
||||
exit(1);
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
if (!strcmp(de->d_name, usl->value)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
|
||||
uwsgi.setns_fds[uwsgi.setns_fds_count] = open(filename, O_RDONLY);
|
||||
if (uwsgi.setns_fds[uwsgi.setns_fds_count] < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
exit(1);
|
||||
}
|
||||
free(filename);
|
||||
uwsgi.setns_fds_count++;
|
||||
}
|
||||
closedir(ns);
|
||||
}
|
||||
void uwsgi_master_manage_setns(int fd) {
|
||||
|
||||
struct sockaddr_un snsun;
|
||||
socklen_t snsun_len = sizeof(struct sockaddr_un);
|
||||
|
||||
int setns_client = accept(fd, (struct sockaddr *) &snsun, &snsun_len);
|
||||
if (setns_client < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_setns()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
int tmp_fds[64];
|
||||
int *fds = tmp_fds;
|
||||
int num_fds = 0;
|
||||
|
||||
struct msghdr sn_msg;
|
||||
void *sn_msg_control;
|
||||
struct iovec sn_iov[2];
|
||||
struct cmsghdr *cmsg;
|
||||
DIR *ns = NULL;
|
||||
|
||||
if (uwsgi.setns_fds_count) {
|
||||
fds = uwsgi.setns_fds;
|
||||
num_fds = uwsgi.setns_fds_count;
|
||||
goto send;
|
||||
}
|
||||
|
||||
struct dirent *de;
|
||||
ns = opendir("/proc/self/ns");
|
||||
if (!ns) {
|
||||
close(setns_client);
|
||||
uwsgi_error("uwsgi_master_manage_setns()/opendir()");
|
||||
return;
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
if (!strcmp(de->d_name, usl->value)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
|
||||
fds[num_fds] = open(filename, O_RDONLY);
|
||||
if (fds[num_fds] < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
free(filename);
|
||||
goto clear;
|
||||
}
|
||||
free(filename);
|
||||
num_fds++;
|
||||
}
|
||||
|
||||
send:
|
||||
|
||||
sn_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
|
||||
|
||||
sn_iov[0].iov_base = "uwsgi-setns";
|
||||
sn_iov[0].iov_len = 11;
|
||||
sn_iov[1].iov_base = &num_fds;
|
||||
sn_iov[1].iov_len = sizeof(int);
|
||||
|
||||
sn_msg.msg_name = NULL;
|
||||
sn_msg.msg_namelen = 0;
|
||||
|
||||
sn_msg.msg_iov = sn_iov;
|
||||
sn_msg.msg_iovlen = 2;
|
||||
|
||||
sn_msg.msg_flags = 0;
|
||||
sn_msg.msg_control = sn_msg_control;
|
||||
sn_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&sn_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
int *sn_fd_ptr = (int *) CMSG_DATA(cmsg);
|
||||
for(i=0;i<num_fds;i++) {
|
||||
sn_fd_ptr[i] = fds[i];
|
||||
}
|
||||
|
||||
if (sendmsg(setns_client, &sn_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_setns()/sendmsg()");
|
||||
}
|
||||
|
||||
free(sn_msg_control);
|
||||
|
||||
clear:
|
||||
close(setns_client);
|
||||
if (ns) {
|
||||
closedir(ns);
|
||||
for(i=0;i<num_fds;i++) {
|
||||
close(fds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
this is racey, but the worst thing would be printing garbage in the logs...
|
||||
*/
|
||||
void uwsgi_dump_worker(int wid, char *msg) {
|
||||
int i;
|
||||
uwsgi_log_verbose("%s !!! worker %d status !!!\n", msg, wid);
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
struct uwsgi_core *uc = &uwsgi.workers[wid].cores[i];
|
||||
struct wsgi_request *wsgi_req = &uc->req;
|
||||
if (uc->in_request) {
|
||||
uwsgi_log_verbose("%s [core %d] %.*s - %.*s %.*s since %llu\n", msg, i, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) (wsgi_req->start_of_request/(1000*1000)));
|
||||
}
|
||||
}
|
||||
uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
|
||||
}
|
||||
|
||||
+981
-63
File diff suppressed because it is too large
Load Diff
+30
-6
@@ -16,6 +16,7 @@
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
@@ -53,6 +54,9 @@ static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_NOSUID
|
||||
{"nosuid", MS_NOSUID},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
@@ -101,8 +105,8 @@ uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
#ifdef __FreeBSD__
|
||||
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;
|
||||
@@ -120,8 +124,8 @@ int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
#elif defined(__FreeBSD__)
|
||||
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;
|
||||
@@ -189,13 +193,14 @@ unmountable:
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__)
|
||||
#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, ' ');
|
||||
@@ -207,8 +212,12 @@ int uwsgi_mount_hook(char *arg) {
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
data = strchr(flags, ' ');
|
||||
if (data) {
|
||||
*data = 0; data++;
|
||||
}
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags)) {
|
||||
if (uwsgi_mount(fs, what, where, flags, data)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
@@ -236,3 +245,18 @@ int uwsgi_umount_hook(char *arg) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
|
||||
uwsgi_mule_run();
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
+1
-1
@@ -323,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
|
||||
return 0;
|
||||
}
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+27
-76
@@ -18,81 +18,6 @@ static size_t get_content_length(char *buf, uint16_t size) {
|
||||
}
|
||||
|
||||
|
||||
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
int fd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
char *udp_port;
|
||||
ssize_t ret;
|
||||
|
||||
struct uwsgi_header *uh;
|
||||
|
||||
udp_port = strchr(host, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_port = htons(atoi(udp_port + 1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
}
|
||||
else {
|
||||
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&un_addr, 0, sizeof(struct sockaddr_un));
|
||||
un_addr.sun_family = AF_UNIX;
|
||||
// use 102 as the magic number
|
||||
strncat(un_addr.sun_path, host, 102);
|
||||
|
||||
}
|
||||
|
||||
if (message) {
|
||||
uh = (struct uwsgi_header *) message;
|
||||
}
|
||||
else {
|
||||
uh = (struct uwsgi_header *) uwsgi_malloc(4);
|
||||
}
|
||||
|
||||
uh->modifier1 = modifier1;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(message_size);
|
||||
#else
|
||||
uh->pktsize = message_size;
|
||||
#endif
|
||||
uh->modifier2 = modifier2;
|
||||
|
||||
if (udp_port) {
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if ((char *) uh != message) {
|
||||
free(uh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
|
||||
|
||||
char *ptr = (char *) uh;
|
||||
@@ -412,6 +337,12 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_ORIGIN", 11)) {
|
||||
wsgi_req->http_origin = buf;
|
||||
wsgi_req->http_origin_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,7 +494,7 @@ static int uwsgi_proto_check_18(struct wsgi_request *wsgi_req, char *key, char *
|
||||
|
||||
|
||||
static int uwsgi_proto_check_20(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
if (uwsgi.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
|
||||
if (uwsgi.logging_options.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
|
||||
wsgi_req->remote_addr = buf;
|
||||
wsgi_req->remote_addr_len = len;
|
||||
return 0;
|
||||
@@ -589,9 +520,28 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
|
||||
wsgi_req->if_modified_since_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_KEY", 22)) {
|
||||
wsgi_req->http_sec_websocket_key = buf;
|
||||
wsgi_req->http_sec_websocket_key_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_27(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_PROTOCOL", 27)) {
|
||||
wsgi_req->http_sec_websocket_protocol = buf;
|
||||
wsgi_req->http_sec_websocket_protocol_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_proto_hooks_setup() {
|
||||
int i = 0;
|
||||
for(i=0;i<UWSGI_PROTO_MAX_CHECK;i++) {
|
||||
@@ -609,6 +559,7 @@ void uwsgi_proto_hooks_setup() {
|
||||
uwsgi.proto_hooks[18] = uwsgi_proto_check_18;
|
||||
uwsgi.proto_hooks[20] = uwsgi_proto_check_20;
|
||||
uwsgi.proto_hooks[22] = uwsgi_proto_check_22;
|
||||
uwsgi.proto_hooks[27] = uwsgi_proto_check_27;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
+72
-15
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
|
||||
struct pollfd upoll[2];
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll[0].fd = fd0;
|
||||
upoll[0].events = POLLIN;
|
||||
upoll[0].revents = 0;
|
||||
|
||||
upoll[1].fd = fd1;
|
||||
upoll[1].events = POLLIN;
|
||||
upoll[1].revents = 0;
|
||||
|
||||
int ret = poll(upoll, 2, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll[0].revents & POLLIN) {
|
||||
*fd = fd0;
|
||||
return 1;
|
||||
}
|
||||
if (upoll[1].revents & POLLIN) {
|
||||
*fd = fd1;
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
seek()/rewind() language-independent implementations.
|
||||
*/
|
||||
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
if (wsgi_req->post_file) {
|
||||
if (pos < 0) {
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
@@ -95,7 +130,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("consume_body_for_readline()/realloc()");
|
||||
uwsgi_req_error("consume_body_for_readline()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_readline_buf = tmp_buf;
|
||||
@@ -114,7 +149,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
uwsgi_req_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += remains;
|
||||
@@ -140,6 +175,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
@@ -147,6 +183,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -159,6 +196,7 @@ wait:
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
@@ -167,6 +205,7 @@ wait:
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -204,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
|
||||
wsgi_req->post_readline_buf = malloc(amount);
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
uwsgi_error("uwsgi_request_body_readline()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -217,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
|
||||
|
||||
if (consume_body_for_readline(wsgi_req)) {
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -272,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (avail > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
@@ -320,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
wsgi_req->post_read_buf = malloc(remains);
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -331,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -348,7 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/fread()");
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
*rlen += remains;
|
||||
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wait:
|
||||
@@ -389,6 +435,8 @@ wait:
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
|
||||
goto wait;
|
||||
}
|
||||
*rlen = -1;
|
||||
if (len == 0) {
|
||||
@@ -396,6 +444,7 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -407,6 +456,7 @@ wait:
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -480,7 +532,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_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;
|
||||
}
|
||||
|
||||
|
||||
+103
-52
@@ -582,6 +582,88 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// simple math router
|
||||
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint16_t var_vallen = 0;
|
||||
char *var_value = uwsgi_get_var(wsgi_req, ur->data, ur->data_len, &var_vallen);
|
||||
if (!var_value) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
int64_t base_value = uwsgi_str_num(var_value, var_vallen);
|
||||
int64_t value = 1;
|
||||
|
||||
if (ur->data2_len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
value = uwsgi_str_num(ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
char out[sizeof(UMAX64_STR)+1];
|
||||
int64_t total = 0;
|
||||
|
||||
switch(ur->custom) {
|
||||
// -
|
||||
case 1:
|
||||
total = base_value - value;
|
||||
break;
|
||||
// *
|
||||
case 2:
|
||||
total = base_value * value;
|
||||
break;
|
||||
// /
|
||||
case 3:
|
||||
if (value == 0) total = 0;
|
||||
else {
|
||||
total = base_value/value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
total = base_value + value;
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = uwsgi_long2str2n(total, out, sizeof(UMAX64_STR)+1);
|
||||
if (ret <= 0) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, out, ret)) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_plus(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_simple_math_func;
|
||||
char *comma = strchr(arg, ',');
|
||||
if (comma) {
|
||||
ur->data = arg;
|
||||
ur->data_len = comma - arg;
|
||||
ur->data2 = comma+1;
|
||||
ur->data2_len = strlen(ur->data);
|
||||
}
|
||||
else {
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_minus(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 1;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_multiply(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 2;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 2;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
// harakiri router
|
||||
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
@@ -623,7 +705,7 @@ static int uwsgi_router_flush(struct uwsgi_route *ur, char *arg) {
|
||||
static int transform_fixcl(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) ut->chunk->pos);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -640,7 +722,6 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// log route
|
||||
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
@@ -881,7 +962,7 @@ static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
if (chdir(ub->buf)) {
|
||||
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_req_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
@@ -1199,10 +1280,21 @@ static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
|
||||
|
||||
// send route
|
||||
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
|
||||
char **subject = (char **) (((char *)(wsgi_req))+route->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+route->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, route, *subject, *subject_len, route->data, route->data_len);
|
||||
if (!ub) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
if (route->custom) {
|
||||
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
|
||||
@@ -1564,7 +1656,7 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
|
||||
ret = uwsgi_num2str(uwsgi.shared->load);
|
||||
ret = uwsgi_num2str(uwsgi.shared->backlog);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
@@ -1629,48 +1721,6 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
@@ -1703,6 +1753,11 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
|
||||
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
|
||||
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
|
||||
uwsgi_register_router("/", uwsgi_router_simple_math_divide);
|
||||
|
||||
uwsgi_register_router("flush", uwsgi_router_flush);
|
||||
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
|
||||
|
||||
@@ -1746,10 +1801,6 @@ void uwsgi_register_embedded_routers() {
|
||||
urv->need_free = 1;
|
||||
urv = uwsgi_register_route_var("httptime", uwsgi_route_var_httptime);
|
||||
urv->need_free = 1;
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
#endif
|
||||
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
|
||||
urv->need_free = 1;
|
||||
|
||||
|
||||
+38
-10
@@ -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);
|
||||
|
||||
@@ -85,8 +85,15 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
|
||||
size_t *r = (size_t *) data;
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
|
||||
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
|
||||
*r = uwsgi_str_num(value, vl);
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(UMAX16);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
|
||||
if (*buffer)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +117,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,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
// ok the reuqest is ready, let's send it in non blocking way
|
||||
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) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is an high-performance memory area shared by all workers/cores/threads
|
||||
|
||||
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
|
||||
|
||||
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
|
||||
the language object.
|
||||
|
||||
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
|
||||
|
||||
You can configure multiple areas specifying multiple --sharedarea options
|
||||
|
||||
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
|
||||
if (id > uwsgi.sharedareas_cnt-1) return NULL;
|
||||
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
|
||||
if (pos > sa->max_pos) return NULL;
|
||||
return sa;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_update(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
sa->updates++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_rlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_wlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_unlock(int id) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
if (len == 0) len = (sa->max_pos + 1) - pos;
|
||||
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
|
||||
uwsgi_rlock(sa->lock);
|
||||
memcpy(blob, sa->area + pos, len);
|
||||
sa->hits++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
memcpy(sa->area + pos, blob, len);
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 8);
|
||||
return rlen == 8 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 1);
|
||||
return rlen == 1 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 2);
|
||||
return rlen == 2 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, (char *) value, 4);
|
||||
return rlen == 4 ? 0 : -1;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
returns:
|
||||
0 -> on updates
|
||||
-1 -> on error
|
||||
-2 -> on timeout
|
||||
*/
|
||||
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
int waiting = 0;
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
if (!freq) freq = 100;
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
|
||||
uwsgi.wait_milliseconds_hook(freq);
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
if (sa->updates != updates) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
// unlock sa
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_new_id() {
|
||||
int id = uwsgi.sharedareas_cnt;
|
||||
uwsgi.sharedareas_cnt++;
|
||||
if (!uwsgi.sharedareas) {
|
||||
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
|
||||
}
|
||||
else {
|
||||
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
|
||||
if (!usa) {
|
||||
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas = usa;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
|
||||
return sa;
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = pages;
|
||||
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = area;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_pages = NULL;
|
||||
char *s_file = NULL;
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid sharedarea keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t len = 0;
|
||||
int pages = 0;
|
||||
if (s_size) {
|
||||
len = uwsgi_n64(s_size);
|
||||
pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) pages++;
|
||||
}
|
||||
|
||||
if (s_pages) {
|
||||
pages = atoi(s_pages);
|
||||
}
|
||||
|
||||
char *area = NULL;
|
||||
struct uwsgi_sharedarea *sa = NULL;
|
||||
if (s_file) {
|
||||
}
|
||||
else if (s_fd) {
|
||||
}
|
||||
else if (s_ptr) {
|
||||
}
|
||||
|
||||
if (pages) {
|
||||
if (!area) {
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pages) free(s_pages);
|
||||
if (s_file) free(s_file);
|
||||
if (s_fd) free(s_fd);
|
||||
if (s_ptr) free(s_ptr);
|
||||
if (s_size) free(s_size);
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sharedareas_init() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
|
||||
char *is_keyval = strchr(usl->value, '=');
|
||||
if (!is_keyval) {
|
||||
uwsgi_sharedarea_init(atoi(usl->value));
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_keyval(usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-9
@@ -45,21 +45,21 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 1;
|
||||
uwsgi.workers[uwsgi.mywid].signum = sig;
|
||||
uwsgi.workers[uwsgi.mywid].signals++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signals++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.mules > 0) {
|
||||
set_mule_harakiri(uwsgi.harakiri_options.mules);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
if (uwsgi.harakiri_options.spoolers > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,7 @@ 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);
|
||||
int fd = uwsgi_connect(addr, uwsgi.socket_timeout, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
@@ -279,7 +279,7 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.socket_timeout, NULL);
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
@@ -301,8 +301,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
uwsgi.shared->unrouted_signals++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi.shared->routed_signals++;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
+55
-14
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
|
||||
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
|
||||
|
||||
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
uwsgi_debug("SNMP version: %d\n", version);
|
||||
#endif
|
||||
|
||||
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
|
||||
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
|
||||
if (*ptr != SNMP_STRING)
|
||||
return;
|
||||
ptr++;
|
||||
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
ptr++;
|
||||
|
||||
oidlen = *ptr;
|
||||
if (oidlen != 11)
|
||||
if (oidlen < 11)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
|
||||
oid_part[0] = *ptr;
|
||||
|
||||
if (oid_part[0] != 1 && oid_part[0] != 2)
|
||||
return;
|
||||
ptr++;
|
||||
// old-style SNMP metrics
|
||||
if (oid_part[0] == 1 || oid_part[0] == 2) {
|
||||
ptr++;
|
||||
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
// metrics subsystem
|
||||
else {
|
||||
size_t metric_asn_len = oidlen - 9;
|
||||
char *metric_asn = (char *) ptr;
|
||||
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
|
||||
if (!um) return;
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int64_t value = *um->value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
|
||||
if (size > 0) {
|
||||
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
uint8_t tlen;
|
||||
int i, j;
|
||||
uint8_t *ptr = (uint8_t *) & snmp_val;
|
||||
int32_t val32 = (int32_t) snmp_val;
|
||||
|
||||
// check for counter, counter64 or gauge
|
||||
|
||||
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
}
|
||||
else {
|
||||
tlen = 4;
|
||||
ptr = (uint8_t *) &val32;
|
||||
}
|
||||
|
||||
buffer[0] = tlen;
|
||||
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
|
||||
|
||||
}
|
||||
|
||||
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
|
||||
uint8_t oid_sz;
|
||||
|
||||
if (type == UWSGI_METRIC_GAUGE) {
|
||||
buffer[size - 2] = SNMP_GAUGE;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
|
||||
}
|
||||
else {
|
||||
buffer[size - 2] = SNMP_COUNTER64;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
|
||||
}
|
||||
|
||||
if (oid_sz < 1)
|
||||
return -1;
|
||||
|
||||
oid_sz--;
|
||||
|
||||
buffer[1] += oid_sz;
|
||||
*seq1 += oid_sz;
|
||||
*seq2 += oid_sz;
|
||||
*seq3 += oid_sz;
|
||||
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
|
||||
uwsgi.snmp = 1;
|
||||
if (value) {
|
||||
|
||||
+79
-104
@@ -6,6 +6,22 @@ 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);
|
||||
@@ -734,7 +750,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
#ifdef __linux__
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.socket_timeout, sizeof(int))) {
|
||||
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
|
||||
}
|
||||
// OSX has no SO_ACCEPTFILTER !!!
|
||||
@@ -1366,7 +1382,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
|
||||
}
|
||||
else if (uwsgi_sock->fd > -1) {
|
||||
@@ -1673,18 +1689,7 @@ void uwsgi_map_sockets() {
|
||||
|
||||
if (!enabled) {
|
||||
close(uwsgi_sock->fd);
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (fd != uwsgi_sock->fd) {
|
||||
if (dup2(fd, uwsgi_sock->fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
|
||||
uwsgi_sock->disabled = 1;
|
||||
}
|
||||
|
||||
@@ -1714,6 +1719,10 @@ void uwsgi_bind_sockets() {
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
|
||||
char *tcp_port = strrchr(uwsgi_sock->name, ':');
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
if (uwsgi_sock->no_defer) {
|
||||
uwsgi.no_defer_accept = 1;
|
||||
}
|
||||
if (tcp_port == NULL) {
|
||||
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -1747,6 +1756,7 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
@@ -1859,96 +1869,8 @@ void uwsgi_set_sockets_protocols() {
|
||||
|
||||
|
||||
setup_proto:
|
||||
if (!requested_protocol) {
|
||||
requested_protocol = uwsgi.protocol;
|
||||
}
|
||||
|
||||
if (requested_protocol && !strcmp("http", requested_protocol)) {
|
||||
uwsgi_sock->proto = uwsgi_proto_http_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
|
||||
uwsgi.zeromq = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
if (!requested_protocol) requested_protocol = uwsgi.protocol;
|
||||
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
@@ -1984,3 +1906,56 @@ int uwsgi_accept(int server_fd) {
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+3
-3
@@ -552,11 +552,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)
|
||||
|
||||
+31
-1
@@ -132,7 +132,6 @@ static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
|
||||
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:
|
||||
@@ -511,10 +510,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);
|
||||
}
|
||||
|
||||
+2
-1
@@ -450,7 +450,8 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
if (st->st_mtime <= ims) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16))
|
||||
return -1;
|
||||
return uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
}
|
||||
|
||||
+33
-60
@@ -111,7 +111,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -123,7 +123,7 @@ int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -161,7 +161,7 @@ int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsign
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -200,7 +200,7 @@ int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vall
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":", key);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -239,7 +239,7 @@ int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":", key);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\"", str);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -266,7 +266,7 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\"", str);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -299,7 +299,7 @@ int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long nu
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
@@ -337,7 +337,7 @@ int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
@@ -440,6 +440,11 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(1);
|
||||
for (;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
|
||||
if (nevents < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
uwsgi_log_verbose("ending the stats pusher thread...\n");
|
||||
return;
|
||||
}
|
||||
if (nevents > 0) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, 0);
|
||||
char buf[4096];
|
||||
@@ -457,7 +462,8 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
struct uwsgi_stats *us = NULL;
|
||||
while (uspi) {
|
||||
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
|
||||
if ((uspi->last_run + delta) <= now) {
|
||||
if (((uspi->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
|
||||
if (uspi->needs_retry) uspi->retries++;
|
||||
if (uspi->raw) {
|
||||
uspi->pusher->func(uspi, now, NULL, 0);
|
||||
}
|
||||
@@ -470,6 +476,17 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
uspi->pusher->func(uspi, now, us->base, us->pos);
|
||||
}
|
||||
uspi->last_run = now;
|
||||
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
|
||||
uspi->next_retry = now + uspi->retry_delay;
|
||||
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
|
||||
uspi->needs_retry = 0;
|
||||
uspi->retries = 0;
|
||||
} else if (uspi->retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
|
||||
uspi->retries = 0;
|
||||
}
|
||||
}
|
||||
next:
|
||||
uspi = uspi->next;
|
||||
@@ -531,50 +548,6 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
return pusher;
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher_file_conf {
|
||||
char *path;
|
||||
char *freq;
|
||||
char *separator;
|
||||
};
|
||||
|
||||
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
|
||||
if (!uspi->configured) {
|
||||
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
|
||||
if (uspi->arg) {
|
||||
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
|
||||
free(uspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!uspic->path)
|
||||
uspic->path = "uwsgi.stats";
|
||||
if (!uspic->separator)
|
||||
uspic->separator = "\n\n";
|
||||
if (uspic->freq)
|
||||
uspi->freq = atoi(uspic->freq);
|
||||
uspi->configured = 1;
|
||||
uspi->data = uspic;
|
||||
}
|
||||
|
||||
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uspic->path);
|
||||
return;
|
||||
}
|
||||
ssize_t rlen = write(fd, json, json_len);
|
||||
if (rlen != (ssize_t) json_len) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
rlen = write(fd, uspic->separator, strlen(uspic->separator));
|
||||
if (rlen != (ssize_t) strlen(uspic->separator)) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
|
||||
+104
@@ -379,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
|
||||
return buf - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
status 0: append mode
|
||||
status 1: single quote found
|
||||
status 2: double quote found
|
||||
status 3: backslash found (on 0)
|
||||
status 4: backslash found (on 1)
|
||||
status 5: backslash found (on 2)
|
||||
|
||||
*/
|
||||
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
|
||||
size_t i;
|
||||
int status = 0;
|
||||
char *base = uwsgi_concat2n(what, what_len, "", 0);
|
||||
char *item = NULL;
|
||||
char *ptr = NULL;
|
||||
*rlen = 0;
|
||||
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
|
||||
|
||||
for(i=0;i<what_len;i++) {
|
||||
if (!item) {
|
||||
item = uwsgi_malloc((what_len - i)+1);
|
||||
ptr = item;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
if (base[i] == '\\') {
|
||||
status = 3;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 2;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 1;
|
||||
}
|
||||
else if (strchr(sep, base[i])) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
item = NULL;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash
|
||||
if (status == 3) {
|
||||
*ptr++= base[i];
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// single quote
|
||||
if (status == 1) {
|
||||
if (base[i] == '\\') {
|
||||
status = 4;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// double quote
|
||||
if (status == 2) {
|
||||
if (base[i] == '\\') {
|
||||
status = 5;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash single quote
|
||||
if (status == 4) {
|
||||
*ptr++= base[i];
|
||||
status = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash double quote
|
||||
if (status == 5) {
|
||||
*ptr++= base[i];
|
||||
status = 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (item) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
}
|
||||
|
||||
free(base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+164
-11
@@ -20,6 +20,51 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static void uwsgi_subscription_sni_check(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_req *usr) {
|
||||
if (usr->sni_key_len > 0 && usr->sni_crt_len > 0) {
|
||||
if (!current_slot->sni_enabled) {
|
||||
char *sni_key = uwsgi_concat2n(usr->sni_key, usr->sni_key_len, "", 0);
|
||||
char *sni_crt = uwsgi_concat2n(usr->sni_crt, usr->sni_crt_len, "", 0);
|
||||
char *sni_ca = NULL;
|
||||
if (usr->sni_ca_len > 0) {
|
||||
sni_ca = uwsgi_concat2n(usr->sni_ca, usr->sni_ca_len, "", 0);
|
||||
}
|
||||
char *servername = NULL;
|
||||
char *colon = memchr(current_slot->key, ':', current_slot->keylen);
|
||||
if (colon) {
|
||||
servername = uwsgi_concat2n(current_slot->key, colon-current_slot->key, "", 0);
|
||||
}
|
||||
else {
|
||||
servername = uwsgi_concat2n(current_slot->key, current_slot->keylen, "", 0);
|
||||
}
|
||||
if (uwsgi_ssl_add_sni_item(servername, sni_crt, sni_key, uwsgi.sni_dir_ciphers , sni_ca)) {
|
||||
current_slot->sni_enabled = 1;
|
||||
}
|
||||
if (sni_key) free(sni_key);
|
||||
if (sni_crt) free(sni_crt);
|
||||
if (sni_ca) free(sni_ca);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_subscription_credentials_check(struct uwsgi_subscribe_slot *slot, struct uwsgi_subscribe_req *usr) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.subscriptions_credentials_check_dir) {
|
||||
char *filename = uwsgi_concat2n(usl->value, usl->len, slot->key, slot->keylen);
|
||||
struct stat st;
|
||||
int ret = stat(filename, &st);
|
||||
free(filename);
|
||||
if (ret != 0) continue;
|
||||
if (st.st_uid != usr->uid) continue;
|
||||
if (st.st_gid != usr->gid) continue;
|
||||
// accepted...
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
|
||||
|
||||
if (keylen > 0xff)
|
||||
@@ -305,6 +350,12 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
EVP_MD_CTX_destroy(node_slot->sign_ctx);
|
||||
}
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
// if there is a SNI context active, destroy it
|
||||
if (node_slot->sni_enabled) {
|
||||
uwsgi_ssl_del_sni_item(node_slot->key, node_slot->keylen);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
free(node_slot);
|
||||
slot[hash_key] = NULL;
|
||||
@@ -358,6 +409,11 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.subscriptions_credentials_check_dir && !uwsgi_subscription_credentials_check(current_slot, usr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = current_slot->nodes;
|
||||
while (node) {
|
||||
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
|
||||
@@ -388,6 +444,8 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
// check here as we are sure the node will be added
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
|
||||
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
@@ -396,7 +454,8 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
node->modifier2 = usr->modifier2;
|
||||
node->requests = 0;
|
||||
node->last_requests = 0;
|
||||
node->transferred = 0;
|
||||
node->tx = 0;
|
||||
node->rx = 0;
|
||||
node->reference = 0;
|
||||
node->death_mark = 0;
|
||||
node->failcnt = 0;
|
||||
@@ -407,6 +466,9 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (!node->weight)
|
||||
node->weight = 1;
|
||||
node->wrr = 0;
|
||||
node->pid = usr->pid;
|
||||
node->uid = usr->uid;
|
||||
node->gid = usr->gid;
|
||||
node->last_check = uwsgi_now();
|
||||
node->slot = current_slot;
|
||||
memcpy(node->name, usr->address, usr->address_len);
|
||||
@@ -464,16 +526,27 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
#endif
|
||||
current_slot->keylen = usr->keylen;
|
||||
memcpy(current_slot->key, usr->key, usr->keylen);
|
||||
if (uwsgi.subscriptions_credentials_check_dir) {
|
||||
if (!uwsgi_subscription_credentials_check(current_slot, usr)) {
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
current_slot->key[usr->keylen] = 0;
|
||||
current_slot->hits = 0;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
current_slot->sni_enabled = 0;
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
current_slot->nodes->slot = current_slot;
|
||||
current_slot->nodes->len = usr->address_len;
|
||||
current_slot->nodes->reference = 0;
|
||||
current_slot->nodes->requests = 0;
|
||||
current_slot->nodes->last_requests = 0;
|
||||
current_slot->nodes->transferred = 0;
|
||||
current_slot->nodes->tx = 0;
|
||||
current_slot->nodes->rx = 0;
|
||||
current_slot->nodes->death_mark = 0;
|
||||
current_slot->nodes->failcnt = 0;
|
||||
current_slot->nodes->modifier1 = usr->modifier1;
|
||||
@@ -485,6 +558,9 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
if (!current_slot->nodes->weight)
|
||||
current_slot->nodes->weight = 1;
|
||||
current_slot->nodes->wrr = 0;
|
||||
current_slot->nodes->pid = usr->pid;
|
||||
current_slot->nodes->uid = usr->uid;
|
||||
current_slot->nodes->gid = usr->gid;
|
||||
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
|
||||
current_slot->nodes->last_check = uwsgi_now();
|
||||
|
||||
@@ -516,8 +592,64 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
|
||||
}
|
||||
|
||||
static void send_subscription(char *host, char *message, uint16_t message_size) {
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
|
||||
int fd;
|
||||
struct sockaddr_in udp_addr;
|
||||
struct sockaddr_un un_addr;
|
||||
ssize_t ret;
|
||||
|
||||
char *udp_port = strchr(host, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
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("send_subscription()/socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
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 (udp_port) {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
udp_port[0] = ':';
|
||||
}
|
||||
else {
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
// could be useless as internally the socket could add them automagically
|
||||
ret = uwsgi_pass_cred2(fd, message, message_size, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
else {
|
||||
ret = sendto(fd, message, message_size, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("send_subscription()/sendto()");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign, char *sni_key, char *sni_crt, char *sni_ca) {
|
||||
|
||||
if (socket_name == NULL && !uwsgi.sockets)
|
||||
return;
|
||||
@@ -560,8 +692,22 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sni_key) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_key", 7, sni_key, strlen(sni_key))) goto end;
|
||||
}
|
||||
|
||||
send_udp_message(224, cmd, udp_address, ub->buf, ub->pos - 4);
|
||||
if (sni_crt) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_crt", 7, sni_crt, strlen(sni_crt))) goto end;
|
||||
}
|
||||
|
||||
if (sni_ca) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "sni_ca", 6, sni_ca, strlen(sni_ca))) goto end;
|
||||
}
|
||||
|
||||
// add uwsgi header
|
||||
if (uwsgi_buffer_set_uh(ub, 224, cmd)) goto end;
|
||||
|
||||
send_subscription(udp_address, ub->buf, ub->pos);
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
@@ -679,7 +825,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
}
|
||||
@@ -697,7 +843,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
modifier1_len = strlen(modifier1);
|
||||
keysize = strlen(key);
|
||||
}
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
modifier1 = NULL;
|
||||
modifier1_len = 0;
|
||||
lines[i] = '\n';
|
||||
@@ -709,9 +855,8 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
}
|
||||
keysize++;
|
||||
}
|
||||
|
||||
free(lines);
|
||||
}
|
||||
free(lines);
|
||||
}
|
||||
else {
|
||||
modifier1 = strchr(subscription_key + 1, ',');
|
||||
@@ -727,7 +872,7 @@ void uwsgi_subscribe(char *subscription, uint8_t cmd) {
|
||||
modifier1_len = strlen(modifier1);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
|
||||
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign, NULL, NULL, NULL);
|
||||
if (modifier1)
|
||||
modifier1[-1] = ',';
|
||||
if (sign)
|
||||
@@ -752,6 +897,9 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
char *s2_modifier1 = NULL;
|
||||
char *s2_modifier2 = NULL;
|
||||
char *s2_check = NULL;
|
||||
char *s2_sni_key = NULL;
|
||||
char *s2_sni_crt = NULL;
|
||||
char *s2_sni_ca = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"server", &s2_server,
|
||||
@@ -763,6 +911,9 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
"modifier2", &s2_modifier2,
|
||||
"sign", &s2_sign,
|
||||
"check", &s2_check,
|
||||
"sni_key", &s2_sni_key,
|
||||
"sni_crt", &s2_sni_crt,
|
||||
"sni_ca", &s2_sni_ca,
|
||||
NULL)) {
|
||||
return;
|
||||
}
|
||||
@@ -798,7 +949,7 @@ void uwsgi_subscribe2(char *arg, uint8_t cmd) {
|
||||
modifier2 = atoi(s2_modifier2);
|
||||
}
|
||||
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign);
|
||||
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign, s2_sni_key, s2_sni_crt, s2_sni_ca);
|
||||
end:
|
||||
if (s2_server) free(s2_server);
|
||||
if (s2_key) free(s2_key);
|
||||
@@ -812,6 +963,8 @@ end:
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
if (uwsgi.subscriptions_blocked) return;
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
|
||||
+1195
-929
File diff suppressed because it is too large
Load Diff
+516
-371
File diff suppressed because it is too large
Load Diff
+87
-14
@@ -10,9 +10,17 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
|
||||
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
|
||||
struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf;
|
||||
if (!ub) {
|
||||
wsgi_req->websocket_send_buf = uwsgi_buffer_new(10 + len);
|
||||
ub = wsgi_req->websocket_send_buf;
|
||||
}
|
||||
else {
|
||||
// reset the buffer
|
||||
ub->pos = 0;
|
||||
}
|
||||
if (uwsgi_buffer_u8(ub, opcode)) goto error;
|
||||
if (len < 126) {
|
||||
if (uwsgi_buffer_u8(ub, len)) goto error;
|
||||
}
|
||||
@@ -29,7 +37,6 @@ static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -59,34 +66,79 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// pong received, send anther ping
|
||||
// pong received, send another ping
|
||||
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
|
||||
return uwsgi_websockets_ping(wsgi_req);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
|
||||
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode);
|
||||
if (!ub) return -1;
|
||||
|
||||
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return ret;
|
||||
|
||||
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
}
|
||||
|
||||
static int uwsgi_websocket_send_from_sharedarea_do(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len, uint8_t opcode) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (!len) {
|
||||
len = sa->honour_used ? sa->used-pos : ((sa->max_pos+1)-pos);
|
||||
}
|
||||
uwsgi_rlock(sa->lock);
|
||||
sa->hits++;
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, sa->area, len, opcode);
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
if (!ub) return -1;
|
||||
|
||||
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x81);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x81);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x82);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x82);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
|
||||
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
|
||||
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
|
||||
@@ -315,18 +367,39 @@ ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
|
||||
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len, char *proto, uint16_t proto_len) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (!key_len) {
|
||||
key = wsgi_req->http_sec_websocket_key;
|
||||
key_len = wsgi_req->http_sec_websocket_key_len;
|
||||
}
|
||||
if (key_len == 0) return -1;
|
||||
|
||||
char sha1[20];
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
|
||||
if (origin_len > 0) {
|
||||
|
||||
// if origin was requested or proto_len is specified, send it back
|
||||
if (wsgi_req->http_origin_len > 0 || origin_len > 0) {
|
||||
if (!origin_len) {
|
||||
origin = wsgi_req->http_origin;
|
||||
origin_len = wsgi_req->http_origin_len;
|
||||
}
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
|
||||
}
|
||||
|
||||
// if protocol was requested or proto_len is specified, send it back
|
||||
if (wsgi_req->http_sec_websocket_protocol_len > 0 || proto_len > 0) {
|
||||
if (!proto_len) {
|
||||
proto = wsgi_req->http_sec_websocket_protocol;
|
||||
proto_len = wsgi_req->http_sec_websocket_protocol_len;
|
||||
}
|
||||
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Protocol", 22, proto, proto_len)) return -1;
|
||||
}
|
||||
// generate websockets sha1 and encode it to base64
|
||||
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
|
||||
size_t b64_len = 0;
|
||||
|
||||
+246
-9
@@ -5,7 +5,7 @@ extern struct uwsgi_server uwsgi;
|
||||
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t sta
|
||||
end = cl-1;
|
||||
}
|
||||
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
|
||||
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
if (ret <= 0 || ret >= (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -179,7 +179,7 @@ int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, ui
|
||||
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
|
||||
}
|
||||
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
@@ -209,11 +209,20 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
|
||||
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int ret = uwsgi_response_write_headers_do0(wsgi_req);
|
||||
if (ret != UWSGI_AGAIN) return ret;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_headers_do()");
|
||||
uwsgi_req_error("uwsgi_response_write_headers_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -221,6 +230,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
@@ -238,6 +248,100 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
private function for highly optimized writes (1 single syscall for headers and body)
|
||||
*/
|
||||
static int uwsgi_response_writev_headers_and_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
struct iovec iov[2];
|
||||
|
||||
int ret = uwsgi_response_write_headers_do0(wsgi_req);
|
||||
if (ret != UWSGI_AGAIN) return ret;
|
||||
|
||||
iov[0].iov_base = wsgi_req->headers->buf;
|
||||
iov[0].iov_len = wsgi_req->headers->pos;
|
||||
iov[1].iov_base = buf;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
size_t iov_len = 2;
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
// no need to use writev if a single iovec remains
|
||||
if (iov_len == 1) {
|
||||
buf = iov[0].iov_base;
|
||||
len = iov[0].iov_len;
|
||||
// update counters
|
||||
wsgi_req->headers_size += wsgi_req->headers->pos;
|
||||
wsgi_req->headers_sent = 1;
|
||||
wsgi_req->response_size += wsgi_req->write_pos - wsgi_req->headers_size;
|
||||
wsgi_req->write_pos = 0;
|
||||
goto fallback;
|
||||
}
|
||||
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_headers_and_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_headers_and_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->headers->pos;
|
||||
wsgi_req->response_size += len;
|
||||
wsgi_req->headers_sent = 1;
|
||||
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
fallback:
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
// here we use the parent name
|
||||
uwsgi_req_error("uwsgi_response_write_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
// here we use the parent name
|
||||
uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
}
|
||||
|
||||
// this is the function called by all request plugins to send chunks to the client
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
@@ -278,6 +382,9 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
write:
|
||||
// send headers if not already sent
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (wsgi_req->socket->proto_writev && len > 0 && wsgi_req->headers) {
|
||||
return uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len);
|
||||
}
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendbody;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
@@ -290,10 +397,11 @@ sendbody:
|
||||
if (len == 0) return UWSGI_OK;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_body_do()");
|
||||
uwsgi_req_error("uwsgi_response_write_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -301,6 +409,7 @@ sendbody:
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
@@ -317,6 +426,130 @@ sendbody:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_response_writev_body_do(struct wsgi_request *wsgi_req, struct iovec *iov, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t i;
|
||||
int buffering = 0;
|
||||
// transformations apply to every vector
|
||||
for(i=0;i<len;i++) {
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
int t_ret = uwsgi_apply_transformations(wsgi_req, iov[i].iov_base, iov[i].iov_len);
|
||||
if (t_ret == 0) {
|
||||
iov[i].iov_base = wsgi_req->transformed_chunk;
|
||||
iov[i].iov_len = wsgi_req->transformed_chunk_len;
|
||||
// reset transformation
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
goto write;
|
||||
}
|
||||
if (t_ret == 1) {
|
||||
buffering = 1;
|
||||
continue;
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffering) return UWSGI_OK;
|
||||
|
||||
write:
|
||||
// send headers if not already sent
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendbody;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sendbody:
|
||||
|
||||
if (len == 0) return UWSGI_OK;
|
||||
// unfortunately vector based I/O cannot be accomplished on all protocols
|
||||
if (!wsgi_req->socket->proto_writev) goto fallback;
|
||||
|
||||
// we use a copy to avoid mess
|
||||
size_t iov_len = len;
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
fallback:
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, iov[i].iov_base, iov[i].iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
|
||||
}
|
||||
@@ -349,7 +582,7 @@ sendfile:
|
||||
if (len == 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
@@ -367,7 +600,7 @@ sendfile:
|
||||
if (!can_close) {
|
||||
int tmp_fd = dup(fd);
|
||||
if (tmp_fd < 0) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()/dup()");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -388,10 +621,11 @@ sendfile:
|
||||
wsgi_req->via = UWSGI_VIA_SENDFILE;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
@@ -400,6 +634,7 @@ sendfile:
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
@@ -454,10 +689,11 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_write()");
|
||||
uwsgi_req_error("uwsgi_simple_write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -465,6 +701,7 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
|
||||
@@ -151,6 +151,8 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
}
|
||||
/* We can safely free resources */
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
|
||||
@@ -267,6 +269,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
|
||||
} while (!done);
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
// we can safely free, as we have a copy of datas
|
||||
XML_ParserFree(parser);
|
||||
|
||||
@@ -280,6 +280,7 @@ next:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -123,12 +123,13 @@ int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t
|
||||
if (!gzipped0) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
|
||||
free(gzipped0);
|
||||
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, crc32)) goto end2;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end2;
|
||||
deflateEnd(z);
|
||||
return 0;
|
||||
end:
|
||||
if (gzipped0) free(gzipped0);
|
||||
end2:
|
||||
deflateEnd(z);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import uwsgi
|
||||
|
||||
import os
|
||||
|
||||
def application(env, start_response):
|
||||
@@ -15,12 +14,12 @@ def application(env, start_response):
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
yield "--%s\n" % boundary
|
||||
yield "--%s\r\n" % boundary
|
||||
|
||||
while 1:
|
||||
yield "Content-Type: image/jpeg\r\n\r\n"
|
||||
uwsgi.sendfile('screenshot.jpg')
|
||||
yield "--%s\n" % boundary
|
||||
print os.system('screencapture -t jpg -m -T 1 screenshot.jpg')
|
||||
f = open('screenshot.jpg')
|
||||
yield env['wsgi.file_wrapper'](f)
|
||||
yield "\r\n--%s\r\n" % boundary
|
||||
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
|
||||
#os.system('screencapture -m -T 1 screenshot.jpg')
|
||||
|
||||
@@ -42,16 +42,6 @@ def application(env, start_response):
|
||||
|
||||
yield '<h2>dynamic options</h2>'
|
||||
|
||||
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
|
||||
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
|
||||
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
|
||||
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
|
||||
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
|
||||
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
|
||||
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
|
||||
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
|
||||
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
|
||||
|
||||
yield '<table border="1">'
|
||||
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
|
||||
|
||||
|
||||
@@ -47,11 +47,6 @@ def serve_logo(e, sr):
|
||||
uwsgi.sendfile('logo_uWSGI.png')
|
||||
return ''
|
||||
|
||||
def serve_options(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in range(0,256):
|
||||
yield "<b>%d</b> = %d<br/>" % (opt, uwsgi.get_option(opt))
|
||||
|
||||
def serve_config(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in uwsgi.opt.keys():
|
||||
@@ -61,7 +56,6 @@ routes = {}
|
||||
routes['/xsendfile'] = xsendfile
|
||||
routes['/logo'] = serve_logo
|
||||
routes['/config'] = serve_config
|
||||
routes['/options'] = serve_options
|
||||
|
||||
@postfork
|
||||
def setprocname():
|
||||
@@ -119,11 +113,6 @@ def application(env, start_response):
|
||||
Configuration<br/>
|
||||
<iframe src="/config"></iframe><br/>
|
||||
|
||||
<br/>
|
||||
|
||||
Dynamic options<br/>
|
||||
<iframe src="/options"></iframe><br/>
|
||||
|
||||
<br/>
|
||||
Workers and applications<br/>
|
||||
<table border="1">
|
||||
|
||||
@@ -9,12 +9,6 @@ def serve_logo(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'image/png')])
|
||||
return uwsgi.sendfile('logo_uWSGI.png')
|
||||
|
||||
def serve_options(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in range(0,256):
|
||||
body = "{opt} = {optvalue}<br/>".format(opt=opt, optvalue=uwsgi.get_option(opt))
|
||||
yield bytes(body.encode('ascii'))
|
||||
|
||||
def serve_config(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in uwsgi.opt.keys():
|
||||
@@ -25,7 +19,6 @@ routes = {}
|
||||
routes['/xsendfile'] = xsendfile
|
||||
routes['/logo'] = serve_logo
|
||||
routes['/config'] = serve_config
|
||||
routes['/options'] = serve_options
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
@@ -43,9 +36,6 @@ Configuration<br/>
|
||||
|
||||
<br/>
|
||||
|
||||
Dynamic options<br/>
|
||||
<iframe src="/options"></iframe><br/>
|
||||
|
||||
""".format(version=uwsgi.version.decode('ascii'))
|
||||
|
||||
return bytes(body.encode('ascii'))
|
||||
|
||||
+15
-2
@@ -52,16 +52,22 @@ int uwsgi_is_a_keep_mount(char *mp) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_ns_start(void *v_argv) {
|
||||
uwsgi_start(v_argv);
|
||||
return uwsgi_run();
|
||||
}
|
||||
|
||||
void linux_namespace_start(void *argv) {
|
||||
for (;;) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
int waitpid_status;
|
||||
char *pid_str = NULL;
|
||||
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
|
||||
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
|
||||
if (uwsgi.ns_net) {
|
||||
clone_flags |= CLONE_NEWNET;
|
||||
}
|
||||
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
|
||||
pid_t pid = clone(uwsgi_ns_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
|
||||
if (pid == -1) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
@@ -72,10 +78,12 @@ void linux_namespace_start(void *argv) {
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
pid_str = uwsgi_num2str((int) pid);
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
if (setenv("UWSGI_JAIL_PID", pid_str, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
free(pid_str);
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
@@ -106,6 +114,11 @@ void linux_namespace_start(void *argv) {
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
|
||||
exit(1);
|
||||
}
|
||||
else if (uwsgi.exit_on_reload && WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 0) {
|
||||
uwsgi_log("jailed master process exited and exit-on-reload is enabled, shutting down\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* uwsgi ADMIN|10 */
|
||||
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint32_t opt_value = 0;
|
||||
|
||||
if (wsgi_req->uh->pktsize != 0 && wsgi_req->uh->pktsize != 4)
|
||||
return UWSGI_OK;
|
||||
|
||||
// write request
|
||||
if (wsgi_req->uh->pktsize == 4) {
|
||||
memcpy(&opt_value, wsgi_req->buffer, 4);
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh->modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh->modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh->modifier1 = 255;
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
}
|
||||
// get request
|
||||
else {
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh->modifier2, uwsgi.shared->options[wsgi_req->uh->modifier2]);
|
||||
|
||||
wsgi_req->uh->modifier1 = 10;
|
||||
wsgi_req->uh->pktsize = 4;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uwsgi.shared->options[wsgi_req->uh->modifier2], 4);
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin admin_plugin = {
|
||||
|
||||
.name = "admin",
|
||||
.modifier1 = 10,
|
||||
.request = uwsgi_request_admin,
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
NAME='admin'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['admin_plugin']
|
||||
@@ -222,8 +222,8 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
|
||||
@@ -146,8 +146,8 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
|
||||
+30
-36
@@ -26,9 +26,6 @@ struct uwsgi_carbon {
|
||||
unsigned long long *last_busyness_values;
|
||||
unsigned long long *current_busyness_values;
|
||||
int *was_busy;
|
||||
int need_retry;
|
||||
time_t last_update;
|
||||
time_t next_retry;
|
||||
int max_retries;
|
||||
int retry_delay;
|
||||
char *root_node;
|
||||
@@ -40,6 +37,7 @@ struct uwsgi_carbon {
|
||||
int zero_avg;
|
||||
uint64_t last_requests;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
int use_metrics;
|
||||
} u_carbon;
|
||||
|
||||
static struct uwsgi_option carbon_options[] = {
|
||||
@@ -55,6 +53,7 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
|
||||
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different)", uwsgi_opt_true, &u_carbon.use_metrics, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -108,7 +107,7 @@ static void carbon_post_init() {
|
||||
|
||||
if (u_carbon.freq < 1) u_carbon.freq = 60;
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
|
||||
if (u_carbon.max_retries < 0) u_carbon.max_retries = 0;
|
||||
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
@@ -153,14 +152,13 @@ static void carbon_post_init() {
|
||||
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set next update to now()+retry_delay, this way we will have first flush just after start
|
||||
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
|
||||
|
||||
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
|
||||
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
|
||||
|
||||
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
|
||||
uspi->freq = u_carbon.freq;
|
||||
uspi->retry_delay = u_carbon.retry_delay;
|
||||
uspi->max_retries = u_carbon.max_retries;
|
||||
// no need to generate the json
|
||||
uspi->raw=1;
|
||||
}
|
||||
@@ -185,14 +183,15 @@ static int carbon_write(int fd, char *fmt,...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
struct carbon_server_list *usl = u_carbon.servers_data;
|
||||
if (!u_carbon.servers_data) return;
|
||||
if (!u_carbon.servers_data) return 0;
|
||||
int i;
|
||||
int fd;
|
||||
int wok;
|
||||
char *ip;
|
||||
char *carbon_address = NULL;
|
||||
int needs_retry;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
@@ -200,7 +199,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
|
||||
}
|
||||
|
||||
u_carbon.need_retry = 0;
|
||||
needs_retry = 0;
|
||||
while(usl) {
|
||||
if (retry_cycle && usl->healthy)
|
||||
// skip healthy servers during retry cycle
|
||||
@@ -228,15 +227,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
|
||||
if (usl->errors < u_carbon.max_retries) {
|
||||
u_carbon.need_retry = 1;
|
||||
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
|
||||
} else {
|
||||
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
|
||||
carbon_address, u_carbon.max_retries);
|
||||
usl->healthy = 0;
|
||||
usl->errors = 0;
|
||||
}
|
||||
needs_retry = 1;
|
||||
usl->healthy = 0;
|
||||
usl->errors++;
|
||||
free(carbon_address);
|
||||
@@ -246,6 +237,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
if (u_carbon.use_metrics) goto metrics_loop;
|
||||
|
||||
unsigned long long total_rss = 0;
|
||||
unsigned long long total_vsz = 0;
|
||||
unsigned long long total_tx = 0;
|
||||
@@ -288,7 +281,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
total_busyness += worker_busyness;
|
||||
u_carbon.was_busy[i-1] = 0;
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
// only running workers are counted in total memory stats and if memory-report option is enabled
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
total_vsz += uwsgi.workers[i].vsz_size;
|
||||
@@ -301,7 +294,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -334,7 +327,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
wok = carbon_write(fd, "%s%s.%s.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -380,6 +373,18 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
metrics_loop:
|
||||
if (u_carbon.use_metrics) {
|
||||
struct uwsgi_metric *um = uwsgi.metrics;
|
||||
while(um) {
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (!wok) goto clear;
|
||||
um = um->next;
|
||||
}
|
||||
}
|
||||
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
|
||||
@@ -390,23 +395,12 @@ clear:
|
||||
nxt:
|
||||
usl = usl->next;
|
||||
}
|
||||
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
|
||||
if (u_carbon.need_retry)
|
||||
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
|
||||
u_carbon.last_update -= u_carbon.timeout;
|
||||
|
||||
return needs_retry;
|
||||
}
|
||||
|
||||
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
|
||||
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
|
||||
carbon_push_stats(1, now);
|
||||
}
|
||||
else {
|
||||
// update
|
||||
u_carbon.need_retry = 0;
|
||||
carbon_push_stats(0, now);
|
||||
|
||||
}
|
||||
uspi->needs_retry = carbon_push_stats(uspi->retries, now);
|
||||
}
|
||||
|
||||
static void carbon_cleanup() {
|
||||
|
||||
@@ -13,16 +13,18 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int cheaper_backlog2_algo(void) {
|
||||
int cheaper_backlog2_algo(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.socket_timeout;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int)uwsgi.cheaper_overload) {
|
||||
// if can_spawn == 0 we cannot spawn any new worker
|
||||
// this is set to 1 if --cheaper-rss-limit-* options are used and running workers are exceeding resources limit
|
||||
if (can_spawn && backlog > (int)uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
|
||||
@@ -13,11 +13,13 @@ struct uwsgi_cheaper_busyness_global {
|
||||
uint64_t busyness_max;
|
||||
uint64_t busyness_min;
|
||||
uint64_t *last_values;
|
||||
uint64_t *current_busyness;
|
||||
uint64_t total_avg_busyness;
|
||||
int *was_busy;
|
||||
uint64_t tcheck;
|
||||
uint64_t last_cheaped; // last time worker was cheaped due to low busyness
|
||||
uint64_t next_cheap; // timestamp, we can cheap worker after it
|
||||
uint64_t penalty; // penelty for respawning to fast, it will be added to multiplier
|
||||
uint64_t penalty; // penalty for respawning to fast, it will be added to multiplier
|
||||
uint64_t min_multi; //initial multiplier will be stored here
|
||||
uint64_t cheap_multi; // current multiplier value
|
||||
int last_action; // 1 - spawn workers ; 2 - cheap worker
|
||||
@@ -41,7 +43,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_max, 0},
|
||||
|
||||
{"cheaper-busyness-min", required_argument, 0,
|
||||
"set the cheaper busyness low percent limit, belowe that value worker is considered idle (default 25)",
|
||||
"set the cheaper busyness low percent limit, below that value worker is considered idle (default 25)",
|
||||
uwsgi_opt_set_64bit, &uwsgi_cheaper_busyness_global.busyness_min, 0},
|
||||
|
||||
{"cheaper-busyness-multiplier", required_argument, 0,
|
||||
@@ -57,7 +59,7 @@ struct uwsgi_option uwsgi_cheaper_busyness_options[] = {
|
||||
|
||||
#ifdef __linux__
|
||||
{"cheaper-busyness-backlog-alert", required_argument, 0,
|
||||
"spawn emergency worker(s) if anytime listen queue is higher than this value (default 33)",
|
||||
"spawn emergency worker(s) if any time listen queue is higher than this value (default 33)",
|
||||
uwsgi_opt_set_int, &uwsgi_cheaper_busyness_global.backlog_alert, 0},
|
||||
{"cheaper-busyness-backlog-multiplier", required_argument, 0,
|
||||
"set cheaper multiplier used for emergency workers (default 3)",
|
||||
@@ -142,52 +144,12 @@ int spawn_emergency_worker(int backlog) {
|
||||
#endif
|
||||
|
||||
|
||||
int cheaper_busyness_algo(void) {
|
||||
int cheaper_busyness_algo(int can_spawn) {
|
||||
|
||||
int i;
|
||||
// we use microseconds
|
||||
uint64_t t = uwsgi.cheaper_overload*1000000;
|
||||
|
||||
// this happens on the first run, the required memory is allocated
|
||||
if (!uwsgi_cheaper_busyness_global.last_values) {
|
||||
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
}
|
||||
if (!uwsgi_cheaper_busyness_global.was_busy) {
|
||||
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set defaults
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
|
||||
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
|
||||
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
|
||||
#endif
|
||||
|
||||
if (!uwsgi_cheaper_busyness_global.min_multi) {
|
||||
// store initial multiplier so we don't loose its initial value
|
||||
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
|
||||
// since this is first run we will print current values
|
||||
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
|
||||
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
|
||||
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
#ifdef __linux__
|
||||
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
|
||||
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
|
||||
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize with current time
|
||||
if (uwsgi_cheaper_busyness_global.tcheck == 0) uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
|
||||
|
||||
if (uwsgi_cheaper_busyness_global.next_cheap == 0) set_next_cheap_time();
|
||||
|
||||
int active_workers = 0;
|
||||
uint64_t total_busyness = 0;
|
||||
uint64_t avg_busyness = 0;
|
||||
@@ -202,7 +164,7 @@ int cheaper_busyness_algo(void) {
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
int backlog = uwsgi.shared->backlog;
|
||||
#endif
|
||||
|
||||
uint64_t now = uwsgi_micros();
|
||||
@@ -228,11 +190,21 @@ int cheaper_busyness_algo(void) {
|
||||
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
|
||||
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
|
||||
i+1, uwsgi.cheaper_overload, percent);
|
||||
if (uwsgi.has_metrics) {
|
||||
// update metrics
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.current_busyness[i] = percent;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
}
|
||||
uwsgi_cheaper_busyness_global.last_values[i] = uwsgi.workers[i+1].running_time;
|
||||
}
|
||||
|
||||
avg_busyness = (active_workers ? total_busyness / active_workers : 0);
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
uwsgi_cheaper_busyness_global.total_avg_busyness = avg_busyness;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] %ds average busyness of %d worker(s) is at %d%%\n",
|
||||
(int) uwsgi.cheaper_overload, (int) active_workers, (int) avg_busyness);
|
||||
@@ -243,11 +215,12 @@ int cheaper_busyness_algo(void) {
|
||||
uwsgi_cheaper_busyness_global.tolerance_counter = 0;
|
||||
|
||||
int decheaped = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step) break;
|
||||
if (can_spawn) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +233,7 @@ int cheaper_busyness_algo(void) {
|
||||
// worker was cheaped and then spawned back in less than current multiplier*cheaper_overload seconds
|
||||
// we will increase the multiplier so that next time worker will need to wait longer before being cheaped
|
||||
uwsgi_cheaper_busyness_global.cheap_multi += uwsgi_cheaper_busyness_global.penalty;
|
||||
uwsgi_log("[busyness] worker(s) respawned to fast, increasing chpeaper multiplier to %llu (+%llu)\n",
|
||||
uwsgi_log("[busyness] worker(s) respawned to fast, increasing cheaper multiplier to %llu (+%llu)\n",
|
||||
uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
} else {
|
||||
decrease_multi();
|
||||
@@ -271,15 +244,15 @@ int cheaper_busyness_algo(void) {
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, decheaped);
|
||||
} else {
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc);
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers available with current limits (%d)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, active_workers);
|
||||
}
|
||||
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
|
||||
#ifdef __linux__
|
||||
} else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
} else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
return spawn_emergency_worker(backlog);
|
||||
#endif
|
||||
|
||||
@@ -332,7 +305,7 @@ int cheaper_busyness_algo(void) {
|
||||
// time needed to cheap them, than a lot min<busy<max when we do not reset timer
|
||||
// and then another idle cycle than would trigger cheaping
|
||||
if (uwsgi_cheaper_busyness_global.verbose)
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), reseting cheaper timer\n",
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, %llu non-idle cycle(s), resetting cheaper timer\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, uwsgi_cheaper_busyness_global.tolerance_counter);
|
||||
set_next_cheap_time();
|
||||
} else {
|
||||
@@ -347,14 +320,14 @@ int cheaper_busyness_algo(void) {
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
// we check for backlog overload every cycle
|
||||
return spawn_emergency_worker(backlog);
|
||||
}
|
||||
else if (backlog > 0) {
|
||||
if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
|
||||
// backlog was > 0 last time, check timestamp and spawn workers if needed
|
||||
if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
|
||||
if (can_spawn && (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
|
||||
uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000);
|
||||
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
|
||||
return spawn_emergency_worker(backlog);
|
||||
@@ -384,11 +357,73 @@ void uwsgi_cheaper_register_busyness(void) {
|
||||
uwsgi_register_cheaper_algo("busyness", cheaper_busyness_algo);
|
||||
}
|
||||
|
||||
static int uwsgi_cheaper_busyness_init(void) {
|
||||
if (!uwsgi.requested_cheaper_algo || strcmp(uwsgi.requested_cheaper_algo, "busyness")) return 0;
|
||||
// this happens on the first run, the required memory is allocated
|
||||
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
// allocate metrics memory
|
||||
uwsgi_cheaper_busyness_global.current_busyness = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set defaults
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
|
||||
if (!uwsgi_cheaper_busyness_global.busyness_min) uwsgi_cheaper_busyness_global.busyness_min = 25;
|
||||
if (!uwsgi_cheaper_busyness_global.cheap_multi) uwsgi_cheaper_busyness_global.cheap_multi = 10;
|
||||
if (!uwsgi_cheaper_busyness_global.penalty) uwsgi_cheaper_busyness_global.penalty = 2;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_alert) uwsgi_cheaper_busyness_global.backlog_alert = 33;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_multi) uwsgi_cheaper_busyness_global.backlog_multi = 3;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_step) uwsgi_cheaper_busyness_global.backlog_step = 1;
|
||||
if (!uwsgi_cheaper_busyness_global.backlog_nonzero_alert) uwsgi_cheaper_busyness_global.backlog_nonzero_alert = 60;
|
||||
#endif
|
||||
|
||||
// store initial multiplier so we don't loose that value
|
||||
uwsgi_cheaper_busyness_global.min_multi = uwsgi_cheaper_busyness_global.cheap_multi;
|
||||
// since this is first run we will print current values
|
||||
uwsgi_log("[busyness] settings: min=%llu%%, max=%llu%%, overload=%llu, multiplier=%llu, respawn penalty=%llu\n",
|
||||
uwsgi_cheaper_busyness_global.busyness_min, uwsgi_cheaper_busyness_global.busyness_max,
|
||||
uwsgi.cheaper_overload, uwsgi_cheaper_busyness_global.cheap_multi, uwsgi_cheaper_busyness_global.penalty);
|
||||
#ifdef __linux__
|
||||
uwsgi_log("[busyness] backlog alert is set to %d request(s), step is %d\n",
|
||||
uwsgi_cheaper_busyness_global.backlog_alert, uwsgi_cheaper_busyness_global.backlog_step);
|
||||
uwsgi_log("[busyness] backlog non-zero alert is set to %llu second(s)\n", uwsgi_cheaper_busyness_global.backlog_nonzero_alert);
|
||||
#endif
|
||||
|
||||
// register metrics if enabled
|
||||
if (uwsgi.has_metrics) {
|
||||
int i;
|
||||
char buf[4096];
|
||||
char buf2[4096];
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
if (snprintf(buf, 4096, "worker.%d.plugin.cheaper_busyness.busyness", i+1) <= 0) {
|
||||
uwsgi_log("[busyness] unable to register busyness metric for worker %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
if (snprintf(buf2, 4096, "3.%d.100.1", i+1) <= 0) {
|
||||
uwsgi_log("[busyness] unable to register busyness metric oid for worker %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.current_busyness[i], 0, NULL);
|
||||
}
|
||||
uwsgi_register_metric("plugin.cheaper_busyness.total_avg_busyness", "4.100.1", UWSGI_METRIC_GAUGE, "ptr", &uwsgi_cheaper_busyness_global.total_avg_busyness, 0, NULL);
|
||||
uwsgi_log("[busyness] metrics registered\n");
|
||||
}
|
||||
|
||||
// initialize timers
|
||||
uwsgi_cheaper_busyness_global.tcheck = uwsgi_micros();
|
||||
set_next_cheap_time();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cheaper_busyness_plugin = {
|
||||
|
||||
.name = "cheaper_busyness",
|
||||
.on_load = uwsgi_cheaper_register_busyness,
|
||||
.on_load = uwsgi_cheaper_register_busyness,
|
||||
.options = uwsgi_cheaper_busyness_options,
|
||||
|
||||
.init = uwsgi_cheaper_busyness_init
|
||||
};
|
||||
|
||||
|
||||
@@ -187,11 +187,12 @@ void uwsgi_opt_corerouter_zerg(char *opt, char *value, void *cr) {
|
||||
|
||||
close(zerg_fd);
|
||||
|
||||
for(j=0;j<count;j++) {
|
||||
if (zerg[j] == -1) break;
|
||||
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
|
||||
ugs->zerg = optarg;
|
||||
}
|
||||
for(j=0;j<count;j++) {
|
||||
if (zerg[j] == -1) break;
|
||||
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
|
||||
ugs->zerg = optarg;
|
||||
}
|
||||
free(zerg);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,6 +272,18 @@ void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
usr->sign = val;
|
||||
usr->sign_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_key", 7, key, keylen)) {
|
||||
usr->sni_key = val;
|
||||
usr->sni_key_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_crt", 7, key, keylen)) {
|
||||
usr->sni_crt = val;
|
||||
usr->sni_crt_len = vallen;
|
||||
}
|
||||
else if (!uwsgi_strncmp("sni_ca", 6, key, keylen)) {
|
||||
usr->sni_ca = val;
|
||||
usr->sni_ca_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
|
||||
@@ -918,10 +931,13 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
|
||||
uwsgi_log("starting %s in cheap mode\n", ucr->name);
|
||||
}
|
||||
for (i = 0; i < ucr->processes; i++) {
|
||||
if (register_gateway(ucr->name, uwsgi_corerouter_loop, ucr) == NULL) {
|
||||
struct uwsgi_gateway *ug = register_gateway(ucr->name, uwsgi_corerouter_loop, ucr);
|
||||
if (ug == NULL) {
|
||||
uwsgi_log("unable to register the %s gateway\n", ucr->name);
|
||||
exit(1);
|
||||
}
|
||||
ug->uid = ucr->uid;
|
||||
ug->gid = ucr->gid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,6 +1036,9 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
if (uwsgi_stats_keyvaln_comma(us, "key", s_slot->key, s_slot->keylen)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "hash", (unsigned long long) s_slot->hash)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) s_slot->hits)) goto end0;
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi_stats_keylong_comma(us, "sni_enabled", (unsigned long long) s_slot->sni_enabled)) goto end0;
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_key(us , "nodes")) goto end0;
|
||||
if (uwsgi_stats_list_open(us)) goto end0;
|
||||
@@ -1033,9 +1052,13 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) s_node->modifier1)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier2", (unsigned long long) s_node->modifier2)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_check", (unsigned long long) s_node->last_check)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) s_node->pid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) s_node->uid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) s_node->gid)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) s_node->requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_requests", (unsigned long long) s_node->last_requests)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->transferred)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) s_node->tx)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "rx", (unsigned long long) s_node->rx)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cores", (unsigned long long) s_node->cores)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) s_node->load)) goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "weight", (unsigned long long) s_node->weight)) goto end0;
|
||||
@@ -1075,7 +1098,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.socket_timeout);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
|
||||
@@ -29,6 +30,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;\
|
||||
ubuf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
@@ -51,6 +53,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_read_exact(peer, l, f) read(peer->fd, peer->in->buf + peer->in->pos, (l - peer->in->pos));\
|
||||
@@ -59,6 +62,7 @@
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->tx+=len;\
|
||||
peer->in->pos += len;\
|
||||
|
||||
#define cr_reset_hooks(peer) if(!peer->session->main_peer->disabled) {\
|
||||
@@ -258,6 +262,9 @@ struct uwsgi_corerouter {
|
||||
|
||||
uint64_t active_sessions;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
};
|
||||
|
||||
// a session is started when a client connect to the router
|
||||
|
||||
@@ -4,7 +4,7 @@ common functions for various routers (fastrouter, http...)
|
||||
|
||||
*/
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -79,6 +79,9 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
}
|
||||
else {
|
||||
ugs->fd = bind_to_unix_dgram(ugs->name);
|
||||
if (ugs->fd < 1 || (uwsgi.subscriptions_use_credentials && uwsgi_socket_passcred(ugs->fd))) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
}
|
||||
@@ -113,10 +116,17 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
int i;
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
ssize_t len = -1;
|
||||
|
||||
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
|
||||
if (uwsgi.subscriptions_use_credentials) {
|
||||
len = uwsgi_recv_cred2(ugs->fd, bbuf, 4096, &usr.pid, &usr.uid, &usr.gid);
|
||||
}
|
||||
else {
|
||||
len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
}
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
|
||||
if (usr.sign_len > 0) {
|
||||
// calc the base size
|
||||
|
||||
+41
-12
@@ -12,8 +12,8 @@ static void uwsgi_opt_setup_coroae(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi.socket_timeout = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "coroae";
|
||||
@@ -51,7 +51,7 @@ SV * coroae_coro_new(CV *block) {
|
||||
XPUSHs(sv_2mortal(newSVpv( "Coro", 4)));
|
||||
XPUSHs(newRV_inc((SV *)block));
|
||||
PUTBACK;
|
||||
call_method("new", G_SCALAR);
|
||||
call_method("new", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
@@ -65,6 +65,33 @@ SV * coroae_coro_new(CV *block) {
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static int coroae_wait_milliseconds(int timeout) {
|
||||
int ret = -1;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(newSVnv(((double)timeout)/1000.0));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
int ret = 0;
|
||||
dSP;
|
||||
@@ -74,7 +101,7 @@ static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
XPUSHs(newSViv(fd));
|
||||
XPUSHs(newSViv(timeout));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::readable", G_SCALAR);
|
||||
call_pv("Coro::AnyEvent::readable", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
@@ -101,13 +128,14 @@ static int coroae_wait_fd_write(int fd, int timeout) {
|
||||
XPUSHs(sv_2mortal(newSViv(fd)));
|
||||
XPUSHs(sv_2mortal(newSViv(timeout)));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::writable", G_SCALAR);
|
||||
call_pv("Coro::AnyEvent::writable", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
if (SvTRUE(POPs)) {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
@@ -136,7 +164,7 @@ XS(XS_coroae_accept_request) {
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -216,8 +244,8 @@ edge:
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +303,7 @@ static SV *coroae_add_watcher(int fd, SV *cb) {
|
||||
XPUSHs(newRV_inc(cb));
|
||||
PUTBACK;
|
||||
|
||||
call_method( "io", G_SCALAR);
|
||||
call_method( "io", G_SCALAR|G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
@@ -306,7 +334,7 @@ static SV *coroae_condvar_new() {
|
||||
XPUSHs(sv_2mortal(newSVpv( "AnyEvent", 8)));
|
||||
PUTBACK;
|
||||
|
||||
call_method( "condvar", G_SCALAR);
|
||||
call_method( "condvar", G_SCALAR|G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
@@ -332,7 +360,7 @@ static void coroae_wait_condvar(SV *cv) {
|
||||
XPUSHs(cv);
|
||||
PUTBACK;
|
||||
|
||||
call_method( "recv", G_DISCARD);
|
||||
call_method( "recv", G_DISCARD|G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
@@ -377,6 +405,7 @@ static void coroae_loop() {
|
||||
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = coroae_wait_fd_write;
|
||||
uwsgi.wait_read_hook = coroae_wait_fd_read;
|
||||
uwsgi.wait_milliseconds_hook = coroae_wait_milliseconds;
|
||||
|
||||
I_CORO_API("uwsgi::coroae");
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ if not coroapi:
|
||||
|
||||
NAME='coroae'
|
||||
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
|
||||
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
|
||||
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=format', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, uc->command);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
// use 1 minute as the cron resolution
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
|
||||
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
// the connection object (will be automatically destroyed at each cycle)
|
||||
mongo::DBClientConnection c;
|
||||
// set the socket timeout
|
||||
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
c.setSoTimeout(uwsgi.socket_timeout);
|
||||
// connect
|
||||
c.connect(uems->address);
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ s.send_multipart(['touch','foo.ini',"[uwsgi]\nsocket=:4142"])
|
||||
|
||||
*/
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <zmq.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -166,7 +164,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
}
|
||||
}
|
||||
// destroy an instance
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) {
|
||||
struct uwsgi_instance *ui = emperor_get(name);
|
||||
if (!ui) {
|
||||
uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name);
|
||||
@@ -215,7 +213,11 @@ static void uwsgi_imperial_monitor_zeromq_event(struct uwsgi_emperor_scanner *ue
|
||||
// initialize the zmq PULL socket
|
||||
static void uwsgi_imperial_monitor_zeromq_init(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
void *context = uwsgi_zeromq_init();
|
||||
void *context = zmq_init(1);
|
||||
if (!context) {
|
||||
uwsgi_error("uwsgi_imperial_monitor_zeromq_init()/zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ues->data = zmq_socket(context, ZMQ_PULL);
|
||||
if (!ues->data) {
|
||||
@@ -256,7 +258,3 @@ struct uwsgi_plugin emperor_zeromq_plugin = {
|
||||
.name = "emperor_zeromq",
|
||||
.on_load = emperor_zeromq_init,
|
||||
};
|
||||
|
||||
#else
|
||||
#error the uWSGI ZeroMQ imperial monitor requires uWSGI zeromq support
|
||||
#endif
|
||||
|
||||
@@ -1,441 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include "erlang.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_erlang uerl;
|
||||
|
||||
struct uwsgi_option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
|
||||
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
void dump_eterm(ei_x_buff *x) {
|
||||
|
||||
int etype, esize, arity;
|
||||
long long num;
|
||||
char *atom;
|
||||
int i;
|
||||
char *binary;
|
||||
long bin_size;
|
||||
double fnum;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("etype: %d/%c esize: %d\n", etype, etype, esize);
|
||||
|
||||
switch(etype) {
|
||||
case ERL_SMALL_INTEGER_EXT:
|
||||
case ERL_INTEGER_EXT:
|
||||
case ERL_SMALL_BIG_EXT:
|
||||
case ERL_LARGE_BIG_EXT:
|
||||
ei_decode_longlong(x->buff, &x->index, &num);
|
||||
uwsgi_log("num: %lu\n", num);
|
||||
break;
|
||||
case ERL_FLOAT_EXT:
|
||||
ei_decode_double(x->buff, &x->index, &fnum);
|
||||
uwsgi_log("float: %f\n", fnum);
|
||||
break;
|
||||
case ERL_STRING_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, atom);
|
||||
uwsgi_log("string: %s\n", atom);
|
||||
free(atom);
|
||||
break;
|
||||
case ERL_ATOM_EXT:
|
||||
atom = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, atom);
|
||||
uwsgi_log("atom: %s\n", atom);
|
||||
free(atom);
|
||||
break;
|
||||
case ERL_SMALL_TUPLE_EXT:
|
||||
case ERL_LARGE_TUPLE_EXT:
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
for(i=0;i<arity;i++) {
|
||||
dump_eterm(x);
|
||||
}
|
||||
break;
|
||||
case ERL_LIST_EXT:
|
||||
case ERL_NIL_EXT:
|
||||
ei_decode_list_header(x->buff, &x->index, &arity);
|
||||
if (arity == 0) {
|
||||
uwsgi_log("nil value\n");
|
||||
break;
|
||||
}
|
||||
for(i=0;i<arity+1;i++) {
|
||||
dump_eterm(x);
|
||||
}
|
||||
break;
|
||||
case ERL_BINARY_EXT:
|
||||
binary = uwsgi_malloc(esize);
|
||||
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
|
||||
uwsgi_log("binary data of %d bytes\n", bin_size);
|
||||
free(binary);
|
||||
break;
|
||||
default:
|
||||
uwsgi_log("ignored...\n");
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
int etype, esize;
|
||||
int arity;
|
||||
|
||||
char *gen_call;
|
||||
char *module;
|
||||
char *call;
|
||||
char buffer[0xffff];
|
||||
|
||||
char *argv[256] ;
|
||||
uint16_t argvs[256] ;
|
||||
int argc = 0;
|
||||
uint16_t ret;
|
||||
ei_x_buff xr;
|
||||
|
||||
erlang_ref eref;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
|
||||
#endif
|
||||
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("rpc arity %d\n", arity);
|
||||
#endif
|
||||
if (arity != 3) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
gen_call = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, gen_call);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, gen_call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("gen call = %s\n", gen_call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
if (arity != 2) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_decode_ref(x->buff, &x->index, &eref);
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, module);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, module);
|
||||
}
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arity: %d\n", arity);
|
||||
#endif
|
||||
if (arity != 5) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
char *method = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, method);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, method);
|
||||
}
|
||||
|
||||
if (strcmp(method, "call")) return;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, module);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, module);
|
||||
}
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
call = uwsgi_malloc(esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
ei_decode_atom(x->buff, &x->index, call);
|
||||
}
|
||||
else {
|
||||
ei_decode_string(x->buff, &x->index, call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("RPC %s %s\n", module, call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
if (etype == ERL_ATOM_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
else if (etype == ERL_STRING_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
|
||||
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("buffer: %.*s\n", ret, buffer);
|
||||
#endif
|
||||
|
||||
ei_x_new_with_version(&xr);
|
||||
|
||||
ei_x_encode_tuple_header(&xr, 2);
|
||||
//ei_x_encode_atom(&xr, "rex");
|
||||
ei_x_encode_ref(&xr, &eref);
|
||||
ei_x_encode_string_len(&xr, buffer, ret);
|
||||
|
||||
uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index));
|
||||
//uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void erlang_loop(int id, void *data) {
|
||||
|
||||
ErlConnect econn;
|
||||
//ErlMessage em;
|
||||
erlang_msg em;
|
||||
int fd;
|
||||
|
||||
int eversion;
|
||||
|
||||
ei_x_buff x, xr;
|
||||
|
||||
ei_x_new(&x);
|
||||
ei_x_new(&xr);
|
||||
|
||||
|
||||
/*
|
||||
int fd0 = ei_connect(&uerl.cnode, "anothernode@maverick64");
|
||||
uwsgi_log("fd0: %d\n", fd0);
|
||||
|
||||
ei_x_encode_list_header(&x, 0);
|
||||
|
||||
ei_rpc_to(&uerl.cnode, fd0, "erlang", "node", x.buff, x.index);
|
||||
|
||||
ei_rpc_from(&uerl.cnode, fd0, 10000, &em, &xr);
|
||||
|
||||
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
|
||||
|
||||
xr.index = 0;
|
||||
ei_decode_version(xr.buff, &xr.index, &eversion);
|
||||
uwsgi_log("eversion: %d\n", eversion);
|
||||
|
||||
dump_eterm(&xr);
|
||||
*/
|
||||
|
||||
for(;;) {
|
||||
|
||||
fd = ei_accept(&uerl.cnode, uerl.fd, &econn);
|
||||
|
||||
if (fd >= 0) {
|
||||
|
||||
for (;;) {
|
||||
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
|
||||
|
||||
if (em.msgtype == ERL_TICK)
|
||||
continue;
|
||||
|
||||
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
|
||||
|
||||
|
||||
|
||||
x.index = 0;
|
||||
ei_decode_version(x.buff, &x.index, &eversion);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("eversion: %d\n", eversion);
|
||||
#endif
|
||||
|
||||
if (!strcmp(em.toname, "rex")) {
|
||||
uwsgi_erlang_rpc(fd, &em.from, &x);
|
||||
}
|
||||
else {
|
||||
struct uwsgi_erlang_process *uep = uerl.uep;
|
||||
while(uep) {
|
||||
if (!strcmp(uep->name, em.toname)) {
|
||||
if (uep->plugin) {
|
||||
uep->plugin(uep->func, &x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
if (!uep) {
|
||||
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
|
||||
dump_eterm(&x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
if (em.msgtype) {
|
||||
dump_erl_obj(em.msg);
|
||||
erl_free_compound(em.msg);
|
||||
}
|
||||
if (em.to) {
|
||||
uwsgi_log("*** TO ***\n");
|
||||
dump_erl_obj(em.to);
|
||||
erl_free_compound(em.to);
|
||||
}
|
||||
|
||||
if (em.from) {
|
||||
uwsgi_log("*** FROM ***\n");
|
||||
dump_erl_obj(em.from);
|
||||
erl_free_compound(em.from);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int erlang_init() {
|
||||
|
||||
char *host;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t slen = sizeof(struct sockaddr_in);
|
||||
char *ip = NULL;
|
||||
char *nodename;
|
||||
struct in_addr addr;
|
||||
|
||||
uerl.lock = uwsgi_lock_init("erlang");
|
||||
|
||||
if (uerl.name) {
|
||||
|
||||
|
||||
host = strchr(uerl.name, '@');
|
||||
|
||||
if (!host) {
|
||||
if (ei_connect_init(&uerl.cnode, uerl.name, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0);
|
||||
ip = uwsgi_resolve_ip(host+1);
|
||||
if (ip) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("ip: %s\n", ip);
|
||||
#endif
|
||||
addr.s_addr = inet_addr(ip);
|
||||
if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) {
|
||||
uwsgi_log("unable to initialize erlang connection\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
free(nodename);
|
||||
}
|
||||
|
||||
if (ip) {
|
||||
uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL);
|
||||
}
|
||||
else {
|
||||
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
|
||||
}
|
||||
|
||||
if (uerl.fd < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (getsockname(uerl.fd, (struct sockaddr *) &sin, &slen)) {
|
||||
uwsgi_error("getsockname()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ei_publish(&uerl.cnode, ntohs(sin.sin_port)) < 0) {
|
||||
uwsgi_log( "*** unable to subscribe with EPMD ***\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin erlang_plugin = {
|
||||
|
||||
.name = "erlang",
|
||||
.options = erlang_options,
|
||||
.init = erlang_init,
|
||||
};
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#include <ei.h>
|
||||
|
||||
struct uwsgi_erlang_process {
|
||||
|
||||
char name[0xff];
|
||||
void (*plugin)(void *, ei_x_buff *);
|
||||
void *func;
|
||||
|
||||
struct uwsgi_erlang_process *next;
|
||||
};
|
||||
|
||||
struct uwsgi_erlang {
|
||||
|
||||
ei_cnode cnode;
|
||||
char *name;
|
||||
char *cookie;
|
||||
|
||||
int fd;
|
||||
|
||||
void *lock;
|
||||
|
||||
struct uwsgi_erlang_process *uep;
|
||||
};
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import os
|
||||
|
||||
NAME='erlang'
|
||||
|
||||
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
|
||||
|
||||
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
|
||||
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
|
||||
|
||||
CFLAGS = [ '-I' + includedir ]
|
||||
LDFLAGS = [ '-L' + libpath ]
|
||||
|
||||
LIBS = ['-lei']
|
||||
|
||||
GCC_LIST = ['erlang']
|
||||
@@ -190,21 +190,23 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
// called after receaving the uwsgi header (read vars)
|
||||
static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf;
|
||||
// better to store it as the original buf address could change
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, uh->pktsize+4))
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4))
|
||||
return -1;
|
||||
ssize_t len = cr_read_exact(main_peer, uh->pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
|
||||
// headers received, ready to choose the instance
|
||||
if (main_peer->in->pos == (size_t)(uh->pktsize+4)) {
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4)) {
|
||||
struct uwsgi_corerouter *ucr = main_peer->session->corerouter;
|
||||
|
||||
struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer->last_hook_read = fr_instance_read;
|
||||
|
||||
// find the hostname
|
||||
if (uwsgi_hooked_parse(main_peer->in->buf+4, uh->pktsize, fr_get_hostname, (void *) new_peer)) {
|
||||
if (uwsgi_hooked_parse(main_peer->in->buf+4, pktsize, fr_get_hostname, (void *) new_peer)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
uWSGI forkpty-router
|
||||
|
||||
can use the uwsgi protocol, modifier2 means:
|
||||
|
||||
0 -> stdin
|
||||
1-99 -> UNIX signal
|
||||
100 -> window rows (pktsize is the window size)
|
||||
101 -> window cols (pktsize is the window size)
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
@@ -9,9 +16,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
#include <pty.h>
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#include <util.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <libutil.h>
|
||||
@@ -24,22 +31,45 @@ extern struct uwsgi_server uwsgi;
|
||||
static struct uwsgi_forkptyrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
char *cmd;
|
||||
uint16_t win_rows;
|
||||
uint16_t win_cols;
|
||||
} ufpty;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct forkptyrouter_session {
|
||||
struct corerouter_session session;
|
||||
// use the uwsgi protocol ?
|
||||
int uwsgi;
|
||||
size_t restore_size;
|
||||
struct winsize w;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static void uwsgi_opt_forkpty_urouter(char *opt, char *value, void *cr) {
|
||||
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, ucr->name);
|
||||
ugs->no_defer = 1;
|
||||
ugs->mode = 1;
|
||||
ucr->has_sockets++;
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option forkptyrouter_options[] = {
|
||||
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
|
||||
{"forkptyurouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
|
||||
{"forkpty-urouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
|
||||
|
||||
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
|
||||
{"forkptyrouter-rows", required_argument, 0, "set forkptyrouter default pty window rows", uwsgi_opt_set_16bit, &ufpty.win_rows, 0},
|
||||
{"forkptyrouter-cols", required_argument, 0, "set forkptyrouter default pty window cols", uwsgi_opt_set_16bit, &ufpty.win_cols, 0},
|
||||
|
||||
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
|
||||
@@ -61,6 +91,7 @@ static struct uwsgi_option forkptyrouter_options[] = {
|
||||
|
||||
// write to backend
|
||||
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
ssize_t len = cr_write(peer, "fpty_instance_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
@@ -68,7 +99,13 @@ static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
// the chunk has been sent, start (again) reading from client and instances
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the buffer
|
||||
peer->out->pos = 0;
|
||||
if (fpty_session->uwsgi) {
|
||||
if (uwsgi_buffer_decapitate(peer->out, peer->out->pos)) return -1;
|
||||
peer->out->pos = fpty_session->restore_size;
|
||||
}
|
||||
else {
|
||||
peer->out->pos = 0;
|
||||
}
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
|
||||
@@ -91,6 +128,42 @@ static ssize_t fpty_write(struct corerouter_peer *main_peer) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t fpty_parse_uwsgi(struct corerouter_peer *peer) {
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
for(;;) {
|
||||
if (peer->in->pos < 4) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) peer->in->buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
switch(uh->modifier2) {
|
||||
case 0:
|
||||
// stdin
|
||||
if ((size_t) (pktsize+4) > peer->in->pos) return 0;
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
return pktsize;
|
||||
case 100:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_row = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// rows
|
||||
break;
|
||||
case 101:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_col = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// cols
|
||||
break;
|
||||
default:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
// send signal
|
||||
kill(fpty_session->pid, uh->modifier2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from backend
|
||||
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_read(peer, "fpty_instance_read()");
|
||||
@@ -106,10 +179,22 @@ static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
|
||||
// read from client
|
||||
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) main_peer->session;
|
||||
ssize_t len = cr_read(main_peer, "fpty_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
if (fpty_session->uwsgi) {
|
||||
ssize_t rlen = fpty_parse_uwsgi(main_peer);
|
||||
if (rlen < 0) return -1;
|
||||
if (rlen == 0) return 1;
|
||||
|
||||
fpty_session->restore_size = main_peer->in->pos - rlen;
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
main_peer->session->peers->out->pos = rlen;
|
||||
}
|
||||
else {
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
}
|
||||
main_peer->session->peers->out_pos = 0;
|
||||
|
||||
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
|
||||
@@ -137,12 +222,19 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
|
||||
cs->close = fpty_session_close;
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
if (ugs->mode == 1) {
|
||||
fpty_session->uwsgi = 1;
|
||||
}
|
||||
|
||||
// default terminal size
|
||||
fpty_session->w.ws_row = ufpty.win_rows ? ufpty.win_rows : 24;
|
||||
fpty_session->w.ws_col = ufpty.win_cols ? ufpty.win_cols : 80;
|
||||
|
||||
// add a new peer
|
||||
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
|
||||
|
||||
// on new connection generate a new pty
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, NULL);
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
|
||||
if (fpty_session->pid < 0) {
|
||||
uwsgi_error("forkpty()");
|
||||
return -1;
|
||||
@@ -156,23 +248,23 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
|
||||
argv[1] = "-c";
|
||||
argv[2] = ufpty.cmd;
|
||||
argv[3] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = ufpty.cmd;
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
// never here;
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execve()");
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execv()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
+271
-13
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
|
||||
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
|
||||
Soon before official Go 1.1, we understood supporting Go in a fork() heavy
|
||||
environment was not blessed by the Go community.
|
||||
|
||||
Instead of completely dropping support for Go, we studied how the gccgo project works and we
|
||||
@@ -16,8 +16,31 @@
|
||||
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
|
||||
manages mules, spoolers and workers)
|
||||
|
||||
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
|
||||
from your apps are native goroutines)
|
||||
The plugin implements goroutines too.
|
||||
|
||||
On startup a goroutine is created for each socket and signals file descriptors.
|
||||
|
||||
For every request a new goroutine is created too.
|
||||
|
||||
The wsgi_request * structure is attached to the "closure" field of the goroutine (PAY ATTENTION)
|
||||
|
||||
even if the loop engine makes use of the async mode, pthreads could be spawned all over the place.
|
||||
For such a reason a mutex is created avoiding the global wsgi_req structures to be clobbered
|
||||
|
||||
Contrary to the standard way Go apps are deployed, the plugin supports loading shared libraries.
|
||||
While this is a common approach in other environments, the Go community prefers monolithic binaries.
|
||||
|
||||
As always, choose the model that best suite for you. Eventually building a single uWSGI binary with your Go
|
||||
app embedded is pretty easy:
|
||||
|
||||
|
||||
CFLAGS=-DUWSGI_GCCGO_MONOLITHIC UWSGI_ADDITIONAL_SOURCES=t/go/uploadtest.go UWSGI_PROFILE=gccgo make
|
||||
|
||||
or you can add the following two directives in a build profile:
|
||||
|
||||
cflags = -DUWSGI_GCCGO_MONOLITHIC
|
||||
additional_sources = t/go/uploadtest.go
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -25,25 +48,29 @@ extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin gccgo_plugin;
|
||||
|
||||
struct uwsgi_gccgo{
|
||||
// 1 if a main is loaded
|
||||
int initialized;
|
||||
struct uwsgi_string_list *libs;
|
||||
char *args;
|
||||
pthread_mutex_t wsgi_req_lock;
|
||||
} ugccgo;
|
||||
|
||||
/*
|
||||
shortcut for enabling the "goroutines" loop engine
|
||||
*/
|
||||
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
*/
|
||||
|
||||
struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of max goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -51,27 +78,46 @@ struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
// no_split_stack is the key to avoid crashing !!!
|
||||
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
|
||||
|
||||
// initialize runtime
|
||||
void runtime_check(void);
|
||||
void runtime_args(int, char **);
|
||||
void runtime_osinit(void);
|
||||
void runtime_schedinit(void);
|
||||
void *__go_go(void *, void *);
|
||||
void runtime_main(void);
|
||||
void runtime_mstart(void *);
|
||||
|
||||
// spawn a goroutine
|
||||
void *__go_go(void *, void *);
|
||||
|
||||
// api functions exposed
|
||||
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
|
||||
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
|
||||
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
|
||||
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
|
||||
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
|
||||
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
|
||||
|
||||
// for goroutines
|
||||
void runtime_netpollinit(void);
|
||||
void runtime_starttheworld(void);
|
||||
void *runtime_pollOpen(int) __asm__ ("net.runtime_pollOpen");
|
||||
void runtime_pollClose(void *) __asm__ ("net.runtime_pollClose");
|
||||
void runtime_pollUnblock(void *) __asm__ ("net.runtime_pollUnblock");
|
||||
int runtime_pollWait(void *, int) __asm__ ("net.runtime_pollWait");
|
||||
void runtime_pollSetDeadline(void *, int64_t, int) __asm__ ("net.runtime_pollSetDeadline");
|
||||
void runtime_gosched(void);
|
||||
// the current goroutine
|
||||
void *runtime_g(void);
|
||||
// we use the closure field to store the wsgi_req structure
|
||||
void __go_set_closure(void *);
|
||||
void *__go_get_closure(void);
|
||||
|
||||
static void mainstart(void *arg __attribute__((unused))) {
|
||||
runtime_main();
|
||||
}
|
||||
|
||||
#ifndef UWSGI_GCCGO_MONOLITHIC
|
||||
void uwsgigo_main_main(void) __asm__ ("main.main");
|
||||
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
|
||||
#endif
|
||||
|
||||
void (*uwsgigo_hook_init)(void);
|
||||
void (*uwsgigo_hook_main)(void);
|
||||
@@ -102,6 +148,14 @@ int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *han
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_initialize() {
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_log("!!! the Go runtime cannot work in multithreaded modes !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef UWSGI_GCCGO_MONOLITHIC
|
||||
uwsgigo_hook_init = dlsym(RTLD_DEFAULT, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(RTLD_DEFAULT, "main.main");
|
||||
#endif
|
||||
struct uwsgi_string_list *usl = ugccgo.libs;
|
||||
while(usl) {
|
||||
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
@@ -109,9 +163,16 @@ static void uwsgi_gccgo_initialize() {
|
||||
uwsgi_log("unable to open go shared library: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(handle, "main.main");
|
||||
void *g_init = dlsym(handle, "__go_init_main");
|
||||
void *g_main = dlsym(handle, "main.main");
|
||||
if (g_init && g_main) {
|
||||
uwsgigo_hook_init = g_init;
|
||||
uwsgigo_hook_main = g_main;
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s as main\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -119,6 +180,8 @@ static void uwsgi_gccgo_initialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
ugccgo.initialized = 1;
|
||||
|
||||
// Go runtime initialization
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
@@ -131,7 +194,7 @@ static void uwsgi_gccgo_initialize() {
|
||||
}
|
||||
runtime_check();
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 2));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p, *ctx = NULL;
|
||||
int n = 0;
|
||||
@@ -145,6 +208,7 @@ static void uwsgi_gccgo_initialize() {
|
||||
char *argv[2] = {0,0};
|
||||
runtime_args(0, argv);
|
||||
}
|
||||
|
||||
runtime_osinit();
|
||||
runtime_schedinit();
|
||||
__go_go(mainstart, NULL);
|
||||
@@ -153,6 +217,10 @@ static void uwsgi_gccgo_initialize() {
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
if (!ugccgo.initialized) {
|
||||
uwsgi_log("!!! Go runtime not initialized !!!\n");
|
||||
goto end;
|
||||
}
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
@@ -170,6 +238,7 @@ static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
i++;
|
||||
}
|
||||
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
|
||||
end:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -178,15 +247,204 @@ static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
|
||||
if (!ugccgo.initialized) return -1;
|
||||
uwsgigo_signal_handler(handler, signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define free_req_queue pthread_mutex_lock(&ugccgo.wsgi_req_lock);uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req; pthread_mutex_unlock(&ugccgo.wsgi_req_lock)
|
||||
|
||||
static void uwsgi_gccgo_request_goroutine(void *arg) {
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg;
|
||||
|
||||
// map wsgi_req to the goroutine
|
||||
__go_set_closure(wsgi_req);
|
||||
|
||||
int ret,status;
|
||||
|
||||
for(;;) {
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
retry:
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto end;
|
||||
}
|
||||
else if (status == 0) {
|
||||
break;
|
||||
}
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
// yield
|
||||
runtime_gosched();
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_close_request(wsgi_req);
|
||||
free_req_queue;
|
||||
}
|
||||
|
||||
static struct wsgi_request *uwsgi_gccgo_current_wsgi_req(void) {
|
||||
return (struct wsgi_request *) __go_get_closure();
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_wait_read_hook(int fd, int timeout) {
|
||||
void *pdesc = runtime_pollOpen(fd);
|
||||
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
|
||||
runtime_pollSetDeadline(pdesc, t, 'r');
|
||||
int ret = runtime_pollWait(pdesc, 'r');
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
if (ret == 0) return 1;
|
||||
// timeout
|
||||
if (ret == 2) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_wait_write_hook(int fd, int timeout) {
|
||||
void *pdesc = runtime_pollOpen(fd);
|
||||
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
|
||||
runtime_pollSetDeadline(pdesc, t, 'w');
|
||||
int ret = runtime_pollWait(pdesc, 'w');
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
if (ret == 0) return 1;
|
||||
// timeout
|
||||
if (ret == 2) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
this goroutine manages signals
|
||||
*/
|
||||
static void uwsgi_gccgo_signal_goroutine(void *arg) {
|
||||
int *fd = (int *) arg;
|
||||
void *pdesc = runtime_pollOpen(*fd);
|
||||
for(;;) {
|
||||
runtime_pollWait(pdesc, 'r');
|
||||
retry:
|
||||
uwsgi_receive_signal(*fd, "worker", uwsgi.mywid);
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_socket_goroutine(void *arg) {
|
||||
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) arg;
|
||||
struct wsgi_request *wsgi_req = NULL;
|
||||
void *pdesc = runtime_pollOpen(uwsgi_sock->fd);
|
||||
// wait for connection
|
||||
for(;;) {
|
||||
runtime_pollWait(pdesc, 'r');
|
||||
retry:
|
||||
pthread_mutex_lock(&ugccgo.wsgi_req_lock);
|
||||
wsgi_req = find_first_available_wsgi_req();
|
||||
pthread_mutex_unlock(&ugccgo.wsgi_req_lock);
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
uwsgi_async_queue_is_full(uwsgi_now());
|
||||
// try rescheduling...
|
||||
// we do not use runtime_gosched() as we want to call the netpoll loop too
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
pdesc = runtime_pollOpen(uwsgi_sock->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
free_req_queue;
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
// spawn the new goroutine
|
||||
__go_go(uwsgi_gccgo_request_goroutine, wsgi_req);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_loop() {
|
||||
if (!ugccgo.initialized) {
|
||||
uwsgi_log("no go.main code loaded !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
// initialize the log protecting the wsgi_req structures
|
||||
pthread_mutex_init(&ugccgo.wsgi_req_lock, NULL);
|
||||
|
||||
// hooks
|
||||
uwsgi.current_wsgi_req = uwsgi_gccgo_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = uwsgi_gccgo_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_gccgo_wait_read_hook;
|
||||
|
||||
// ininitialize Go I/O loop
|
||||
runtime_netpollinit();
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.signal_socket);
|
||||
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.my_signal_socket);
|
||||
}
|
||||
|
||||
// start a goroutine for each socket
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (!uwsgi_sock->next) {
|
||||
uwsgi_gccgo_socket_goroutine(uwsgi_sock);
|
||||
}
|
||||
else {
|
||||
__go_go(uwsgi_gccgo_socket_goroutine, uwsgi_sock);
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_on_load() {
|
||||
uwsgi_register_loop( (char *) "go", uwsgi_gccgo_loop);
|
||||
uwsgi_register_loop( (char *) "goroutine", uwsgi_gccgo_loop);
|
||||
uwsgi_register_loop( (char *) "goroutines", uwsgi_gccgo_loop);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin gccgo_plugin = {
|
||||
.name = "gccgo",
|
||||
.modifier1 = 11,
|
||||
.options = uwsgi_gccgo_options,
|
||||
//.on_load = uwsgi_gccgo_on_load,
|
||||
.on_load = uwsgi_gccgo_on_load,
|
||||
.request = uwsgi_gccgo_request,
|
||||
.after_request = uwsgi_gccgo_after_request,
|
||||
.post_fork = uwsgi_gccgo_initialize,
|
||||
|
||||
+45
-2
@@ -1,5 +1,12 @@
|
||||
package uwsgi
|
||||
|
||||
/*
|
||||
|
||||
this is a very low-level module, full of performance hacks
|
||||
do not take it as a good example of go coding...
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/http"
|
||||
@@ -20,17 +27,27 @@ func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
|
||||
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_gccgo_helper_register_signal
|
||||
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
|
||||
//extern uwsgi_cache_magic_get
|
||||
func uwsgi_cache_magic_get(*byte, uint16, *uint64, *uint64, *byte) *byte;
|
||||
//extern __go_byte_array_to_string
|
||||
func __go_byte_array_to_string(*byte, int) string
|
||||
//extern free
|
||||
func free(* byte)
|
||||
|
||||
var uwsgi_signals_gc [256]func(uint8)
|
||||
var uwsgi_env_gc map[interface{}]interface{}
|
||||
|
||||
func Env(wsgi_req *interface{}) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
uwsgi_env_gc[wsgi_req] = &env
|
||||
return &env
|
||||
}
|
||||
|
||||
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
|
||||
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
|
||||
func EnvAdd(env *map[string]string, k *byte, kl uint16, v *byte, vl uint16) {
|
||||
s_k := __go_byte_array_to_string(k, int(kl))
|
||||
s_v := __go_byte_array_to_string(v, int(vl))
|
||||
(*env)[ s_k ] = s_v
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
@@ -98,9 +115,13 @@ func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
delete(uwsgi_env_gc, wsgi_req)
|
||||
}
|
||||
|
||||
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
if (receiver == "") {
|
||||
receiver = "worker"
|
||||
}
|
||||
var b []byte = []byte(receiver)
|
||||
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
|
||||
return false
|
||||
@@ -109,10 +130,32 @@ func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// get an item from the cache
|
||||
func CacheGet(key string, cache string) string {
|
||||
|
||||
var b_key []byte = []byte(key)
|
||||
var v_len uint64 = 0
|
||||
var expires uint64 = 0
|
||||
var value *byte
|
||||
|
||||
if (cache == "") {
|
||||
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, nil)
|
||||
} else {
|
||||
b_cache := []byte(cache)
|
||||
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, &b_cache[0])
|
||||
}
|
||||
|
||||
ret := __go_byte_array_to_string(value, int(v_len))
|
||||
free(value)
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
func SignalHandler(handler func(uint8), signum uint8) {
|
||||
handler(signum)
|
||||
}
|
||||
|
||||
func Run() {
|
||||
uwsgi_env_gc = make(map[interface{}]interface{})
|
||||
uwsgi_takeover()
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user