mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7108ee1ba0 | ||
|
|
cf8e68f7a0 | ||
|
|
a9510c2209 | ||
|
|
b2be5943a8 | ||
|
|
8f19fe292e | ||
|
|
d3e7668d0a | ||
|
|
88e67a74e5 | ||
|
|
7fecda1a23 | ||
|
|
56b6fa88f9 | ||
|
|
e847cfe4bc | ||
|
|
1a854ae3ba | ||
|
|
c75180bf95 | ||
|
|
d496450b84 | ||
|
|
d2636ed133 | ||
|
|
59de0c2085 | ||
|
|
4b7df29bd1 | ||
|
|
b099ba6a29 | ||
|
|
164069e194 | ||
|
|
b3e4ff8613 | ||
|
|
3eb5ec3543 | ||
|
|
c3c698a615 | ||
|
|
ac6d2f3e83 | ||
|
|
d1f1b8a43a | ||
|
|
85586a621c | ||
|
|
1a384a334f | ||
|
|
8901afded5 | ||
|
|
ab12703a11 | ||
|
|
9992b4c964 | ||
|
|
9a2dbd08cd | ||
|
|
5f92a00b71 | ||
|
|
7bd9d51217 | ||
|
|
80c649aa40 | ||
|
|
6c8fe2cc53 | ||
|
|
dcc7167d75 | ||
|
|
e3a52e4039 | ||
|
|
498f6162f7 | ||
|
|
33d85d3670 | ||
|
|
afbf5b9633 | ||
|
|
a8505be6c0 | ||
|
|
4a07632569 | ||
|
|
d4f0589c39 | ||
|
|
a9989d46fc | ||
|
|
99cf598c0c | ||
|
|
a6af22b8f0 | ||
|
|
0961d61a88 | ||
|
|
7b76a2d749 | ||
|
|
b516f1d3ec | ||
|
|
8fdef7a1f9 | ||
|
|
10258db4ae | ||
|
|
621c9523cf | ||
|
|
c415adab28 | ||
|
|
7fef1048b3 | ||
|
|
1e7aaeeeed | ||
|
|
c5b4564001 | ||
|
|
a9127c8d79 | ||
|
|
a0f7a5c70f | ||
|
|
ecf3cae35b | ||
|
|
d553bc8014 | ||
|
|
a1553d3632 | ||
|
|
bb42ae1b4a | ||
|
|
61ac2efe0e | ||
|
|
1c0a3ec413 | ||
|
|
8b7e93385b | ||
|
|
c742624054 | ||
|
|
8011f0615d | ||
|
|
8096b2198f | ||
|
|
3556bd5283 | ||
|
|
26710694af | ||
|
|
0f397eeb55 | ||
|
|
bf929398a9 | ||
|
|
4f8a0f753e | ||
|
|
7db5da9566 | ||
|
|
4d1389805c | ||
|
|
ee87e2b946 | ||
|
|
6356d78768 | ||
|
|
afdf7e740e | ||
|
|
51ce3ddf78 | ||
|
|
192186056e | ||
|
|
336a7febd7 | ||
|
|
63e73d1b73 | ||
|
|
a02ab9a723 | ||
|
|
95f15ab9dd | ||
|
|
5d0ea0066a | ||
|
|
9ff6b2da9b | ||
|
|
6ac7e27847 | ||
|
|
4ed1c5e747 | ||
|
|
bae3bc096f | ||
|
|
9d73683de2 | ||
|
|
f5fec0ab71 | ||
|
|
9909ab10c4 | ||
|
|
65cff01fee | ||
|
|
10190a3012 | ||
|
|
79ab696f4e | ||
|
|
cb603682e4 | ||
|
|
c986a06bf7 | ||
|
|
e2843a6cee | ||
|
|
ea1f239807 | ||
|
|
8d7618146a | ||
|
|
eb9e419bb0 | ||
|
|
f98f71ac26 | ||
|
|
03baaaebcb | ||
|
|
cbca954508 | ||
|
|
22ba6cc406 | ||
|
|
6bd172acb4 | ||
|
|
818ba4416f | ||
|
|
adff12841c | ||
|
|
480c306591 | ||
|
|
cbd1481cb7 | ||
|
|
d1c1871222 | ||
|
|
15a94b8fb0 | ||
|
|
66be54e6a7 | ||
|
|
62c85cc2eb | ||
|
|
1ae05a9ebc | ||
|
|
3457c70f30 | ||
|
|
c1ec9126da | ||
|
|
398da2fac7 | ||
|
|
47f33d6346 | ||
|
|
2cad82d537 | ||
|
|
8d06d78537 | ||
|
|
b61be000de | ||
|
|
9ca6de6e7a | ||
|
|
5c03c25e96 | ||
|
|
23843163ad | ||
|
|
8b07fbbedc | ||
|
|
5bf55220d4 | ||
|
|
0e1de3d6e8 | ||
|
|
3a7ba3675b | ||
|
|
5c0deb5bdb | ||
|
|
50dcbc2b01 | ||
|
|
90d72f7843 | ||
|
|
90ee59c70d | ||
|
|
59eda11c1b | ||
|
|
78684a424f | ||
|
|
4a936dda6e | ||
|
|
094d4b99a4 | ||
|
|
382268308e | ||
|
|
97315d27b9 | ||
|
|
26ae573b72 | ||
|
|
803c44d783 | ||
|
|
90f3f1037a | ||
|
|
ce39a751d9 | ||
|
|
ceebf7d32d | ||
|
|
8da59bf0ac | ||
|
|
d25979502a | ||
|
|
549bc3bf9f | ||
|
|
22b2f325e0 | ||
|
|
6615d1b90c | ||
|
|
8f045c4254 | ||
|
|
a4434349e5 | ||
|
|
01272be25f | ||
|
|
be0beed403 | ||
|
|
453d2abed5 | ||
|
|
57e9ccbef0 | ||
|
|
989124772b | ||
|
|
72400e4b91 | ||
|
|
900cba29a7 | ||
|
|
f177a65c1e | ||
|
|
b6baf9016d | ||
|
|
86ac6e8044 | ||
|
|
66d8fb95db | ||
|
|
22da8d9ba2 | ||
|
|
819e9c1b16 | ||
|
|
dd4b2e8bc2 | ||
|
|
e2f7ac2017 | ||
|
|
31b5cf6926 | ||
|
|
25fe3035c2 | ||
|
|
0cf56823cd | ||
|
|
c2f36968c3 | ||
|
|
a508c7f53e | ||
|
|
48de68031d | ||
|
|
81ef85af82 | ||
|
|
16b65d7dbe | ||
|
|
5a98e6511b | ||
|
|
2418f08e22 | ||
|
|
80a821bc20 | ||
|
|
378f78bd87 | ||
|
|
f010591e19 | ||
|
|
5274abdcca | ||
|
|
48f9e8c5c8 | ||
|
|
5c02117fde | ||
|
|
bc56a188f8 | ||
|
|
b6df1b22ab | ||
|
|
0fbf2dd5bb | ||
|
|
38c126d11a | ||
|
|
7dff602e5e | ||
|
|
e401f32815 | ||
|
|
12e94b70a7 | ||
|
|
884de3959c | ||
|
|
fe12325e50 | ||
|
|
bea86f3f79 | ||
|
|
7a5f3667da | ||
|
|
0813788c98 | ||
|
|
b1ca73e7f0 | ||
|
|
ebf9e9b1a3 | ||
|
|
b0abab7a1d | ||
|
|
995bb493df | ||
|
|
1b2375fc84 | ||
|
|
b7315bcb5a | ||
|
|
2c9ebdaa69 | ||
|
|
fbd9e5b4d7 | ||
|
|
b9a3425b6d | ||
|
|
d4742c611b | ||
|
|
c645a590aa | ||
|
|
275a7fe63f | ||
|
|
0ff16d8312 | ||
|
|
1cb31d6c7e | ||
|
|
8a6eb553df | ||
|
|
946af8b9ee | ||
|
|
098a1f647e | ||
|
|
c9681dc430 | ||
|
|
ff0b8b2d53 | ||
|
|
75f520d43a | ||
|
|
65209748ba | ||
|
|
cd604ef07b | ||
|
|
51da8bc531 | ||
|
|
2374ba12bd | ||
|
|
0a75aaec25 | ||
|
|
a8c286ae83 | ||
|
|
9cbdfc7764 | ||
|
|
cb1423436f | ||
|
|
2fb391795a | ||
|
|
9ec20f2d8f | ||
|
|
9323ca5136 | ||
|
|
978e6072ab | ||
|
|
d0e3869d54 | ||
|
|
15c7e956f2 | ||
|
|
ed61545ec7 | ||
|
|
1aac5becdc | ||
|
|
4bca26debc | ||
|
|
d6eecd1637 | ||
|
|
00e7620d2e | ||
|
|
d657283aad | ||
|
|
70a879ea94 | ||
|
|
591ee22472 | ||
|
|
956b05d39d | ||
|
|
5bdad6d4cb | ||
|
|
29a6ac6ed7 | ||
|
|
8f7f091e9b | ||
|
|
63dfe7628b | ||
|
|
ce507e7851 | ||
|
|
a9cd76173e | ||
|
|
44f8ffb434 | ||
|
|
28c395f111 | ||
|
|
39df68c38e | ||
|
|
b33ca9225a | ||
|
|
bd137afecf | ||
|
|
a3b9bed8c2 | ||
|
|
0a157739bc | ||
|
|
c46b08ad5e | ||
|
|
754e6193a4 | ||
|
|
56b49fe2dd | ||
|
|
36a7215f94 | ||
|
|
702247affd | ||
|
|
e752b1f8e5 | ||
|
|
920eee36e3 | ||
|
|
a5070a5d98 | ||
|
|
ccb5aefa61 | ||
|
|
378b08e37c | ||
|
|
5763483c91 | ||
|
|
559f8ee095 | ||
|
|
4382ef360c | ||
|
|
0cb576cf1a | ||
|
|
dee4d047b4 | ||
|
|
2520cc7bb9 | ||
|
|
192c31efe0 | ||
|
|
a1d8ebc2d2 | ||
|
|
14a9de2147 | ||
|
|
a760a9a3f1 | ||
|
|
efd14e1c7a | ||
|
|
6019c46cee | ||
|
|
ec6acfbc1c | ||
|
|
e925dbaad6 | ||
|
|
8321adf0bc | ||
|
|
e1c5e9e874 | ||
|
|
0aec581714 | ||
|
|
b77b8623d1 | ||
|
|
5ab986d6d9 | ||
|
|
09b8332236 | ||
|
|
d05345abc0 | ||
|
|
804c369f0d | ||
|
|
8f67fc886c | ||
|
|
ca3b1a9b30 | ||
|
|
63c1dbb3ed | ||
|
|
9a424dfe29 | ||
|
|
0a6eb596bb | ||
|
|
34452376db | ||
|
|
53a90a59c5 | ||
|
|
ec491ebd83 | ||
|
|
cdc41c305e | ||
|
|
6cf67b399c | ||
|
|
dc3c56bccc | ||
|
|
4657f2039a | ||
|
|
b0082fbd0d | ||
|
|
ede1b4df11 | ||
|
|
d78a3d1f8a | ||
|
|
6152555f26 | ||
|
|
bbad505044 | ||
|
|
11c5429184 | ||
|
|
4e865c4525 | ||
|
|
2fa785a539 | ||
|
|
296a8449c9 | ||
|
|
f20213ff10 | ||
|
|
8a7067ee24 | ||
|
|
a3024e9f5a | ||
|
|
86e651f5e7 | ||
|
|
409710b2b1 | ||
|
|
14a406a276 | ||
|
|
28a283b1c1 | ||
|
|
ccf298a148 | ||
|
|
914b600af4 | ||
|
|
4944994667 | ||
|
|
3a487578a5 | ||
|
|
39eeccb16a | ||
|
|
32acd3b9d1 | ||
|
|
c57baae477 | ||
|
|
4a6ed633b9 | ||
|
|
2ab1845547 | ||
|
|
f4d2e1f20c | ||
|
|
81dca1f690 | ||
|
|
2b331fd68f | ||
|
|
cc77e4dba7 | ||
|
|
620a13a308 | ||
|
|
42d4ba09d7 | ||
|
|
ca071fa52f | ||
|
|
d38e5dec7b | ||
|
|
e5db38f7c0 | ||
|
|
68a29730c0 | ||
|
|
5c33c4d341 | ||
|
|
a1d6270089 | ||
|
|
1968175b00 | ||
|
|
cf1e2aeeba | ||
|
|
199b0b9f57 | ||
|
|
87a0daa465 | ||
|
|
c2af90b58f | ||
|
|
62f01453af | ||
|
|
375d6ee331 | ||
|
|
222ca2915b | ||
|
|
5ca848f9fe | ||
|
|
68d878ff6b | ||
|
|
782a7b418a | ||
|
|
724d7854ad | ||
|
|
f8e64d17e8 | ||
|
|
3b40799000 | ||
|
|
709964ca92 | ||
|
|
d2cdedc610 | ||
|
|
b7d0730343 | ||
|
|
30b4ea7d49 | ||
|
|
546dadbd06 | ||
|
|
76edf902de | ||
|
|
7c4caef5e7 | ||
|
|
068024134c | ||
|
|
538ab57b6e | ||
|
|
fd6d9148f3 | ||
|
|
f033f59755 | ||
|
|
7168c6dd69 | ||
|
|
f121d41c2f | ||
|
|
e56e774eac | ||
|
|
6d9b0918a3 | ||
|
|
d445418611 | ||
|
|
6d15a51c9a | ||
|
|
42a615efdd | ||
|
|
54cd1f79a6 | ||
|
|
8ed8f46374 | ||
|
|
dd3a2996a4 | ||
|
|
bf1f90a96a | ||
|
|
2d6200231a | ||
|
|
032cd23304 | ||
|
|
de4c0a9e1c | ||
|
|
e33f8e8920 | ||
|
|
22615c7921 | ||
|
|
9d8809c580 | ||
|
|
96b92c98ff | ||
|
|
07939acecd | ||
|
|
30abcb2563 | ||
|
|
35ce8f2b8d | ||
|
|
d6453eab38 | ||
|
|
e0964d07ea | ||
|
|
fc359f1956 | ||
|
|
322261d65d | ||
|
|
bd1163c439 | ||
|
|
e203a8c706 | ||
|
|
6a1ba2af74 | ||
|
|
22569e64df | ||
|
|
dcafe41cde | ||
|
|
dd2adc08a3 | ||
|
|
d7534d2673 | ||
|
|
0a59920025 | ||
|
|
77602a8de4 | ||
|
|
65b3fde97c | ||
|
|
b690148452 | ||
|
|
4c7bc9ada6 | ||
|
|
432651489f | ||
|
|
82aa232a37 | ||
|
|
19b13bf7a7 | ||
|
|
f7e25d807d | ||
|
|
cf05316b95 | ||
|
|
001c4386b5 | ||
|
|
572527f8cb | ||
|
|
b4252beda6 | ||
|
|
d82ee16e0c | ||
|
|
e4d65c07ce | ||
|
|
86fcb78cc3 | ||
|
|
5beb422d75 | ||
|
|
53679879ca | ||
|
|
a8ad766182 | ||
|
|
cbb2d30f79 | ||
|
|
c5e00bcec6 | ||
|
|
51535d374d | ||
|
|
1e057e6c35 | ||
|
|
b23e8ab862 | ||
|
|
0f7f13dfb2 | ||
|
|
aa19ccda1d | ||
|
|
cd0129e780 | ||
|
|
506c9023e6 | ||
|
|
d47c25ea4c | ||
|
|
010651073c | ||
|
|
76364e3799 | ||
|
|
f9fd0a0203 | ||
|
|
8dfbde5d16 | ||
|
|
888991f8c1 | ||
|
|
ece03922d6 | ||
|
|
47bb827e6e | ||
|
|
a56003d847 | ||
|
|
61022c398c | ||
|
|
00bd8cc525 | ||
|
|
cf6a232aef | ||
|
|
59d1a45ef0 | ||
|
|
0b5f9fcb48 | ||
|
|
f713ffd6a1 | ||
|
|
22ba9d81d4 | ||
|
|
309bc98d7f | ||
|
|
9b8646a583 | ||
|
|
48d1b87ab8 | ||
|
|
c5f849d846 | ||
|
|
31fbb6e4f5 | ||
|
|
4d9a88e999 | ||
|
|
252e8484a8 | ||
|
|
1b89203932 | ||
|
|
2263c6a618 | ||
|
|
673cb3ee21 | ||
|
|
b4ecd504e3 | ||
|
|
f226f29428 | ||
|
|
b87a284390 | ||
|
|
f63dcd0d9c | ||
|
|
7f5563d581 | ||
|
|
d8a61a920e | ||
|
|
5a4900da8e | ||
|
|
677c30057a | ||
|
|
26113e091b | ||
|
|
1b5e98f593 | ||
|
|
0aa5201947 | ||
|
|
e3951baa3f | ||
|
|
9f9dbbab9e | ||
|
|
d546bbadbd | ||
|
|
2b7f25054f | ||
|
|
bb3f6bcf7e | ||
|
|
41da7175d1 | ||
|
|
446763b58a | ||
|
|
3e9337a0fc | ||
|
|
028806165b | ||
|
|
e4be42edbb | ||
|
|
230fa1f3bb | ||
|
|
d74653bbad | ||
|
|
38049b0897 | ||
|
|
b4af646929 | ||
|
|
b21ec73a52 | ||
|
|
c595844f0e | ||
|
|
fe8ee7c7b3 | ||
|
|
cd382c6bc0 | ||
|
|
e68296c293 | ||
|
|
cc189feae5 | ||
|
|
18e19027a1 | ||
|
|
2d2e0e4757 | ||
|
|
a9f50d79f9 | ||
|
|
0ccd31bee0 | ||
|
|
3ea82b2bcd | ||
|
|
6dad7b3ced | ||
|
|
f96ebd2b07 | ||
|
|
b8d0e7a3ac | ||
|
|
14cca3d497 | ||
|
|
c343ca0cc3 | ||
|
|
527d371bda | ||
|
|
b87a800a9a | ||
|
|
e406993ed1 | ||
|
|
eeff935fc9 | ||
|
|
0791394f1a | ||
|
|
082a407b06 | ||
|
|
8a89b49df1 | ||
|
|
2314b9cbab | ||
|
|
d0cca85c83 | ||
|
|
6a7a5cbcba | ||
|
|
ecccc82cc8 | ||
|
|
02693489fe | ||
|
|
0f5dba5828 | ||
|
|
e528d4c4b7 | ||
|
|
52a3af6acf | ||
|
|
dcefea9958 | ||
|
|
59121ff834 | ||
|
|
7f5bb6d472 | ||
|
|
639c1a508c | ||
|
|
417a26fc64 | ||
|
|
210ccd0063 | ||
|
|
1bf0162d38 | ||
|
|
e93027fd7e | ||
|
|
807060706f | ||
|
|
a317f88d3c | ||
|
|
e17a7f0701 | ||
|
|
db325eb9fe | ||
|
|
b41a4c8c3b | ||
|
|
73b4d11d18 | ||
|
|
8162b87287 | ||
|
|
70e9e4f3ee | ||
|
|
e61ae376b3 | ||
|
|
2d57b0e926 | ||
|
|
ae683af07a | ||
|
|
3c4f6a9171 | ||
|
|
39986e546c | ||
|
|
2e81a80f7b | ||
|
|
fcb3aa38c8 | ||
|
|
00a38d8ec5 | ||
|
|
07a0ab4227 | ||
|
|
d4a9a2c543 | ||
|
|
2b523fc60d | ||
|
|
0c26928236 | ||
|
|
8401e56a22 | ||
|
|
5109f9ae0b | ||
|
|
c9bc06669a | ||
|
|
a83fb2672c | ||
|
|
8f9ecb44d9 | ||
|
|
bfcc09a8de | ||
|
|
f8a8c997db | ||
|
|
132b996f30 | ||
|
|
12f970cdfb | ||
|
|
9afa963225 | ||
|
|
ed368d0d51 | ||
|
|
21f21d34ba | ||
|
|
f37823c809 | ||
|
|
6eaefcff5e | ||
|
|
79235c1cc3 | ||
|
|
29135f014b | ||
|
|
13c998fb8d | ||
|
|
71bfd0d636 | ||
|
|
51e99e0f5a | ||
|
|
66e7beefc4 | ||
|
|
f2b10c35b7 | ||
|
|
e951eba96c | ||
|
|
9fe18da7a3 | ||
|
|
a14fdead14 | ||
|
|
9a671a4991 | ||
|
|
8f5e7b124a | ||
|
|
5f7464d015 | ||
|
|
238dd6c1d0 | ||
|
|
82e4e54edc | ||
|
|
9946cbb9da | ||
|
|
2474adb23a | ||
|
|
f40757bb67 | ||
|
|
bc29479930 | ||
|
|
4ec78edaa3 | ||
|
|
aa0271158d | ||
|
|
c0aa5bfe17 | ||
|
|
3f8e6a8cc8 | ||
|
|
ef0316fc2e | ||
|
|
7274efab15 | ||
|
|
e44b62b6b2 | ||
|
|
31c041d435 | ||
|
|
35f47371ed | ||
|
|
c5412e1620 | ||
|
|
a9b4c52811 | ||
|
|
5ce40b6ac8 |
@@ -2,6 +2,8 @@
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
*~
|
||||
*.so
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
|
||||
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
|
||||
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
|
||||
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
|
||||
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
|
||||
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
|
||||
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
|
||||
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
|
||||
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
|
||||
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
|
||||
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
|
||||
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
|
||||
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
|
||||
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
0000000000000000000000000000000000000000 0.9.7.1
|
||||
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
|
||||
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
|
||||
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
|
||||
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
|
||||
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
|
||||
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
|
||||
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
|
||||
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
|
||||
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
|
||||
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
|
||||
@@ -217,6 +217,45 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
return rp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
@@ -337,7 +376,11 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap
|
||||
inherit = base
|
||||
+1
-8
@@ -1,18 +1,11 @@
|
||||
[uwsgi]
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
ssl = auto
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
alarm = auto
|
||||
ipv6 = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
@@ -23,7 +16,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi,coroae
|
||||
inherit = base
|
||||
@@ -1,3 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
debug = false
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gridfs
|
||||
inherit = base
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin =
|
||||
inherit = base
|
||||
@@ -0,0 +1,32 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
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 =
|
||||
bin_name = /usr/lib/libuwsgi.so
|
||||
append_version = ubuntu
|
||||
plugin_dir = /usr/lib/uwsgi
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,6 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
plugins = jvm,ring
|
||||
plugin_dir = .
|
||||
|
||||
+12
-6
@@ -1,26 +1,32 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ldap = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
alarm = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /opt/unbit/bin/uwsgi
|
||||
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
|
||||
append_version = unbit
|
||||
plugin_dir = /opt/unbit/uwsgi_plugins
|
||||
plugin_dir = /opt/unbit/uwsgi19/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
json = false
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_plugins
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
the uwsgi handler is included in the official Cherokee distribution
|
||||
@@ -0,0 +1,24 @@
|
||||
require 'socket'
|
||||
require 'openssl'
|
||||
|
||||
secret = 'ciaociao'
|
||||
iv = ''
|
||||
address = '127.0.0.1'
|
||||
port = 1717
|
||||
algo = 'bf-cbc'
|
||||
|
||||
s = UDPSocket.new
|
||||
s.bind(address, port)
|
||||
cipher = OpenSSL::Cipher.new(algo)
|
||||
cipher.decrypt
|
||||
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
|
||||
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
|
||||
|
||||
loop do
|
||||
msg, sender = s.recvfrom(8192)
|
||||
cipher.reset
|
||||
begin
|
||||
puts cipher.update(msg) + cipher.final
|
||||
rescue
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Greenlets support
|
||||
|
||||
simply --pypy-exec this file to enable PyPy's greenlet mode
|
||||
|
||||
Example:
|
||||
|
||||
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
|
||||
"""
|
||||
|
||||
import greenlet
|
||||
|
||||
uwsgi_pypy_greenlets = {}
|
||||
|
||||
def uwsgi_pypy_greenlet_wrapper():
|
||||
lib.async_schedule_to_req_green()
|
||||
|
||||
@ffi.callback("void()")
|
||||
def uwsgi_pypy_greenlet_schedule():
|
||||
id = lib.uwsgi.wsgi_req.async_id
|
||||
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
|
||||
|
||||
# generate a new greenlet
|
||||
if not lib.uwsgi.wsgi_req.suspended:
|
||||
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
|
||||
lib.uwsgi.wsgi_req.suspended = 1
|
||||
|
||||
# this is called in the main stack
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
|
||||
|
||||
# let's switch
|
||||
uwsgi_pypy_greenlets[id].switch()
|
||||
|
||||
# back to the main stack
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(ffi.NULL)
|
||||
|
||||
@ffi.callback("void(struct wsgi_request *)")
|
||||
def uwsgi_pypy_greenlet_switch(wsgi_req):
|
||||
id = wsgi_req.async_id
|
||||
modifier1 = wsgi_req.uh.modifier1;
|
||||
|
||||
# this is called in the current greenlet
|
||||
if lib.uwsgi.p[modifier1].suspend:
|
||||
lib.uwsgi.p[modifier1].suspend(wsgi_req)
|
||||
|
||||
uwsgi_pypy_main_greenlet.switch()
|
||||
|
||||
# back to the greenlet
|
||||
if lib.uwsgi.p[modifier1].resume:
|
||||
lib.uwsgi.p[modifier1].resume(wsgi_req)
|
||||
|
||||
# update current running greenlet
|
||||
lib.uwsgi.wsgi_req = wsgi_req
|
||||
|
||||
if lib.uwsgi.async <= 1:
|
||||
raise Exception("pypy greenlets require async mode !!!")
|
||||
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
|
||||
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
|
||||
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
|
||||
@@ -0,0 +1,15 @@
|
||||
# uWSGI - Emperor
|
||||
#
|
||||
|
||||
description "uWSGI Emperor"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
env VASSALS=/etc/uwsgi
|
||||
|
||||
exec $BINPATH --emperor $VASSALS --logto $LOGTO
|
||||
@@ -11,7 +11,6 @@ respawn
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
# --die-on-term could be a good idea
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
# --die-on-term is upstart friendly
|
||||
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
|
||||
|
||||
|
||||
+139
-10
@@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
|
||||
uwsgi_route_signal(uai->data8);
|
||||
}
|
||||
|
||||
// simply log an alarm
|
||||
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
if (msg[len-1] != '\n') {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s\n", len, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uai->arg && strlen(uai->arg) > 0) {
|
||||
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log_alarm("] %.*s", len, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run a command on alarm
|
||||
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = uai->arg;
|
||||
@@ -86,6 +109,7 @@ void uwsgi_register_embedded_alarms() {
|
||||
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
|
||||
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
|
||||
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
|
||||
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
|
||||
}
|
||||
|
||||
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
|
||||
@@ -189,21 +213,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
#endif
|
||||
|
||||
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
|
||||
// add uwsgi_alarm_fd;
|
||||
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
|
||||
while(uafd) {
|
||||
event_queue_add_fd_read(ut->queue, uafd->fd);
|
||||
uafd = uafd->next;
|
||||
}
|
||||
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
if (interesting_fd == ut->pipe[1]) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
long ptr = 0;
|
||||
memcpy(&ptr, buf, sizeof(long));
|
||||
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
|
||||
if (!uai)
|
||||
break;
|
||||
uwsgi_alarm_run(uai, msg, msg_size);
|
||||
}
|
||||
}
|
||||
// check for alarm_fd
|
||||
else {
|
||||
uafd = uwsgi.alarm_fds;
|
||||
int fd_read = 0;
|
||||
while(uafd) {
|
||||
if (interesting_fd == uafd->fd) {
|
||||
if (fd_read) goto raise;
|
||||
size_t remains = uafd->buf_len;
|
||||
while(remains) {
|
||||
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("[uwsgi-alarm-fd]/read()");
|
||||
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
|
||||
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
|
||||
break;
|
||||
}
|
||||
remains-=len;
|
||||
}
|
||||
fd_read = 1;
|
||||
raise:
|
||||
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
|
||||
}
|
||||
uafd = uafd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +300,37 @@ void uwsgi_alarms_init() {
|
||||
|
||||
if (!uwsgi.alarm_instances) return;
|
||||
|
||||
// map alarm file descriptors
|
||||
usl = uwsgi.alarm_fd_list;
|
||||
while(usl) {
|
||||
char *space0 = strchr(usl->value, ' ');
|
||||
if (!space0) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space0 = 0;
|
||||
size_t buf_len = 1;
|
||||
char *space1 = strchr(space0+1, ' ');
|
||||
if (!space1) {
|
||||
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *colon = strchr(space0+1, ':');
|
||||
if (colon) {
|
||||
buf_len = strtoul(colon+1, NULL, 10);
|
||||
*colon = 0;
|
||||
}
|
||||
int fd = atoi(space0+1);
|
||||
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
|
||||
*space0 = ' ';
|
||||
*space1 = ' ';
|
||||
if (colon) {
|
||||
*colon = ':';
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
@@ -340,3 +428,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
|
||||
if (!uai) {
|
||||
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!buf_len) buf_len = 1;
|
||||
|
||||
while(uafd) {
|
||||
// check if an equal alarm has been added
|
||||
if (uafd->fd == fd && uafd->alarm == uai) {
|
||||
return uafd;
|
||||
}
|
||||
old_uafd = uafd;
|
||||
uafd = uafd->next;
|
||||
}
|
||||
|
||||
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
|
||||
uafd->fd = fd;
|
||||
uafd->buf = uwsgi_malloc(buf_len);
|
||||
uafd->buf_len = buf_len;
|
||||
uafd->msg = msg;
|
||||
uafd->msg_len = msg_len;
|
||||
uafd->alarm = uai;
|
||||
|
||||
if (!old_uafd) {
|
||||
uwsgi.alarm_fds = uafd;
|
||||
}
|
||||
else {
|
||||
old_uafd->next = uafd;
|
||||
}
|
||||
|
||||
// avoid the fd to be closed
|
||||
uwsgi_add_safe_fd(fd);
|
||||
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
|
||||
|
||||
return uafd;
|
||||
}
|
||||
|
||||
+135
-94
@@ -2,6 +2,24 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general purpose async loop engine (it expects a coroutine based approach)
|
||||
|
||||
You can see it as an hub holding the following structures:
|
||||
|
||||
1) the runqueue, cores ready to be run are appended in 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)
|
||||
|
||||
|
||||
IMPORTANT: this is not a callback based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
// this is called whenever a new connection is ready, but there are no cores to handle it
|
||||
void uwsgi_async_queue_is_full(time_t now) {
|
||||
if (now > uwsgi.async_queue_is_full) {
|
||||
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
|
||||
@@ -22,12 +40,15 @@ 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;
|
||||
|
||||
}
|
||||
@@ -52,7 +73,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
if (u_request == uwsgi.async_runqueue) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
|
||||
@@ -61,33 +82,33 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
}
|
||||
|
||||
free(u_request);
|
||||
|
||||
uwsgi.async_runqueue_cnt--;
|
||||
}
|
||||
|
||||
static void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct uwsgi_async_request *uar;
|
||||
// do not push the same request in the runqueue
|
||||
struct uwsgi_async_request *uar = uwsgi.async_runqueue;
|
||||
while(uar) {
|
||||
if (uar->wsgi_req == wsgi_req) return;
|
||||
uar = uar->next;
|
||||
}
|
||||
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = NULL;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
|
||||
if (uwsgi.async_runqueue == NULL) {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
uwsgi.async_runqueue = uar;
|
||||
}
|
||||
else {
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
}
|
||||
|
||||
uwsgi.async_runqueue_cnt++;
|
||||
|
||||
if (uwsgi.async_runqueue_last) {
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
}
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
}
|
||||
|
||||
struct wsgi_request *find_first_available_wsgi_req() {
|
||||
@@ -103,11 +124,28 @@ struct wsgi_request *find_first_available_wsgi_req() {
|
||||
return wsgi_req;
|
||||
}
|
||||
|
||||
void async_reset_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *uaf = wsgi_req->waiting_fds;
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
struct uwsgi_async_fd *current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
}
|
||||
|
||||
static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for (;;) {
|
||||
@@ -121,20 +159,9 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
uaf = wsgi_req->waiting_fds;
|
||||
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
current_uaf = uaf;
|
||||
uaf = current_uaf->next;
|
||||
free(current_uaf);
|
||||
}
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
// put th request in the runqueue
|
||||
// reset teh request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
@@ -151,7 +178,7 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -179,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
|
||||
static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -195,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
|
||||
}
|
||||
@@ -208,7 +241,7 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// find first slot
|
||||
// find last slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
@@ -238,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
static int async_wait_fd_write(int fd, int timeout) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_write(wsgi_req, fd, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -252,7 +288,49 @@ static int async_wait_fd_write(int fd, int timeout) {
|
||||
}
|
||||
|
||||
void async_schedule_to_req(void) {
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
// a trick to avoid calling routes again
|
||||
uwsgi.wsgi_req->is_routing = 1;
|
||||
#endif
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
}
|
||||
return;
|
||||
|
||||
end:
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
}
|
||||
|
||||
void async_schedule_to_req_green(void) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
uwsgi.wsgi_req->switches++;
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(uwsgi.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;
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
@@ -262,7 +340,6 @@ void async_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *tmp_uaf;
|
||||
int interesting_fd, i;
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
int timeout;
|
||||
@@ -271,13 +348,12 @@ void async_loop() {
|
||||
|
||||
uint64_t now;
|
||||
|
||||
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
|
||||
struct uwsgi_async_request *current_request = NULL;
|
||||
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
@@ -298,7 +374,7 @@ void async_loop() {
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
now = (uint64_t) uwsgi_now();
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
if (uwsgi.async_runqueue) {
|
||||
timeout = 0;
|
||||
}
|
||||
else {
|
||||
@@ -328,16 +404,15 @@ void async_loop() {
|
||||
// manage events
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
// signals are executed in the main stack... in the future we could have dedicated stacks for them
|
||||
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
is_a_new_connection = 0;
|
||||
|
||||
// new request coming in ?
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
|
||||
@@ -351,6 +426,7 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// on error re-insert the request in the queue
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
@@ -364,6 +440,9 @@ void async_loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// by default the core is in UWSGI_AGAIN mode
|
||||
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
|
||||
// some protocol (like zeromq) do not need additional parsing, just push it in the runqueue
|
||||
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
}
|
||||
@@ -380,9 +459,7 @@ void async_loop() {
|
||||
if (uwsgi.wsgi_req) {
|
||||
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
|
||||
// reset timeout
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
@@ -393,8 +470,6 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
else if (proto_parser_status < 0) {
|
||||
if (proto_parser_status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
continue;
|
||||
@@ -404,7 +479,7 @@ void async_loop() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// app event
|
||||
// app-registered event
|
||||
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
|
||||
// unknown fd, remove it (for safety)
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
@@ -413,79 +488,45 @@ void async_loop() {
|
||||
}
|
||||
|
||||
// remove all the fd monitors and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_ready_fd = 1;
|
||||
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
|
||||
|
||||
// put the request in the runqueue again
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
// avoid managing other enqueued events...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// event queue managed, give cpu to runqueue
|
||||
if (!current_request)
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
// event queue managed, give cpu to runqueue
|
||||
current_request = uwsgi.async_runqueue;
|
||||
|
||||
while(current_request) {
|
||||
|
||||
// current_request could be nulled on error/end of request
|
||||
struct uwsgi_async_request *next_request = current_request->next;
|
||||
|
||||
uwsgi.wsgi_req = current_request->wsgi_req;
|
||||
|
||||
uwsgi.schedule_to_req();
|
||||
uwsgi.wsgi_req->switches++;
|
||||
|
||||
next_async_request = current_request->next;
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
// remove all the monitored fds and timeout
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
// remove from the list
|
||||
// remove from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
|
||||
// push wsgi_request in the unused stack
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
|
||||
}
|
||||
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove this request from suspended list
|
||||
// remove this request from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
current_request = next_async_request;
|
||||
|
||||
current_request = next_request;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -328,3 +328,37 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
|
||||
ub->buf[3] = modifier2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
|
||||
struct stat st;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
|
||||
|
||||
ssize_t len = read(fd, ub->buf, st.st_size);
|
||||
close(fd);
|
||||
if (len != st.st_size) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ub->pos = len;
|
||||
return ub;
|
||||
}
|
||||
|
||||
void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
if (ub->buf) {
|
||||
free(ub->buf);
|
||||
}
|
||||
ub->buf = buf;
|
||||
ub->pos = len;
|
||||
ub->len = len;
|
||||
}
|
||||
|
||||
+297
-93
@@ -156,14 +156,14 @@ static void cache_send_udp_command(struct uwsgi_cache *, char *, uint16_t, char
|
||||
static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_cache *uc = (struct uwsgi_cache *) data;
|
||||
if (!uwsgi_strncmp(k, kl, "items", 5)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->max_items) {
|
||||
uwsgi_log("[cache-sync] invalid cache size, expected %llu received %llu\n", (unsigned long long) uc->max_items, (unsigned long long) num);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!uwsgi_strncmp(k, kl, "blocksize", 9)) {
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
size_t num = uwsgi_str_num(v, vl);
|
||||
if (num != uc->blocksize) {
|
||||
uwsgi_log("[cache-sync] invalid cache block size, expected %llu received %llu\n", (unsigned long long) uc->blocksize, (unsigned long long) num);
|
||||
exit(1);
|
||||
@@ -171,6 +171,41 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
char *value = strchr(key, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("[cache] unable to store item %s\n", usl->value);
|
||||
goto next;
|
||||
}
|
||||
key_len = value - key;
|
||||
value++;
|
||||
uint64_t len = (usl->value + usl->len) - value;
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
|
||||
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
|
||||
@@ -194,12 +229,52 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
|
||||
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
free(value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key);
|
||||
}
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
usl = uwsgi.load_file_in_cache_gzip;
|
||||
while(usl) {
|
||||
size_t len = 0;
|
||||
char *value = NULL;
|
||||
char *key = usl->value;
|
||||
uint16_t key_len = usl->len;
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
// need to skip ?
|
||||
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
|
||||
goto next2;
|
||||
}
|
||||
key = space+1;
|
||||
key_len = usl->len - ((space-usl->value)+1);
|
||||
}
|
||||
value = uwsgi_open_and_read(key, &len, 0, NULL);
|
||||
if (value) {
|
||||
struct uwsgi_buffer *gzipped = uwsgi_gzip(value, len);
|
||||
if (gzipped) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
if (!uwsgi_cache_set2(uc, key, key_len, gzipped->buf, gzipped->len, 0, 0)) {
|
||||
uwsgi_log("[cache-gzip] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
uwsgi_buffer_destroy(gzipped);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
next2:
|
||||
usl = usl->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -288,21 +363,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
(unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items),
|
||||
(unsigned long long) uc->blocks_bitmap_size);
|
||||
|
||||
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_setup_nodes(uc);
|
||||
|
||||
uc->udp_node_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (uc->udp_node_socket < 0) {
|
||||
@@ -311,70 +372,12 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
uwsgi_socket_nb(uc->udp_node_socket);
|
||||
|
||||
usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, ub->pos, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_cache_sync_from_nodes(uc);
|
||||
|
||||
uwsgi_cache_load_files(uc);
|
||||
|
||||
uwsgi_cache_add_items(uc);
|
||||
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
@@ -456,6 +459,46 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t uwsgi_cache_num2(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
|
||||
if (index) {
|
||||
struct uwsgi_cache_item *uci = cache_item(index);
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return 0;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
int64_t *num = (int64_t *) (uc->data + (uci->first_block * uc->blocksize));
|
||||
return *num;
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *expires) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
|
||||
if (index) {
|
||||
struct uwsgi_cache_item *uci = cache_item(index);
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return NULL;
|
||||
*valsize = uci->valsize;
|
||||
if (expires)
|
||||
*expires = uci->expires;
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
}
|
||||
|
||||
uc->miss++;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
@@ -501,6 +544,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
|
||||
uci->expires = 0;
|
||||
|
||||
uc->n_items--;
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = uwsgi_now();
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
@@ -533,7 +580,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
|
||||
uc->n_items = restored;
|
||||
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
|
||||
}
|
||||
|
||||
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
|
||||
@@ -546,6 +594,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uint8_t rollback_mode = 0;
|
||||
|
||||
int ret = -1;
|
||||
time_t now = 0;
|
||||
|
||||
if (!keylen || !vallen)
|
||||
return -1;
|
||||
@@ -555,6 +604,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
|
||||
if (vallen > uc->max_item_size) return -1;
|
||||
|
||||
if ((flags & UWSGI_CACHE_FLAG_MATH) && vallen != 8) return -1;
|
||||
|
||||
//uwsgi_log("putting cache data in key %.*s %d\n", keylen, key, vallen);
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) {
|
||||
@@ -591,13 +642,13 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
}
|
||||
else if (rollback_mode == 2) {
|
||||
uc->first_available_block--;
|
||||
uc->first_available_block--;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -605,14 +656,42 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks + 1;
|
||||
}
|
||||
}
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE))
|
||||
expires += uwsgi_now();
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
}
|
||||
uci->expires = expires;
|
||||
uci->hash = uc->hash->func(key, keylen);
|
||||
uci->hits = 0;
|
||||
uci->flags = flags;
|
||||
memcpy(uci->key, key, keylen);
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
// ok math operations here
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
*num = uc->math_initial;
|
||||
int64_t *delta = (int64_t *) val;
|
||||
if (flags & UWSGI_CACHE_FLAG_INC) {
|
||||
*num += *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DEC) {
|
||||
*num -= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_MUL) {
|
||||
*num *= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DIV) {
|
||||
if (*delta == 0) {
|
||||
*num = 0;
|
||||
}
|
||||
else {
|
||||
*num /= *delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set this as late as possibile (to reduce races risk)
|
||||
|
||||
@@ -644,8 +723,9 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = cache_item(index);
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
expires += uwsgi_now();
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE) && !(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
uci->expires = expires;
|
||||
}
|
||||
if (uc->blocks_bitmap) {
|
||||
@@ -670,11 +750,38 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
// unmark the old blocks
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
}
|
||||
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
int64_t *delta = (int64_t *) val;
|
||||
if (flags & UWSGI_CACHE_FLAG_INC) {
|
||||
*num += *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DEC) {
|
||||
*num -= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_MUL) {
|
||||
*num *= *delta;
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_DIV) {
|
||||
if (*delta == 0) {
|
||||
*num = 0;
|
||||
}
|
||||
else {
|
||||
*num /= *delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
uci->valsize = vallen;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
||||
if (uc->use_last_modified) {
|
||||
uc->last_modified_at = (now ? now : uwsgi_now());
|
||||
}
|
||||
|
||||
if (uc->nodes && ret == 0 && !(flags & UWSGI_CACHE_FLAG_LOCAL)) {
|
||||
cache_send_udp_command(uc, key, keylen, val, vallen, expires, 10);
|
||||
}
|
||||
@@ -952,6 +1059,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->nodes = uwsgi.cache_udp_node;
|
||||
uc->udp_servers = uwsgi.cache_udp_server;
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
uc->use_last_modified = (uint8_t) uwsgi.cache_use_last_modified;
|
||||
|
||||
if (uwsgi.cache_sync) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, uwsgi.cache_sync);
|
||||
@@ -971,6 +1079,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
char *c_bitmap = NULL;
|
||||
char *c_use_last_modified = NULL;
|
||||
char *c_math_initial = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -996,6 +1106,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"udpservers", &c_udp_servers,
|
||||
"udpserver", &c_udp_servers,
|
||||
"bitmap", &c_bitmap,
|
||||
"lastmod", &c_use_last_modified,
|
||||
"math_initial", &c_math_initial,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -1020,7 +1132,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
// defaults
|
||||
uc->blocks = uc->max_items;
|
||||
uc->blocksize = UMAX16;
|
||||
uc->max_item_size = uc->blocksize;
|
||||
uc->keysize = 2048;
|
||||
uc->hashsize = UMAX16;
|
||||
uc->hash = uwsgi_hash_algo_get("djb33x");
|
||||
@@ -1028,6 +1139,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
// customize
|
||||
if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize);
|
||||
if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); }
|
||||
// set the true max size of an item
|
||||
uc->max_item_size = uc->blocksize;
|
||||
|
||||
if (c_blocks) uc->blocks = uwsgi_n64(c_blocks);
|
||||
if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); }
|
||||
if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash);
|
||||
@@ -1040,6 +1154,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->use_blocks_bitmap = 1;
|
||||
uc->max_item_size = uc->blocksize * uc->blocks;
|
||||
}
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
|
||||
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
|
||||
@@ -1306,7 +1423,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *cache) {
|
||||
char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64_t *expires, char *cache) {
|
||||
struct uwsgi_cache_magic_context ucmc;
|
||||
struct uwsgi_cache *uc = NULL;
|
||||
char *cache_server = NULL;
|
||||
@@ -1331,7 +1448,7 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
// we have a local cache !!!
|
||||
if (uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, key, keylen, vallen);
|
||||
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return NULL;
|
||||
@@ -1401,6 +1518,9 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char *
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
*vallen = ucmc.size;
|
||||
if (expires) {
|
||||
*expires = ucmc.expires;
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
@@ -1695,3 +1815,87 @@ int uwsgi_cache_magic_clear(char *cache) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->sync_nodes;
|
||||
while(usl) {
|
||||
uwsgi_log("[cache-sync] getting cache dump from %s ...\n", usl->value);
|
||||
int fd = uwsgi_connect(usl->value, 0, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[cache-sync] unable to connect to the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append(ub, uc->name, uc->name_len)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 6)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (uwsgi_write_nb(fd, ub->buf, ub->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to write to the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
goto next;
|
||||
}
|
||||
|
||||
uwsgi_hooked_parse(ub->buf, rlen, cache_sync_hook, uc);
|
||||
|
||||
if (uwsgi_read_nb(fd, (char *) uc->items, uc->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
goto next;
|
||||
}
|
||||
|
||||
// reset the hashtable
|
||||
memset(uc->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// re-fill the hashtable
|
||||
uwsgi_cache_fix(uc);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
close(fd);
|
||||
break;
|
||||
next:
|
||||
if (!usl->next) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[cache-sync] trying with the next sync node...\n");
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
|
||||
struct uwsgi_string_list *usl = uc->nodes;
|
||||
while(usl) {
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[cache-udp-node] invalid udp address: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
uwsgi_log("added udp node %s for cache \"%s\"\n", usl->value, uc->name);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Chunked input implementation
|
||||
|
||||
--chunked-input-limit <bytes> (default 1MB)
|
||||
|
||||
--chunked-input-timeout <s> (default --socket-timeout)
|
||||
|
||||
chunk = uwsgi.chunked_read([timeout])
|
||||
|
||||
timeout = -1 (wait forever)
|
||||
timeout = 0 (default)
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
|
||||
|
||||
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
|
||||
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
|
||||
int ret = -1;
|
||||
|
||||
for(;;) {
|
||||
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
if (nb) return -1;
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait:
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
|
||||
if (ret > 0) {
|
||||
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
|
||||
if (rlen > 0) return rlen;
|
||||
if (rlen <= 0) return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_chunked_input_recv()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
|
||||
size_t i;
|
||||
int found = 0;
|
||||
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
|
||||
if (found) {
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
|
||||
// strtoul will stop at \r
|
||||
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
|
||||
return num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
|
||||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
|
||||
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0 -> waiting for \r\n
|
||||
1 -> waiting for whole body
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
|
||||
char *ret;
|
||||
if (!wsgi_req->chunked_input_buf) {
|
||||
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
|
||||
}
|
||||
|
||||
// the whole chunk stream has been consumed
|
||||
if (wsgi_req->chunked_input_complete) {
|
||||
*len = 0;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
|
||||
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
|
||||
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
|
||||
if (rlen <= 0) return NULL;
|
||||
// update buffer position
|
||||
wsgi_req->chunked_input_buf->pos += rlen;
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) {
|
||||
if ((size_t)rlen > wsgi_req->chunked_input_need) {
|
||||
wsgi_req->chunked_input_need = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->chunked_input_need -= rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->chunked_input_need > 0) continue;
|
||||
|
||||
// ok we have a frame, let's parse it
|
||||
if (wsgi_req->chunked_input_buf->pos > 0) {
|
||||
switch(wsgi_req->chunked_input_parser_status) {
|
||||
case 0:
|
||||
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
|
||||
if (wsgi_req->chunked_input_chunk_len == -2) {
|
||||
break;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (wsgi_req->chunked_input_chunk_len == 0) {
|
||||
*len = 0;
|
||||
wsgi_req->chunked_input_complete = 1;
|
||||
return wsgi_req->chunked_input_buf->buf;
|
||||
}
|
||||
// if here the buffer has been already decapitated
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
wsgi_req->chunked_input_parser_status = 1;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
ret = wsgi_req->chunked_input_buf->buf;
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
|
||||
return ret;
|
||||
case 1:
|
||||
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
|
||||
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
|
||||
break;
|
||||
}
|
||||
*len = wsgi_req->chunked_input_chunk_len;
|
||||
ret = wsgi_req->chunked_input_buf->buf;
|
||||
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
|
||||
wsgi_req->chunked_input_parser_status = 0;
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int main() {}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
pluggable configuration system
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
|
||||
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (!strcmp(uc->name, name)) {
|
||||
return uc;
|
||||
}
|
||||
old_uc = uc;
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
|
||||
uc->name = name;
|
||||
uc->func = func;
|
||||
|
||||
if (old_uc) {
|
||||
old_uc->next = uc;
|
||||
}
|
||||
else {
|
||||
uwsgi.configurators = uc;
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
cookie management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t orig_cookie_len = cookie_len-1;
|
||||
// first lstrip white spaces
|
||||
char *ptr = cookie;
|
||||
uint16_t i;
|
||||
for(i=0;i<cookie_len;i++) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie++;
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then rstrip (skipping the first char...)
|
||||
for(i=orig_cookie_len;i>0;i--) {
|
||||
if (isspace((int)ptr[i])) {
|
||||
cookie_len--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the first equal sign
|
||||
char *equal = memchr(cookie, '=', cookie_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookie_len -= (equal-cookie)+1;
|
||||
if (cookie_len == 0) return NULL;
|
||||
|
||||
*vallen = cookie_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *cookie = wsgi_req->cookie;
|
||||
uint16_t cookie_len = 0;
|
||||
char *ptr = wsgi_req->cookie;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->cookie_len;i++) {
|
||||
if (!cookie) {
|
||||
cookie = ptr + i;
|
||||
}
|
||||
if (ptr[i] == ';') {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
cookie_len = 0;
|
||||
cookie = NULL;
|
||||
}
|
||||
else {
|
||||
cookie_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie_len > 0) {
|
||||
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
|
||||
int i;
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = crontab + i;
|
||||
uc->pid = -1;
|
||||
return uc;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
uwsgi_cron_add(value);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(value);
|
||||
uc->unique = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
uc->unique = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *c_minute = NULL;
|
||||
char *c_hour = NULL;
|
||||
char *c_day = NULL;
|
||||
char *c_month = NULL;
|
||||
char *c_week = NULL;
|
||||
char *c_unique = NULL;
|
||||
char *c_harakiri = NULL;
|
||||
char *c_legion = NULL;
|
||||
|
||||
char *c_command = value;
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (space) {
|
||||
if (uwsgi_str_contains(value, space - value, '=')) {
|
||||
// --cron2 key=val command
|
||||
*space = 0;
|
||||
c_command = space + 1;
|
||||
}
|
||||
|
||||
// no point in parsing key=val list if there is none
|
||||
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
|
||||
"minute", &c_minute,
|
||||
"hour", &c_hour,
|
||||
"day", &c_day,
|
||||
"month", &c_month,
|
||||
"week", &c_week,
|
||||
"unique", &c_unique,
|
||||
"harakiri", &c_harakiri,
|
||||
"legion", &c_legion,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_str_contains(value, strlen(value), '=')) {
|
||||
// --cron2 key=val
|
||||
uwsgi_log("unable to parse cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
uc->command = c_command;
|
||||
if (!uc->command) {
|
||||
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// defaults
|
||||
uc->minute = -1;
|
||||
uc->hour = -1;
|
||||
uc->day = -1;
|
||||
uc->month = -1;
|
||||
uc->week = -1;
|
||||
|
||||
uc->unique = 0;
|
||||
uc->mercy = 0;
|
||||
uc->harakiri = 0;
|
||||
uc->pid = -1;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uc->legion = c_legion;
|
||||
#endif
|
||||
|
||||
if (c_minute)
|
||||
uc->minute = atoi(c_minute);
|
||||
|
||||
if (c_hour)
|
||||
uc->hour = atoi(c_hour);
|
||||
|
||||
if (c_day)
|
||||
uc->day = atoi(c_day);
|
||||
|
||||
if (c_month)
|
||||
uc->month = atoi(c_month);
|
||||
|
||||
if (c_week)
|
||||
uc->week = atoi(c_week);
|
||||
|
||||
if (c_unique)
|
||||
uc->unique = atoi(c_unique);
|
||||
|
||||
if (c_harakiri) {
|
||||
if (atoi(c_harakiri)) {
|
||||
// harakiri > 0
|
||||
uc->mercy = atoi(c_harakiri);
|
||||
}
|
||||
else {
|
||||
// harakiri == 0
|
||||
uc->mercy = -1;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.cron_harakiri) {
|
||||
uc->harakiri = uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job >= 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// check for legion cron
|
||||
if (current_cron->legion) {
|
||||
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
|
||||
goto next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// skip unique crons that are still running
|
||||
if (current_cron->unique && current_cron->pid >= 0)
|
||||
goto next;
|
||||
|
||||
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job >= 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (current_cron->func) {
|
||||
current_cron->func(current_cron, now);
|
||||
}
|
||||
else {
|
||||
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
|
||||
if (pid >= 0) {
|
||||
current_cron->pid = pid;
|
||||
current_cron->started_at = now;
|
||||
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
|
||||
if (current_cron->mercy) {
|
||||
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
|
||||
if (current_cron->mercy > 0)
|
||||
current_cron->harakiri = now + current_cron->mercy;
|
||||
}
|
||||
else if (uwsgi.cron_harakiri)
|
||||
current_cron->harakiri = now + uwsgi.cron_harakiri;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
}
|
||||
|
||||
+110
-18
@@ -1,4 +1,4 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -42,6 +42,31 @@ void uwsgi_daemons_smart_check() {
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion) {
|
||||
if (uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// lord, spawn if not running
|
||||
if (ud->pid <= 0) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// not lord, kill daemon if running
|
||||
if (ud->pid > 0) {
|
||||
if (!kill(ud->pid, 0)) {
|
||||
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
|
||||
kill(-ud->pid, SIGTERM);
|
||||
}
|
||||
else {
|
||||
// pid already died
|
||||
ud->pid = -1;
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -70,12 +95,13 @@ void uwsgi_daemons_smart_check() {
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a dumb daemon dies and we do not wat to respawn it
|
||||
// this function is called when a dumb daemon dies and we do not want to respawn it
|
||||
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
}
|
||||
ud = ud->next;
|
||||
@@ -87,6 +113,15 @@ int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->pid == diedpid && ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion but not lord, don't respawn
|
||||
ud->pid = -1;
|
||||
uwsgi_log("uwsgi-daemons] legion \"%s\" daemon \"%s\" (pid: %d) annihilated\n", ud->legion, ud->command, (int) diedpid);
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
@@ -133,6 +168,20 @@ void uwsgi_daemons_spawn_all() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (!ud->registered) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
|
||||
// part of legion, register but don't spawn it yet
|
||||
if (ud->pidfile) {
|
||||
ud->pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (ud->pid > 0)
|
||||
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
|
||||
}
|
||||
ud->registered = 1;
|
||||
ud = ud->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ud->registered = 1;
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
@@ -146,7 +195,6 @@ void uwsgi_daemons_spawn_all() {
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -156,8 +204,29 @@ void uwsgi_daemons_spawn_all() {
|
||||
void uwsgi_detach_daemons() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && !ud->pidfile)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
#ifdef UWSGI_SSL
|
||||
// stop any legion daemon, doesn't matter if dumb or smart
|
||||
if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
|
||||
#else
|
||||
// stop only dumb daemons
|
||||
if (ud->pid > 0 && !ud->pidfile) {
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
// try to gracefully stop daemon, kill it if it won't die
|
||||
// if mercy is not set than wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, SIGTERM);
|
||||
sleep(1);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
kill(-ud->pid, SIGKILL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// unregister daemon to prevent it from being respawned
|
||||
ud->registered = 0;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
@@ -165,6 +234,9 @@ void uwsgi_detach_daemons() {
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
|
||||
@@ -208,18 +280,20 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -259,11 +333,26 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
char *pidfile = NULL;
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
char *space = NULL;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
|
||||
char *space = strchr(command, ' ');
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion = NULL;
|
||||
if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid legion daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
legion = command;
|
||||
command = space+1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
@@ -277,7 +366,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
freq = atoi(comma + 1);
|
||||
}
|
||||
command = space + 1;
|
||||
if (!strcmp(opt, "smart-attach-daemon2")) {
|
||||
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
|
||||
daemonize = 1;
|
||||
}
|
||||
}
|
||||
@@ -306,6 +395,9 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = legion;
|
||||
#endif
|
||||
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
|
||||
+280
-58
@@ -122,19 +122,101 @@ void uwsgi_emperor_blacklist_remove(char *id) {
|
||||
|
||||
struct uwsgi_emperor_scanner *emperor_scanners;
|
||||
|
||||
static int has_extra_extension(char *name) {
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(name, usl->value)) {
|
||||
return 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_emperor_is_valid(char *name) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
|
||||
|
||||
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
|
||||
|
||||
if (strlen(name) < 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *emperor_check_on_demand_socket(char *filename) {
|
||||
size_t len = 0;
|
||||
if (uwsgi.emperor_on_demand_extension) {
|
||||
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
|
||||
int fd = open(tmp, O_RDONLY);
|
||||
free(tmp);
|
||||
if (fd < 0) return NULL;
|
||||
char *ret = uwsgi_read_fd(fd, &len, 1);
|
||||
close(fd);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_directory) {
|
||||
// we need to build the socket path automagically
|
||||
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
|
||||
if (!start_of_vassal_name) {
|
||||
start_of_vassal_name = filename;
|
||||
}
|
||||
else {
|
||||
start_of_vassal_name++;
|
||||
}
|
||||
char *last_dot = uwsgi_get_last_char(filename, '.');
|
||||
if (!last_dot) return NULL;
|
||||
|
||||
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_exec) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("emperor_check_on_demand_socket()pipe()");
|
||||
return NULL;
|
||||
}
|
||||
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
|
||||
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
|
||||
free(cmd);
|
||||
if (r < 0) {
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return NULL;
|
||||
}
|
||||
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this is the monitor for non-glob directories
|
||||
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
struct uwsgi_instance *ui_current;
|
||||
@@ -160,10 +242,27 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(de->d_name, &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -175,7 +274,9 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(de->d_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
@@ -235,10 +336,27 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
uid_t t_uid = st.st_uid;
|
||||
gid_t t_gid = st.st_gid;
|
||||
|
||||
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
|
||||
struct stat lst;
|
||||
if (lstat(g.gl_pathv[i], &lst)) {
|
||||
uwsgi_error("[emperor-tyrant]/lstat()");
|
||||
if (ui_current) {
|
||||
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
t_uid = lst.st_uid;
|
||||
t_gid = lst.st_gid;
|
||||
}
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, stop the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
@@ -250,7 +368,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -377,6 +497,22 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
// over engineering...
|
||||
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
|
||||
return c_ui;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct uwsgi_instance *emperor_get(char *name) {
|
||||
|
||||
@@ -430,6 +566,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi.emperor_broodlord_count--;
|
||||
}
|
||||
|
||||
if (c_ui->socket_name) {
|
||||
free(c_ui->socket_name);
|
||||
}
|
||||
|
||||
free(c_ui);
|
||||
|
||||
}
|
||||
@@ -478,17 +618,10 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
uwsgi_log("[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) {
|
||||
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) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -544,8 +677,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
|
||||
memset(n_ui, 0, sizeof(struct uwsgi_instance));
|
||||
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
|
||||
|
||||
if (config) {
|
||||
n_ui->use_config = 1;
|
||||
@@ -576,10 +708,60 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
n_ui->first_run = uwsgi_now();
|
||||
n_ui->last_run = n_ui->first_run;
|
||||
n_ui->on_demand_fd = -1;
|
||||
if (socket_name) {
|
||||
n_ui->socket_name = uwsgi_str(socket_name);
|
||||
}
|
||||
|
||||
n_ui->pid = -1;
|
||||
|
||||
// ok here we check if we need to bind to the specified socket or continue with the activation
|
||||
if (socket_name) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
if (n_ui->on_demand_fd < 0) {
|
||||
uwsgi_error("emperor_add()/bind()");
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
|
||||
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi_emperor_vassal_start(n_ui)) {
|
||||
// clear the vassal
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
int i;
|
||||
char *colon = NULL;
|
||||
int counter;
|
||||
char **uenvs;
|
||||
char *uef;
|
||||
char **vassal_argv;
|
||||
pid_t pid;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
|
||||
@@ -587,7 +769,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
if (n_ui->use_config) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,6 +788,11 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
// close the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
close(n_ui->on_demand_fd);
|
||||
n_ui->on_demand_fd = -1;
|
||||
}
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
}
|
||||
@@ -625,13 +812,13 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
|
||||
if (setgid(gid)) {
|
||||
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)) {
|
||||
uwsgi_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -640,7 +827,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(uid)) {
|
||||
if (setuid(n_ui->uid)) {
|
||||
uwsgi_error("setuid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -678,15 +865,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
uenvs = environ;
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
free(oe);
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
|
||||
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
@@ -720,7 +908,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
@@ -728,34 +916,43 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
vassal_argv[2] = name;
|
||||
vassal_argv[2] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", name);
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", name);
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
@@ -768,18 +965,29 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
if (n_ui->on_demand_fd != 0) {
|
||||
if (dup2(n_ui->on_demand_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(n_ui->on_demand_fd);
|
||||
}
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
@@ -813,11 +1021,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
|
||||
@@ -975,6 +1179,8 @@ void emperor_loop() {
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.disable_nuclear_blast = 1;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
if (uwsgi.emperor_pidfile) {
|
||||
@@ -1087,14 +1293,24 @@ void emperor_loop() {
|
||||
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);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
// 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 {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
ui_current = emperor_get_by_socket_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
|
||||
if (uwsgi_emperor_vassal_start(ui_current)) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1120,7 +1336,9 @@ void emperor_loop() {
|
||||
has_children = 0;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
has_children++;
|
||||
if (ui_current->pid > -1) {
|
||||
has_children++;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.notify) {
|
||||
@@ -1172,7 +1390,7 @@ void emperor_loop() {
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
@@ -1266,7 +1484,7 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
|
||||
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
|
||||
goto end0;
|
||||
@@ -1285,6 +1503,9 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
|
||||
@@ -1403,6 +1624,7 @@ void uwsgi_emperor_start() {
|
||||
else {
|
||||
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_pid < 0) {
|
||||
uwsgi_error("pid()");
|
||||
exit(1);
|
||||
@@ -1436,7 +1658,7 @@ void uwsgi_check_emperor() {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
|
||||
|
||||
if (!uwsgi_emperor_is_valid(name))
|
||||
return;
|
||||
@@ -1473,6 +1695,6 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
new_config = uwsgi_str(config);
|
||||
new_config_len = strlen(new_config);
|
||||
}
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
+31
-14
@@ -260,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -282,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -293,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
@@ -376,12 +376,16 @@ void *event_queue_alloc(int nevents) {
|
||||
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
int eq = (long) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
@@ -423,7 +427,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
port_event_t *pe_i = &pe[i];
|
||||
if (pe_i->portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
|
||||
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
@@ -449,22 +453,26 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_get()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FD) {
|
||||
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
|
||||
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
|
||||
uwsgi_error("port_associate");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#else
|
||||
if (pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
#endif
|
||||
*interesting_fd = (long) pe.portev_user;
|
||||
}
|
||||
else {
|
||||
@@ -972,6 +980,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
|
||||
#ifdef PORT_SOURCE_FILE
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
|
||||
struct file_obj fo;
|
||||
@@ -1032,6 +1041,14 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
return -1;
|
||||
}
|
||||
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -322,7 +322,7 @@ void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
|
||||
|
||||
if (do_exit) goto check_catch;
|
||||
|
||||
if (wsgi_req && uwsgi.exception_handlers_instance) {
|
||||
if (uwsgi.exception_handlers_instance) {
|
||||
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
|
||||
if (ehi) {
|
||||
uwsgi_exception_run_handlers(ehi);
|
||||
@@ -442,7 +442,7 @@ static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret > 0) {
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
|
||||
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
|
||||
if (len > (ssize_t)(sizeof(long) + 1)) {
|
||||
size_t msg_size = len - sizeof(long);
|
||||
char *msg = buf + sizeof(long);
|
||||
@@ -488,7 +488,7 @@ void uwsgi_exception_setup_handlers() {
|
||||
}
|
||||
|
||||
void uwsgi_exceptions_handler_thread_start() {
|
||||
|
||||
if (!uwsgi.exception_handlers_instance) return;
|
||||
// start the exception_handler_thread
|
||||
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
|
||||
if (!uwsgi.exception_handler_thread) {
|
||||
|
||||
+10
-1
@@ -18,7 +18,9 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
}
|
||||
}
|
||||
|
||||
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
|
||||
char *str = uwsgi_num2str(num);
|
||||
char *fullname = uwsgi_concat3(name, " ", str);
|
||||
free(str);
|
||||
|
||||
ug = &ushared->gateways[ushared->gateways_cnt];
|
||||
ug->pid = 0;
|
||||
@@ -28,10 +30,17 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
|
||||
ug->fullname = fullname;
|
||||
ug->data = data;
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
|
||||
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
|
||||
+20
-6
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_INI
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
|
||||
This memory must not be freed for all the server lifecycle
|
||||
*/
|
||||
|
||||
static char *last_file = NULL;
|
||||
|
||||
void ini_rstrip(char *line) {
|
||||
|
||||
off_t i;
|
||||
@@ -91,6 +91,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
int got_section = 0;
|
||||
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
@@ -106,13 +107,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
if (colon[1] != 0) {
|
||||
section_asked = colon + 1;
|
||||
}
|
||||
|
||||
if (colon == file) {
|
||||
file = last_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (file[0] != 0) {
|
||||
if (file[0] != 0 && file != last_file) {
|
||||
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
if (file != last_file) {
|
||||
if (last_file) {
|
||||
free(last_file);
|
||||
}
|
||||
last_file = uwsgi_str(file);
|
||||
}
|
||||
|
||||
while (len) {
|
||||
ini_line = ini_get_line(ini, len);
|
||||
@@ -137,6 +148,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
val = ini_get_key(key);
|
||||
|
||||
if (!strcmp(section, section_asked)) {
|
||||
got_section = 1;
|
||||
ini_rstrip(key);
|
||||
val = ini_lstrip(val);
|
||||
ini_rstrip(val);
|
||||
@@ -151,11 +163,13 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
}
|
||||
|
||||
if (!got_section) {
|
||||
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
@@ -161,10 +161,17 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.empty = "";
|
||||
|
||||
#ifdef __linux__
|
||||
uwsgi.cgroup_dir_mode = "0700";
|
||||
#endif
|
||||
|
||||
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -347,6 +354,12 @@ void uwsgi_setup_workers() {
|
||||
// allocate signal table
|
||||
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
pid_t uwsgi_daemonize2() {
|
||||
|
||||
@@ -955,6 +955,8 @@ readok2:
|
||||
|
||||
int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffer *ub, size_t remains, int timeout) {
|
||||
|
||||
struct uwsgi_buffer *headers = NULL;
|
||||
|
||||
int fd = uwsgi_connect(addr, 0, 1);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
@@ -988,21 +990,110 @@ int uwsgi_proxy_nb(struct wsgi_request *wsgi_req, char *addr, struct uwsgi_buffe
|
||||
}
|
||||
|
||||
// read the response
|
||||
headers = uwsgi_buffer_new(8192);
|
||||
// max 64k headers
|
||||
ub->limit = UMAX16;
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
ssize_t rlen = uwsgi_read_true_nb(fd, buf, 8192, timeout);
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
if (headers) {
|
||||
if (uwsgi_buffer_append(headers, buf, rlen)) {
|
||||
goto end;
|
||||
}
|
||||
// check if we have a full HTTP response
|
||||
if (uwsgi_is_full_http(headers)) {
|
||||
int ret = uwsgi_blob_to_response(wsgi_req, headers->buf, headers->pos);
|
||||
if (ret) continue;
|
||||
uwsgi_buffer_destroy(headers);
|
||||
headers = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
end:
|
||||
if (headers) uwsgi_buffer_destroy(headers);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_file_write_do(struct uwsgi_string_list *usl) {
|
||||
|
||||
struct uwsgi_string_list *fl = usl;
|
||||
while(fl) {
|
||||
char *equal = strchr(fl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
FILE *f = fopen(fl->value, "w");
|
||||
if (!f) {
|
||||
uwsgi_error_open("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("writing \"%s\" to \"%s\" ...\n", equal+1, fl->value);
|
||||
if (fprintf(f, "%s\n", equal+1) <= 0 || ferror(f) || fclose(f)) {
|
||||
uwsgi_error("uwsgi_file_write_do()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to write empty value for \"%s\"\n", fl->value);
|
||||
exit(1);
|
||||
}
|
||||
*equal = '=';
|
||||
fl = fl->next;
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_fd_is_safe(int fd) {
|
||||
int i;
|
||||
for(i=0;i<uwsgi.safe_fds_cnt;i++) {
|
||||
if (uwsgi.safe_fds[i] == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void uwsgi_add_safe_fd(int fd) {
|
||||
// check if the fd is already safe
|
||||
if (uwsgi_fd_is_safe(fd)) return;
|
||||
|
||||
size_t len = sizeof(int) * (uwsgi.safe_fds_cnt+1);
|
||||
int *tmp = realloc(uwsgi.safe_fds, len);
|
||||
if (!tmp) {
|
||||
uwsgi_error("uwsgi_add_safe_fd()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.safe_fds = tmp;
|
||||
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
|
||||
uwsgi.safe_fds_cnt++;
|
||||
}
|
||||
|
||||
int uwsgi_is_again() {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
|
||||
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
-370
@@ -1,370 +0,0 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
#ifndef LDAP_OPT_SUCCESS
|
||||
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
|
||||
#endif
|
||||
|
||||
#ifndef ldap_unbind_ext_s
|
||||
#define ldap_unbind_ext_s ldap_unbind_ext
|
||||
#endif
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
char *ptr = uwsginame;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int) strlen(ldapname); i++) {
|
||||
if (isupper((int) ldapname[i])) {
|
||||
*ptr++ = '-';
|
||||
*ptr++ = tolower((int) ldapname[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++ = ldapname[i];
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
for (i = 0; i < (int) strlen(name); i++) {
|
||||
if (isupper((int) name[i])) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return strlen(name) + counter;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry {
|
||||
int num;
|
||||
char names[1024];
|
||||
int has_arg;
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_name_to_ldap(char *src, char *dst) {
|
||||
|
||||
int i;
|
||||
char *ptr = dst;
|
||||
|
||||
memset(dst, 0, 1024);
|
||||
|
||||
strcat(dst, " 'uWSGI");
|
||||
|
||||
ptr += 7;
|
||||
|
||||
for (i = 0; i < (int) strlen(src); i++) {
|
||||
if (src[i] == '-') {
|
||||
i++;
|
||||
*ptr++ = toupper((int) src[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
strcat(dst, "'");
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (ule->num == num) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
|
||||
int i;
|
||||
struct uwsgi_ldap_entry *ule;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ule = &root[i];
|
||||
if (uwsgi_list_has_str(ule->names, name + 1)) {
|
||||
return ule;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
char ldap_name[1024];
|
||||
|
||||
*count = 0;
|
||||
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
|
||||
|
||||
while (op && op->name) {
|
||||
|
||||
uwsgi_name_to_ldap((char *) op->name, ldap_name);
|
||||
|
||||
entry = search_ldap_cache(ule, ldap_name, *count);
|
||||
|
||||
if (entry)
|
||||
goto next;
|
||||
|
||||
entry = &ule[*count];
|
||||
entry->num = *count;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count + 1;
|
||||
|
||||
entry->has_arg = op->type;
|
||||
|
||||
next:
|
||||
op++;
|
||||
}
|
||||
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
|
||||
uwsgi_log("\n");
|
||||
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
|
||||
uwsgi_log("objectClass: olcSchemaConfig\n");
|
||||
uwsgi_log("cn: uwsgi\n");
|
||||
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
|
||||
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
uwsgi_log("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
|
||||
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
|
||||
|
||||
if (entry->has_arg) {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
|
||||
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
for (i = 0; i < items; i++) {
|
||||
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
BerElement *ber;
|
||||
struct berval **bervalues;
|
||||
char *attr;
|
||||
char *uwsgi_attr;
|
||||
|
||||
char *url_slash;
|
||||
|
||||
int desired_version = LDAP_VERSION3;
|
||||
int ret;
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (!ldap_is_ldap_url(url)) {
|
||||
uwsgi_log("invalid LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
|
||||
uwsgi_log("unable to parse LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
|
||||
|
||||
url_slash = strchr(url, '/');
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
if (url_slash) {
|
||||
url_slash[0] = 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP URL: %s\n", url);
|
||||
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
|
||||
#endif
|
||||
|
||||
#if LDAP_API_VERSION >= 3000
|
||||
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
|
||||
uwsgi_error("ldap_init()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP connection initialized %p\n", ldp);
|
||||
#endif
|
||||
|
||||
free(ldap_url);
|
||||
|
||||
if (ldap_count_entries(ldp, results) < 1) {
|
||||
uwsgi_log("no LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(ldp, results);
|
||||
|
||||
int found = 0;
|
||||
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
|
||||
if (!strncmp(attr, "uWSGI", 5)) {
|
||||
|
||||
found = 1;
|
||||
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
|
||||
if (!uwsgi_attr) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ldap2uwsgi(attr + 5, uwsgi_attr);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
|
||||
#endif
|
||||
bervalues = ldap_get_values_len(ldp, entry, attr);
|
||||
if (bervalues) {
|
||||
// do not free uwsgi_attr/uwsgi_val;
|
||||
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
|
||||
if (!uwsgi_val) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
|
||||
uwsgi_val[bervalues[0]->bv_len] = 0;
|
||||
|
||||
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
|
||||
free(bervalues);
|
||||
}
|
||||
else {
|
||||
free(uwsgi_attr);
|
||||
}
|
||||
}
|
||||
free(attr);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_log("no uWSGI LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(ber);
|
||||
free(results);
|
||||
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
+190
-34
@@ -81,6 +81,37 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a node is added or removed (heavy locking is needed)
|
||||
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
|
||||
uint64_t max_size = ul->scrolls_max_size;
|
||||
|
||||
// first, try to add myself
|
||||
if (ul->scroll_len + (uint64_t) 2 > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
ul->scroll_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char *ptr = ul->scrolls;
|
||||
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
|
||||
ul->scrolls_len = 2 + ul->scroll_len;
|
||||
// ok start adding nodes;
|
||||
struct uwsgi_legion_node *uln = ul->nodes_head;
|
||||
while(uln) {
|
||||
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
return;
|
||||
}
|
||||
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
|
||||
ul->scrolls_len += 2 + uln->scroll_len;
|
||||
uln = uln->next;
|
||||
}
|
||||
}
|
||||
|
||||
// critical section (remember to lock when you use it)
|
||||
struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
|
||||
@@ -104,6 +135,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
|
||||
ul->nodes_head = node;
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
|
||||
|
||||
@@ -141,6 +173,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
|
||||
}
|
||||
|
||||
free(node);
|
||||
|
||||
legion_rebuild_scrolls(ul);
|
||||
}
|
||||
|
||||
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
@@ -169,14 +203,22 @@ static void legions_check_nodes() {
|
||||
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
|
||||
if (now - node->last_seen > uwsgi.legion_tolerance) {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->valor > 0 ? "node" : "arbiter", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
// trigger node_left hooks
|
||||
struct uwsgi_string_list *usl = legion->node_left_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_left", legion, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_left hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -190,12 +232,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
|
||||
|
||||
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
uwsgi_log("[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
|
||||
while (nodes) {
|
||||
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
uwsgi_log("[uwsgi-legion-node] %s: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->valor > 0 ? "node" : "arbiter", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
|
||||
nodes = nodes->next;
|
||||
}
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n\n");
|
||||
uwsgi_log("[uwsgi-legion] --- END OF QUORUM REPORT ---\n");
|
||||
}
|
||||
|
||||
uint64_t uwsgi_legion_checksum(struct uwsgi_legion *ul) {
|
||||
@@ -231,12 +273,17 @@ static void legions_check_nodes_step2() {
|
||||
best_valor = node->valor;
|
||||
memcpy(best_uuid, node->uuid, 36);
|
||||
}
|
||||
else {
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
memset(best_uuid, 0, 36);
|
||||
}
|
||||
|
||||
// calculate the checksum
|
||||
uint64_t new_checksum = uwsgi_legion_checksum(ul);
|
||||
@@ -268,6 +315,18 @@ static void legions_check_nodes_step2() {
|
||||
|
||||
// we have quorum !!!
|
||||
if (votes > 0 && votes >= ul->quorum) {
|
||||
if (!ul->joined) {
|
||||
// triggering join hooks
|
||||
struct uwsgi_string_list *usl = ul->join_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("join", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->joined = 1;
|
||||
}
|
||||
// something changed ???
|
||||
if (ul->changed) {
|
||||
legions_report_quorum(ul, best_valor, best_uuid, votes);
|
||||
@@ -303,9 +362,9 @@ static void legions_check_nodes_step2() {
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
|
||||
if (ul->lord_scroll_len > 0) {
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n");
|
||||
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
|
||||
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("*********** End of the New Lord Scroll ***********\n");
|
||||
}
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
@@ -322,6 +381,20 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
else if (votes > 0 && votes < ul->quorum && (uwsgi_now() - ul->last_warning >= 60)) {
|
||||
uwsgi_log("[uwsgi-legion] no quorum: only %d vote(s) for Legion %s, %d needed to elect a Lord\n", votes, ul->legion, ul->quorum);
|
||||
// no more quorum, leave the Lord state
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] i cannot be The Lord of The Legion %s without a quorum ...\n", ul->legion);
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("unlord", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
ul->i_am_the_lord = 0;
|
||||
}
|
||||
ul->last_warning = uwsgi_now();
|
||||
}
|
||||
|
||||
@@ -341,6 +414,8 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
|
||||
struct uwsgi_legion_node *nodes = ul->nodes_head;
|
||||
while (nodes) {
|
||||
// skip arbiters
|
||||
if (nodes->valor == 0) goto next;
|
||||
if (nodes->valor > best_valor) {
|
||||
best_node = nodes;
|
||||
best_valor = nodes->valor;
|
||||
@@ -353,11 +428,12 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
memcpy(best_uuid, nodes->uuid, 36);
|
||||
}
|
||||
}
|
||||
next:
|
||||
nodes = nodes->next;
|
||||
}
|
||||
|
||||
// first round ?
|
||||
if (ul->lord_valor == 0) {
|
||||
// first round ? (skip first round if arbiter)
|
||||
if (ul->valor > 0 && ul->lord_valor == 0) {
|
||||
ul->changed = 1;
|
||||
}
|
||||
else if (best_valor != ul->lord_valor) {
|
||||
@@ -521,8 +597,19 @@ static void *legion_loop(void *foobar) {
|
||||
node->scroll_len = legion_msg.scroll_len;
|
||||
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
|
||||
}
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
// trigger node_joined hooks
|
||||
struct uwsgi_string_list *usl = ul->node_joined_hooks;
|
||||
while (usl) {
|
||||
int ret = uwsgi_legion_action_call("node_joined", ul, usl);
|
||||
if (ret) {
|
||||
uwsgi_log("[uwsgi-legion] ERROR, node_joined hook returned: %d\n", ret);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
node->last_seen = uwsgi_now();
|
||||
@@ -710,6 +797,21 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_mcast(char *opt, char *value, void *foobar) {
|
||||
uwsgi_opt_legion(opt, value, foobar);
|
||||
char *legion = uwsgi_str(value);
|
||||
char *space = strchr(legion, ' ');
|
||||
// over engineering
|
||||
if (!space) exit(1);
|
||||
*space = 0;
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_legion_register_node(ul, uwsgi_str(ul->addr));
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
@@ -727,15 +829,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
|
||||
char *port = strchr(usl->value, ':');
|
||||
uwsgi_legion_register_node(ul, space + 1);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
|
||||
char *port = strchr(addr, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
|
||||
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
// no need to zero the memory, socket_to_in_addr will do that
|
||||
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
|
||||
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
|
||||
usl->custom = socket_to_in_addr(addr, port, 0, sin);
|
||||
usl->custom_ptr = sin;
|
||||
}
|
||||
|
||||
@@ -787,51 +894,76 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *event = strchr(opt, '-');
|
||||
if (!event) {
|
||||
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_legion_register_hook(ul, event + 1, space + 1);
|
||||
}
|
||||
|
||||
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
if (!strcmp(opt, "legion-lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
|
||||
if (!strcmp(event, "lord")) {
|
||||
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
|
||||
else if (!strcmp(event, "unlord")) {
|
||||
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
|
||||
else if (!strcmp(event, "setup")) {
|
||||
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
|
||||
}
|
||||
else if (!strcmp(opt, "legion-death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
|
||||
else if (!strcmp(event, "death")) {
|
||||
usl = uwsgi_string_new_list(&ul->death_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "join")) {
|
||||
usl = uwsgi_string_new_list(&ul->join_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-joined")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_joined_hooks, action);
|
||||
}
|
||||
else if (!strcmp(event, "node-left")) {
|
||||
usl = uwsgi_string_new_list(&ul->node_left_hooks, action);
|
||||
}
|
||||
|
||||
else {
|
||||
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!usl)
|
||||
return;
|
||||
|
||||
char *port = strchr(usl->value, ':');
|
||||
if (!port) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
|
||||
char *hook = strchr(action, ':');
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// pointer to action plugin
|
||||
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
|
||||
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
|
||||
// add that to check the plugin value
|
||||
usl->custom = port - usl->value + 1;
|
||||
}
|
||||
usl->custom = hook - action + 1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -869,6 +1001,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
*colon = 0;
|
||||
char *secret = colon + 1;
|
||||
|
||||
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
|
||||
}
|
||||
|
||||
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
|
||||
char *iv = strchr(secret, ' ');
|
||||
if (iv) {
|
||||
*iv = 0;
|
||||
@@ -882,9 +1018,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
|
||||
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -937,10 +1073,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
uwsgi.legion_scroll_max_size = 4096;
|
||||
}
|
||||
|
||||
if (!uwsgi.legion_scroll_list_max_size) {
|
||||
uwsgi.legion_scroll_list_max_size = 32768;
|
||||
}
|
||||
|
||||
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
|
||||
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
|
||||
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
|
||||
@@ -1020,3 +1164,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (!legion) return NULL;
|
||||
uwsgi_rlock(legion->lock);
|
||||
buf = uwsgi_malloc(legion->scrolls_len);
|
||||
memcpy(buf, legion->scrolls, legion->scrolls_len);
|
||||
*rlen = legion->scrolls_len;
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
+13
-8
@@ -474,8 +474,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
@@ -661,7 +659,9 @@ ready:
|
||||
// application generic lock
|
||||
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
|
||||
for (i = 0; i < uwsgi.locks + 1; i++) {
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
|
||||
char *num = uwsgi_num2str(i);
|
||||
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
|
||||
free(num);
|
||||
}
|
||||
|
||||
// event queue lock (mitigate same event on multiple queues)
|
||||
@@ -679,9 +679,6 @@ ready:
|
||||
// timer table lock
|
||||
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
|
||||
|
||||
// probe table lock
|
||||
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
|
||||
|
||||
// rb_timer table lock
|
||||
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
|
||||
|
||||
@@ -767,10 +764,18 @@ nextlock:
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_user_lock(int lock_num) {
|
||||
int uwsgi_user_lock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_user_unlock(int lock_num) {
|
||||
int uwsgi_user_unlock(int lock_num) {
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return -1;
|
||||
}
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+7
-7
@@ -642,12 +642,8 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
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);
|
||||
#else
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
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;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
logvecpos++;
|
||||
@@ -677,7 +673,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
*vsz = syscall(356);
|
||||
uint64_t ret[2];
|
||||
ret[0] = 0; ret[1] = 0;
|
||||
syscall(358, ret);
|
||||
*vsz = ret[0];
|
||||
*rss = ret[1] * uwsgi.page_size;
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
|
||||
+60
-35
@@ -473,6 +473,30 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
|
||||
// update exec touches
|
||||
struct uwsgi_string_list *usl = uwsgi.touch_exec;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
@@ -638,22 +662,6 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_manage_command_cron(uwsgi_now());
|
||||
}
|
||||
|
||||
|
||||
// check for probes
|
||||
if (ushared->probes_cnt > 0) {
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
for (i = 0; i < ushared->probes_cnt; i++) {
|
||||
if (interesting_fd == -1) {
|
||||
// increment cycles
|
||||
ushared->probes[i].cycles++;
|
||||
}
|
||||
if (ushared->probes[i].func(interesting_fd, &ushared->probes[i])) {
|
||||
uwsgi_route_signal(ushared->probes[i].sig);
|
||||
}
|
||||
}
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
}
|
||||
|
||||
// some event returned
|
||||
if (rlen > 0) {
|
||||
// if the following function returns -1, a new worker has just spawned
|
||||
@@ -710,6 +718,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_master_check_gateways_deadline();
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
uwsgi_master_check_crons_deadline();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
@@ -764,6 +773,20 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
}
|
||||
}
|
||||
|
||||
// be sure to run it as the last touch check
|
||||
touched = uwsgi_check_touches(uwsgi.touch_exec);
|
||||
if (touched) {
|
||||
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -785,6 +808,7 @@ int master_loop(char **argv, char **environ) {
|
||||
if (uwsgi_master_check_mules_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid)) continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -798,8 +822,8 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
*/
|
||||
|
||||
uwsgi.mywid = find_worker_id(diedpid);
|
||||
if (uwsgi.mywid <= 0) {
|
||||
int thewid = find_worker_id(diedpid);
|
||||
if (thewid <= 0) {
|
||||
// check spooler, mules, gateways and daemons
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -842,50 +866,51 @@ next:
|
||||
|
||||
|
||||
// ok a worker died...
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
uwsgi.workers[thewid].pid = 0;
|
||||
// only to be safe :P
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[thewid].harakiri = 0;
|
||||
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
|
||||
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
|
||||
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are stopping workers, just end here
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
|
||||
else if (uwsgi.workers[thewid].cursed_at > 0) {
|
||||
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
|
||||
}
|
||||
// manage_next_request is zero, but killed by signal...
|
||||
else if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
|
||||
if (uwsgi.workers[thewid].cheaped == 1) {
|
||||
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -909,12 +934,12 @@ next:
|
||||
uwsgi.respawn_delta = last_respawn.tv_sec;
|
||||
|
||||
// are we chain reloading it ?
|
||||
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
|
||||
if (uwsgi.status.chain_reloading == thewid) {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
|
||||
// respawn the worker (if needed)
|
||||
if (uwsgi_respawn_worker(uwsgi.mywid))
|
||||
if (uwsgi_respawn_worker(thewid))
|
||||
return 0;
|
||||
|
||||
// end of the loop
|
||||
|
||||
@@ -177,6 +177,7 @@ void uwsgi_master_check_gateways_deadline() {
|
||||
if (ushared->gateways_harakiri[i] > 0) {
|
||||
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
|
||||
if (ushared->gateways[i].pid > 0) {
|
||||
uwsgi_log("*** HARAKIRI ON GATEWAY %s %d (pid: %d) ***\n", ushared->gateways[i].name, ushared->gateways[i].num, ushared->gateways[i].pid);
|
||||
kill(ushared->gateways[i].pid, SIGKILL);
|
||||
}
|
||||
ushared->gateways_harakiri[i] = 0;
|
||||
@@ -196,6 +197,14 @@ void uwsgi_master_check_mules_deadline() {
|
||||
uwsgi.mules[i].harakiri = 0;
|
||||
}
|
||||
}
|
||||
// user harakiri
|
||||
if (uwsgi.mules[i].user_harakiri > 0) {
|
||||
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
uwsgi.mules[i].user_harakiri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +216,11 @@ void uwsgi_master_check_spoolers_deadline() {
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->harakiri = 0;
|
||||
}
|
||||
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
|
||||
kill(uspool->pid, SIGKILL);
|
||||
uspool->user_harakiri = 0;
|
||||
}
|
||||
uspool = uspool->next;
|
||||
}
|
||||
}
|
||||
@@ -276,3 +290,29 @@ int uwsgi_worker_is_busy(int wid) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_master_check_cron_death(int diedpid) {
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid == (pid_t) diedpid) {
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
|
||||
uc->pid = -1;
|
||||
uc->started_at = 0;
|
||||
return -1;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_master_check_crons_deadline() {
|
||||
struct uwsgi_cron *uc = uwsgi.crons;
|
||||
while (uc) {
|
||||
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
|
||||
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
|
||||
kill(-uc->pid, SIGKILL);
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+152
-180
@@ -351,6 +351,9 @@ void uwsgi_reload(char **argv) {
|
||||
/* check fd table (a module can obviosly open some fd on initialization...) */
|
||||
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
|
||||
if (uwsgi_fd_is_safe(i)) continue;
|
||||
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
@@ -385,6 +388,12 @@ void uwsgi_reload(char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.alarm_thread) {
|
||||
if (i == uwsgi.alarm_thread->queue) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[0]) continue;
|
||||
if (i == uwsgi.alarm_thread->pipe[1]) continue;
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
@@ -413,9 +422,13 @@ void uwsgi_reload(char **argv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
#ifndef UWSGI_IPCSEM_ATEXIT
|
||||
// free ipc semaphores if in use
|
||||
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_ipcsem_clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
@@ -436,7 +449,6 @@ void uwsgi_reload(char **argv) {
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -634,178 +646,6 @@ int uwsgi_respawn_worker(int wid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
for (i = 0; i < ushared->cron_cnt; i++) {
|
||||
|
||||
struct uwsgi_cron *ucron = &ushared->cron[i];
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = ucron->minute;
|
||||
uc_hour = ucron->hour;
|
||||
uc_day = ucron->day;
|
||||
uc_month = ucron->month;
|
||||
uc_week = ucron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day >= 0 && ucron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (now - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("localtime()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
struct tm *uwsgi_cron_delta;
|
||||
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
uwsgi_error("localtime()");
|
||||
return;
|
||||
}
|
||||
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
uc_minute = current_cron->minute;
|
||||
uc_hour = current_cron->hour;
|
||||
uc_day = current_cron->day;
|
||||
uc_month = current_cron->month;
|
||||
uc_week = current_cron->week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (current_cron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (current_cron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (current_cron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (current_cron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (now - current_cron->last_job > 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
|
||||
}
|
||||
}
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
current_cron = current_cron->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
int i;
|
||||
@@ -856,11 +696,20 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
while (ud) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) (ud->respawns - 1)))
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
|
||||
goto end;
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
@@ -944,7 +793,10 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "full", (unsigned long long) uc->full))
|
||||
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
@@ -957,6 +809,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
@@ -1233,6 +1088,68 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
struct uwsgi_cron *ucron = uwsgi.crons;
|
||||
if (ucron) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_key(us, "crons"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
while (ucron) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
goto end;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
|
||||
goto end;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
|
||||
goto end;
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
ucron = ucron->next;
|
||||
if (ucron) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
struct uwsgi_legion *legion = NULL;
|
||||
if (uwsgi.legions) {
|
||||
@@ -1486,3 +1403,58 @@ void uwsgi_master_fix_request_counters() {
|
||||
uwsgi.workers[0].requests = total_counter;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uc_minute = minute;
|
||||
uc_hour = hour;
|
||||
uc_day = day;
|
||||
uc_month = month;
|
||||
uc_week = week;
|
||||
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (day >= 0 && week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return run_task;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
|
||||
uWSGI metrics subsystem
|
||||
|
||||
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
|
||||
|
||||
uwsgi.worker.1.requests
|
||||
uwsgi.custom.foo.bar
|
||||
|
||||
the oid representation:
|
||||
|
||||
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
|
||||
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
|
||||
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
|
||||
...
|
||||
|
||||
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
|
||||
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
|
||||
|
||||
gauge
|
||||
counter
|
||||
absolute
|
||||
|
||||
both 32 and 64bit, both signed and unsigned
|
||||
|
||||
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
|
||||
but you can cache lookups in a uWSGI cache for really big list.
|
||||
|
||||
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
|
||||
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
|
||||
|
||||
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
|
||||
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
|
||||
|
||||
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
|
||||
|
||||
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
|
||||
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
|
||||
to even modify the values manually)
|
||||
|
||||
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
|
||||
|
||||
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
|
||||
|
||||
uwsgi.metric_set("worker.1.requests", N)
|
||||
uwsgi.metric_inc("worker.1.requests", N=1)
|
||||
uwsgi.metric_dec("worker.1.requests", N=1)
|
||||
uwsgi.metric_mul("worker.1.requests", N=1)
|
||||
uwsgi.metric_div("worker.1.requests", N=1)
|
||||
|
||||
and obviously they can get values:
|
||||
|
||||
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
|
||||
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
|
||||
|
||||
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
|
||||
|
||||
Metrics can be updated from the internal routing subsystem too:
|
||||
|
||||
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
|
||||
|
||||
and can be accessed as ${metric[foobar.test]}
|
||||
|
||||
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_metric {
|
||||
char *name;
|
||||
char *oid;
|
||||
|
||||
// pre-computed snmp representation
|
||||
char *asn;
|
||||
size_t asn_size;
|
||||
|
||||
// ABSOLUTE/COUNTER/GAUGE
|
||||
uint8_t type;
|
||||
|
||||
// MANUAL/PTR/FUNC/FILE
|
||||
uint8_t collect_way
|
||||
|
||||
// this could be taken from a file storage and must laways be added to value when reporting (default 0)
|
||||
int64_t initial_value;
|
||||
// the value of the metric (point to a shared memory area)
|
||||
*int64_t value;
|
||||
|
||||
// a custom blob you can attach to a metric
|
||||
void *custom;
|
||||
|
||||
// the collection frequency
|
||||
uint32_t freq;
|
||||
time_t last_update;
|
||||
|
||||
// run this function to collect the value
|
||||
int64_t (*collector)(struct uwsgi_metric *);
|
||||
// take the value from this pointer to a 64bit value
|
||||
int64_t *ptr;
|
||||
// get the initial value from this file, and store each update in it
|
||||
char *filename;
|
||||
|
||||
struct uwsgi_metric *next;
|
||||
};
|
||||
|
||||
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
|
||||
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
|
||||
|
||||
while(metric) {
|
||||
metric = metric->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_metric_loop() {
|
||||
// every second scan the whole metrics tree
|
||||
time_t now = uwsgi_now();
|
||||
}
|
||||
|
||||
int64_t uwsgi_metric_get(char *name, char *oid) {
|
||||
struct uwsgi_metric *um = NULL;
|
||||
if (name) {
|
||||
um = uwsgi_metric_find_by_name(name);
|
||||
}
|
||||
else if (oid) {
|
||||
um = uwsgi_metric_find_by_oid(oid);
|
||||
}
|
||||
if (!um) return 0;
|
||||
|
||||
//
|
||||
switch(um->collect_way) {
|
||||
case UWSGI_METRIC_MANUAL:
|
||||
return um->initial_value+*um->value;
|
||||
case UWSGI_METRIC_PTR:
|
||||
return um->initial_value+*um->ptr;
|
||||
case UWSGI_METRIC_FUNC:
|
||||
case UWSGI_METRIC_FILE:
|
||||
}
|
||||
}
|
||||
+29
-19
@@ -77,19 +77,8 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_run();
|
||||
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
@@ -98,6 +87,23 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_run() {
|
||||
int id = uwsgi.muleid;
|
||||
int i;
|
||||
if (uwsgi.mules[id - 1].patch) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here ?
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
@@ -184,6 +190,7 @@ void uwsgi_mule_handler() {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -197,7 +204,9 @@ void uwsgi_mule_handler() {
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("uwsgi_mule_handler/read()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i, found = 0;
|
||||
@@ -343,6 +352,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -350,7 +360,7 @@ next:
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
@@ -406,12 +416,12 @@ void uwsgi_setup_mules_and_farms() {
|
||||
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
|
||||
|
||||
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
|
||||
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
|
||||
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.mules[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.mules[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
uwsgi.mules[i].id = i + 1;
|
||||
|
||||
@@ -437,11 +447,11 @@ void uwsgi_setup_mules_and_farms() {
|
||||
mules_list++;
|
||||
|
||||
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
|
||||
free(farm_value);
|
||||
|
||||
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_signal_pipe(uwsgi.farms[i].queue_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
@@ -458,7 +468,7 @@ void uwsgi_setup_mules_and_farms() {
|
||||
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
|
||||
|
||||
farm_name = farm_name->next;
|
||||
|
||||
free(farm_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+151
-2
@@ -58,6 +58,39 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offload engine:
|
||||
fd -> the file descriptor to read from
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (uor->fd < 0 || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
memory offload engine:
|
||||
buf -> pointer to the memory to transfer (memory is freed at the end)
|
||||
len -> amount of data to transfer
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->buf || !uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
transfer offload engine:
|
||||
@@ -66,13 +99,13 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
|
||||
*/
|
||||
|
||||
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uor->name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uor->fd = uwsgi_connect(uor->ubuf->buf, 0, 1);
|
||||
uor->fd = uwsgi_connect(uor->name, 0, 1);
|
||||
if (uor->fd < 0) {
|
||||
uwsgi_error("u_offload_transfer_prepare()/connect()");
|
||||
return -1;
|
||||
@@ -240,6 +273,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
|
||||
return uwsgi_thread_new(uwsgi_offload_loop);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
offload memory transfer
|
||||
|
||||
uor->len -> the size of the memory chunk
|
||||
uor->buf -> the memory to transfer
|
||||
uor->written -> written bytes
|
||||
|
||||
status: none
|
||||
|
||||
*/
|
||||
|
||||
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
if (fd == -1) {
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
return 0;
|
||||
}
|
||||
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
|
||||
if (rlen > 0) {
|
||||
uor->written += rlen;
|
||||
if (uor->written >= uor->len) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_memory_do()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
the offload task starts after having acquired the file fd
|
||||
@@ -293,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pipe offloading
|
||||
status:
|
||||
0 -> waiting for data on fd
|
||||
1 -> waiting for write to s
|
||||
*/
|
||||
|
||||
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
|
||||
|
||||
ssize_t rlen;
|
||||
|
||||
// setup
|
||||
if (fd == -1) {
|
||||
event_queue_add_fd_read(ut->queue, uor->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(uor->status) {
|
||||
// read event from fd
|
||||
case 0:
|
||||
if (!uor->buf) {
|
||||
uor->buf = uwsgi_malloc(4096);
|
||||
}
|
||||
rlen = read(uor->fd, uor->buf, 4096);
|
||||
if (rlen > 0) {
|
||||
uor->to_write = rlen;
|
||||
uor->pos = 0;
|
||||
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
|
||||
uor->status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> read()");
|
||||
}
|
||||
return -1;
|
||||
// write event on s
|
||||
case 1:
|
||||
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
|
||||
if (rlen > 0) {
|
||||
uor->to_write -= rlen;
|
||||
uor->pos += rlen;
|
||||
if (uor->to_write == 0) {
|
||||
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
|
||||
uor->status = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (rlen < 0) {
|
||||
uwsgi_offload_retry
|
||||
uwsgi_error("u_offload_pipe_do() -> write()");
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
the offload task starts soon after the call to connect()
|
||||
|
||||
@@ -490,6 +621,8 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre
|
||||
void uwsgi_offload_engines_register_all() {
|
||||
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
|
||||
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
|
||||
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
|
||||
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
@@ -507,3 +640,19 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname
|
||||
uor.ubuf = ubuf;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
|
||||
uor.buf = buf;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
|
||||
struct uwsgi_offload_request uor;
|
||||
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
|
||||
uor.fd = fd;
|
||||
uor.len = len;
|
||||
return uwsgi_offload_run(wsgi_req, &uor, NULL);
|
||||
}
|
||||
|
||||
+106
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// this is line uwsgi_str_num but with security checks
|
||||
// this is like uwsgi_str_num but with security checks
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0;
|
||||
@@ -80,7 +80,7 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
ret = sendto(fd, (char *) uh, message_size + 4, 0, (struct sockaddr *) &un_addr, sizeof(un_addr));
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
uwsgi_error("send_udp_message()/sendto()");
|
||||
}
|
||||
close(fd);
|
||||
|
||||
@@ -303,8 +303,41 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
uint16_t rlen = 0;
|
||||
uint16_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == ',') break;
|
||||
rlen++;
|
||||
}
|
||||
|
||||
// bytes=X-
|
||||
if (rlen < 8) return;
|
||||
char *equal = memchr(buf, '=', rlen);
|
||||
if (!equal) return;
|
||||
if (equal-buf != 5) return;
|
||||
if (memcmp(buf, "bytes", 5)) return;
|
||||
char *range = equal+1;
|
||||
rlen -= 6;
|
||||
char *dash = memchr(range, '-', rlen);
|
||||
if (!dash) return;
|
||||
*from = uwsgi_str_num(range, dash-range);
|
||||
*to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
|
||||
if (*to > 0 && *from > *to) {
|
||||
*from = 0;
|
||||
*to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
|
||||
|
||||
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
|
||||
uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
|
||||
wsgi_req->file = buf;
|
||||
wsgi_req->file_len = len;
|
||||
@@ -312,6 +345,12 @@ static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,6 +393,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
|
||||
wsgi_req->cookie = buf;
|
||||
wsgi_req->cookie_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
|
||||
wsgi_req->appid = buf;
|
||||
wsgi_req->appid_len = len;
|
||||
@@ -409,8 +455,8 @@ static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
|
||||
wsgi_req->pyhome = buf;
|
||||
wsgi_req->pyhome_len = len;
|
||||
wsgi_req->home = buf;
|
||||
wsgi_req->home_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -693,7 +739,7 @@ next:
|
||||
// check if data are available in the local cache
|
||||
if (wsgi_req->cache_get_len > 0) {
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -704,7 +750,7 @@ next:
|
||||
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
|
||||
|
||||
uint64_t cache_value_size;
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL);
|
||||
char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
|
||||
if (cache_value && cache_value_size > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
|
||||
free(cache_value);
|
||||
@@ -961,6 +1007,60 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
|
||||
|
||||
}
|
||||
|
||||
|
||||
// this functions transform a raw HTTP response to a uWSGI-managed response
|
||||
int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
|
||||
char *line = body;
|
||||
size_t line_len = 0;
|
||||
size_t i;
|
||||
int status_managed = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (body[i] == '\n') {
|
||||
// invalid line
|
||||
if (line_len < 1) {
|
||||
return -1;
|
||||
}
|
||||
if (line[line_len-1] != '\r') {
|
||||
return -1;
|
||||
}
|
||||
// end of the headers
|
||||
if (line_len == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status_managed) {
|
||||
char *colon = memchr(line, ':', line_len-1);
|
||||
if (!colon) return -1;
|
||||
if (colon[1] != ' ') return -1;
|
||||
if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
|
||||
}
|
||||
else {
|
||||
char *space = memchr(line, ' ', line_len-1);
|
||||
if (!space) return -1;
|
||||
if ((line_len-1) - ((space+1)-line) < 3) return -1;
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
|
||||
status_managed = 1;
|
||||
}
|
||||
line = NULL;
|
||||
line_len = 0;
|
||||
}
|
||||
else {
|
||||
if (!line) {
|
||||
line = body + i;
|
||||
}
|
||||
line_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i+1) < len) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
QUERY_STRING management functions (mainly used by the internal routing subsystem)
|
||||
|
||||
*/
|
||||
|
||||
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
// search for the equal sign
|
||||
char *equal = memchr(qs, '=', qs_len);
|
||||
if (!equal) return NULL;
|
||||
|
||||
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qs_len -= (equal-qs)+1;
|
||||
if (qs_len == 0) return NULL;
|
||||
|
||||
*vallen = qs_len;
|
||||
return equal+1;
|
||||
}
|
||||
|
||||
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
uint16_t i;
|
||||
|
||||
char *qs = wsgi_req->query_string;
|
||||
uint16_t qs_len = 0;
|
||||
char *ptr = wsgi_req->query_string;
|
||||
//start splitting by ;
|
||||
for(i=0;i<wsgi_req->query_string_len;i++) {
|
||||
if (!qs) {
|
||||
qs = ptr + i;
|
||||
}
|
||||
if (ptr[i] == '&') {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
qs_len = 0;
|
||||
qs = NULL;
|
||||
}
|
||||
else {
|
||||
qs_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qs_len > 0) {
|
||||
char *value = check_qs(qs, qs_len, key, keylen, vallen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+17
-17
@@ -47,7 +47,7 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
|
||||
if (uwsgi.post_buffering) {
|
||||
if (pos < 0) {
|
||||
if (pos > (off_t) wsgi_req->post_pos) {
|
||||
if ((off_t) wsgi_req->post_pos - pos < 0) {
|
||||
wsgi_req->post_pos = 0;
|
||||
return;
|
||||
}
|
||||
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
|
||||
|
||||
// read from a file
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read from post_buffering memory
|
||||
if (uwsgi.post_buffering) {
|
||||
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
|
||||
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
|
||||
wsgi_req->post_pos += remains;
|
||||
wsgi_req->post_readline_watermark += remains;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from socket
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
ret = uwsgi_wait_read_req(wsgi_req);
|
||||
if (ret > 0) {
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
|
||||
if (len > 0) {
|
||||
wsgi_req->post_pos += len;
|
||||
wsgi_req->post_readline_watermark += len;
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
else if (ret == 0) {
|
||||
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_timeout(remains);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
|
||||
uwsgi_read_error(remains);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_log("%llu\n", remains);
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
return NULL;
|
||||
}
|
||||
@@ -478,9 +478,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
int upload_progress_fd = -1;
|
||||
char *upload_progress_filename = NULL;
|
||||
|
||||
wsgi_req->post_file = tmpfile();
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+1059
-59
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -1,8 +1,8 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
|
||||
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
|
||||
|
||||
struct uwsgi_rpc *urpc;
|
||||
int ret = -1;
|
||||
@@ -30,7 +30,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
||||
already:
|
||||
memcpy(urpc->name, name, strlen(name));
|
||||
urpc->modifier1 = modifier1;
|
||||
urpc->plugin = plugin;
|
||||
urpc->args = args;
|
||||
urpc->func = func;
|
||||
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
||||
@@ -77,8 +77,8 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
}
|
||||
|
||||
if (urpc) {
|
||||
if (uwsgi.p[urpc->modifier1]->rpc) {
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
|
||||
if (urpc->plugin->rpc) {
|
||||
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,3 +37,39 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
simple non blocking sendfile implementation
|
||||
(generally used as fallback)
|
||||
*/
|
||||
|
||||
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_sendfile()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() {
|
||||
//now close all the unbound fd
|
||||
for (j = 3; j < (int) uwsgi.max_fd; j++) {
|
||||
int useless = 1;
|
||||
|
||||
if (uwsgi_fd_is_safe(j)) continue;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (j == uwsgi.emperor_fd)
|
||||
continue;
|
||||
@@ -123,6 +126,16 @@ void uwsgi_setup_inherited_sockets() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (j == uwsgi.original_log_fd)
|
||||
continue;
|
||||
|
||||
+8
-141
@@ -99,7 +99,10 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
if (!uwsgi.master_process) {
|
||||
uwsgi_log("you cannot register signals without a master\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
||||
uwsgi_log("only the master and the workers can register signal handlers\n");
|
||||
@@ -137,7 +140,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
int pos = (i * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,89 +180,10 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
|
||||
if (!uwsgi_up) {
|
||||
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
uwsgi_up = *up;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_up) {
|
||||
old_up = uwsgi_up;
|
||||
uwsgi_up = uwsgi_up->next;
|
||||
}
|
||||
|
||||
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
|
||||
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
|
||||
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
|
||||
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while (up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fill the probe table
|
||||
ushared->probes[ushared->probes_cnt].func = up->func;
|
||||
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
|
||||
ushared->probes[ushared->probes_cnt].registered = 0;
|
||||
ushared->probes[ushared->probes_cnt].sig = sig;
|
||||
ushared->probes[ushared->probes_cnt].fd = -1;
|
||||
ushared->probes[ushared->probes_cnt].state = 0;
|
||||
ushared->probes[ushared->probes_cnt].last_event = 0;
|
||||
ushared->probes[ushared->probes_cnt].data = NULL;
|
||||
ushared->probes[ushared->probes_cnt].cycles = 0;
|
||||
ushared->probes[ushared->probes_cnt].bad = 0;
|
||||
|
||||
if (!timeout) {
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].timeout = timeout;
|
||||
if (!freq) {
|
||||
freq = 1;
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].freq = freq;
|
||||
ushared->probes_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
|
||||
if (ushared->timers_cnt < 64) {
|
||||
@@ -282,63 +206,6 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value + i;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
@@ -595,7 +462,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
|
||||
+123
-25
@@ -2,6 +2,10 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int connect_to_unix(char *, int, int);
|
||||
static int connect_to_tcp(char *, int, int, int);
|
||||
static int connect_to_udp(char *, int);
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
@@ -66,6 +70,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -85,6 +90,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
@@ -100,6 +106,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (strlen(socket_name) > 102) {
|
||||
uwsgi_log("invalid socket name\n");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socket_name[0] == '@') {
|
||||
@@ -113,6 +120,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (uws_addr == NULL) {
|
||||
uwsgi_error("malloc()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
@@ -120,6 +128,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -131,6 +140,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
if (socket_name[0] == '@') {
|
||||
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
|
||||
@@ -157,12 +184,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
@@ -287,36 +316,46 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_connect_do(char *socket_name, int timeout, int async) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
return connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
}
|
||||
|
||||
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
|
||||
|
||||
int fd;
|
||||
|
||||
char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
|
||||
fd = uwsgi_connect(zeroed_socket_name, timeout, async);
|
||||
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_connect(char *socket_name, int timeout, int async) {
|
||||
|
||||
int ret;
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
ret = connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
|
||||
// reset the socket name
|
||||
tcp_port--;
|
||||
tcp_port[0] = ':';
|
||||
return ret;
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout, async);
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
int uwsgi_connect_udp(char *socket_name) {
|
||||
int fd = -1;
|
||||
char *zeroed_socket_name = uwsgi_str(socket_name);
|
||||
char *udp_port = strchr(zeroed_socket_name, ':');
|
||||
if (!udp_port) goto end;
|
||||
*udp_port = 0;
|
||||
udp_port++;
|
||||
fd = connect_to_udp(zeroed_socket_name, atoi(udp_port));
|
||||
end:
|
||||
free(zeroed_socket_name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_un uws_addr;
|
||||
@@ -361,7 +400,7 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_in uws_addr;
|
||||
@@ -378,15 +417,13 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
socket_name[strlen(socket_name)] = ':';
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_error("connect_to_tcp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -402,6 +439,38 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
}
|
||||
|
||||
static int connect_to_udp(char *socket_name, int port) {
|
||||
|
||||
struct sockaddr_in uws_addr;
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
uws_addr.sin_family = AF_INET;
|
||||
uws_addr.sin_port = htons(port);
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
uws_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("connect_to_udp()/socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *generate_socket_name(char *socket_name) {
|
||||
|
||||
char *asterisk = strchr(socket_name, '*');
|
||||
@@ -578,11 +647,31 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.so_sndbuf) {
|
||||
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_SNDBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.so_rcvbuf) {
|
||||
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
|
||||
uwsgi_error("SO_RCVBUF setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -593,6 +682,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("IP_FREEBIND setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -602,6 +692,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEPORT setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
@@ -628,6 +719,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
|
||||
uwsgi_error("SO_SNDTIMEO setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,6 +754,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -669,12 +762,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1457,6 +1552,9 @@ void uwsgi_setup_shared_sockets() {
|
||||
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
shared_sock->family = AF_UNIX;
|
||||
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef AF_INET6
|
||||
|
||||
+21
-16
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
// avoid race conditions !!!
|
||||
@@ -123,21 +122,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
|
||||
@@ -146,6 +131,26 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
void uwsgi_spooler_run() {
|
||||
int i;
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->spooler_init) {
|
||||
uwsgi.p[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->spooler_init) {
|
||||
uwsgi.gp[i]->spooler_init();
|
||||
}
|
||||
}
|
||||
|
||||
spooler(uspool);
|
||||
}
|
||||
|
||||
void destroy_spool(char *dir, char *file) {
|
||||
|
||||
if (chdir(dir)) {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef UWSGI_SQLITE3
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
|
||||
// make a copy of the string
|
||||
if (field_count >= 2) {
|
||||
size_t value_len = strlen(fields[1]) + 1;
|
||||
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
|
||||
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
|
||||
|
||||
sqlite3 *db;
|
||||
char *err = NULL;
|
||||
char *query = "SELECT * FROM uwsgi";
|
||||
|
||||
char *colon = uwsgi_get_last_char(file, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
query = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
|
||||
|
||||
#ifdef sqlite3_open_v2
|
||||
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
|
||||
#else
|
||||
if (sqlite3_open(file, &db)) {
|
||||
#endif
|
||||
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
|
||||
uwsgi_log("sqlite3 error: %s\n", err);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+21
-4
@@ -1,5 +1,7 @@
|
||||
#include "../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
/*
|
||||
@@ -252,8 +254,14 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
|
||||
if (!uwsgi.ssl_sessions_cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
// check for default cache
|
||||
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
|
||||
uwsgi.ssl_sessions_cache = uwsgi.caches;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.ssl_sessions_cache->max_items) {
|
||||
@@ -406,8 +414,9 @@ char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
|
||||
}
|
||||
|
||||
char *uwsgi_ssl_rand(size_t len) {
|
||||
unsigned char *buf = uwsgi_calloc(len+1);
|
||||
unsigned char *buf = uwsgi_calloc(len);
|
||||
if (RAND_bytes(buf, len) <= 0) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
return (char *) buf;
|
||||
@@ -421,6 +430,14 @@ char *uwsgi_sha1(char *src, size_t len, char *dst) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_md5(char *src, size_t len, char *dst) {
|
||||
MD5_CTX md5;
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, src, len);
|
||||
MD5_Final((unsigned char *)dst, &md5);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
|
||||
SHA_CTX sha;
|
||||
SHA1_Init(&sha);
|
||||
|
||||
+72
-36
@@ -2,9 +2,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
|
||||
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
|
||||
// check for filename size
|
||||
if (filename_len + 4 > PATH_MAX) return 0;
|
||||
if (*filename_len + 4 > PATH_MAX) return 0;
|
||||
// check for supported encodings
|
||||
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
|
||||
|
||||
@@ -14,7 +14,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for dirs/prefix
|
||||
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
|
||||
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -23,7 +23,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for ext/suffix
|
||||
usl = uwsgi.static_gzip_ext;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto gzip;
|
||||
}
|
||||
usl = usl->next;
|
||||
@@ -33,7 +33,7 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
// check for regexp
|
||||
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
|
||||
goto gzip;
|
||||
}
|
||||
url = url->next;
|
||||
@@ -43,19 +43,19 @@ int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t
|
||||
|
||||
gzip:
|
||||
|
||||
memcpy(filename + filename_len, ".gz\0", 4);
|
||||
filename_len += 3;
|
||||
memcpy(filename + *filename_len, ".gz\0", 4);
|
||||
*filename_len += 3;
|
||||
|
||||
if (stat(filename, st)) {
|
||||
filename_len -= 3;
|
||||
filename[filename_len] = 0;
|
||||
*filename_len -= 3;
|
||||
filename[*filename_len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_http_date(time_t t, char *dst) {
|
||||
int uwsgi_http_date(time_t t, char *dst) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -179,7 +179,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int m
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -228,7 +228,7 @@ int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filenam
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st)
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now + delta, expires);
|
||||
int size = uwsgi_http_date(now + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
while (udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime + delta, expires);
|
||||
int size = uwsgi_http_date(st->st_mtime + delta, expires);
|
||||
if (size > 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
|
||||
#endif
|
||||
|
||||
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
@@ -333,6 +333,10 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while (udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
@@ -361,11 +365,16 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -429,16 +438,14 @@ static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size
|
||||
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
int mime_type_size = 0;
|
||||
size_t mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&uwsgi.lock_static);
|
||||
int use_gzip = 0;
|
||||
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
|
||||
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
@@ -451,8 +458,32 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
@@ -460,6 +491,10 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_add_expires_uri(wsgi_req, st);
|
||||
#endif
|
||||
|
||||
if (use_gzip) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
}
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
|
||||
@@ -474,25 +509,25 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// apache
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
|
||||
// this is the final header (\r\n added)
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
}
|
||||
// raw
|
||||
else {
|
||||
// here we need to choose if we want the gzip variant;
|
||||
if (uwsgi_static_want_gzip(wsgi_req, real_filename, real_filename_len, st)) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
|
||||
// set Content-Length (to fsize NOT st->st_size)
|
||||
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
// here use the original size !!!
|
||||
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
|
||||
}
|
||||
// set Content-Length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
|
||||
int size = set_http_date(st->st_mtime, http_last_modified);
|
||||
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
|
||||
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
|
||||
|
||||
// if it is a HEAD request just skip transfer
|
||||
@@ -506,7 +541,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
int fd = open(real_filename, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
// fd will be closed in the following function
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st->st_size);
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
|
||||
}
|
||||
|
||||
wsgi_req->status = 200;
|
||||
@@ -544,6 +579,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
if (item && item_len > 0 && item_len <= PATH_MAX) {
|
||||
memcpy(real_filename, item, item_len);
|
||||
real_filename_len = item_len;
|
||||
real_filename[real_filename_len] = 0;
|
||||
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
|
||||
goto found;
|
||||
}
|
||||
@@ -609,7 +645,7 @@ safe:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
|
||||
+42
-1
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
|
||||
if (uwsgi_stats_apply_tabs(us))
|
||||
return -1;
|
||||
|
||||
char *ptr = us->base + us->pos;
|
||||
char *watermark = us->base + us->size;
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
if (!new_base)
|
||||
return -1;
|
||||
us->base = new_base;
|
||||
us->size += us->chunk;
|
||||
ptr = us->base + us->pos;
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
us->pos += ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
|
||||
int ret = uwsgi_stats_keyslong(us, key, num);
|
||||
if (ret)
|
||||
return -1;
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
@@ -383,7 +422,9 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
|
||||
|
||||
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
|
||||
uspi->pusher = pusher;
|
||||
uspi->arg = uwsgi_str(arg);
|
||||
if (arg) {
|
||||
uspi->arg = uwsgi_str(arg);
|
||||
}
|
||||
uspi->raw = pusher->raw;
|
||||
if (old_uspi) {
|
||||
old_uspi->next = uspi;
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
uWSGI transformations
|
||||
|
||||
each body chunk is passed (in chain) to every transformation
|
||||
|
||||
some of them supports streaming, other requires buffering
|
||||
|
||||
at the end of the request the "final chain" is called (and the whole chain freed)
|
||||
|
||||
Transformations (if required) could completely swallow already set headers
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// -1 error, 0 = no buffer, send the body, 1 = buffer
|
||||
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
char *t_buf = buf;
|
||||
size_t t_len = len;
|
||||
uint8_t flushed = 0;
|
||||
while(ut) {
|
||||
// allocate the buffer (if needed)
|
||||
if (!ut->chunk) {
|
||||
ut->chunk = uwsgi_buffer_new(t_len);
|
||||
}
|
||||
// skip final transformations before appending data
|
||||
if (ut->is_final) goto next;
|
||||
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if the transformation cannot stream, continue buffering (the func will be called at the end)
|
||||
if (!ut->can_stream) return 1;
|
||||
|
||||
ut->round++;
|
||||
if (ut->func(wsgi_req, ut)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ut->flushed) flushed = 1;
|
||||
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
// we reset the buffer, so we do not waste memory
|
||||
ut->chunk->pos = 0;
|
||||
next:
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
// if we are here we can tell the writer to send the body to the client
|
||||
// no buffering please
|
||||
if (!flushed) {
|
||||
wsgi_req->transformed_chunk = t_buf;
|
||||
wsgi_req->transformed_chunk_len = t_len;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
run all the remaining (or buffered) transformations
|
||||
|
||||
*/
|
||||
int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
char *t_buf = NULL;
|
||||
size_t t_len = 0;
|
||||
uint8_t flushed = 0;
|
||||
int found_nostream = 0;
|
||||
while(ut) {
|
||||
if (!found_nostream) {
|
||||
if (!ut->can_stream) {
|
||||
found_nostream = 1;
|
||||
}
|
||||
else {
|
||||
// stop the chain if no chunk is available
|
||||
if (!ut->chunk) return 0;
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ut->chunk) {
|
||||
if (t_len > 0) {
|
||||
ut->chunk = uwsgi_buffer_new(t_len);
|
||||
}
|
||||
else {
|
||||
ut->chunk = uwsgi_buffer_new(uwsgi.page_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (t_len > 0) {
|
||||
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// run the transformation
|
||||
ut->round++;
|
||||
if (ut->func(wsgi_req, ut)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ut->flushed) flushed = 1;
|
||||
|
||||
t_buf = ut->chunk->buf;
|
||||
t_len = ut->chunk->pos;
|
||||
next:
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
// if we are here, all of the transformations are applied
|
||||
if (!flushed) {
|
||||
wsgi_req->transformed_chunk = t_buf;
|
||||
wsgi_req->transformed_chunk_len = t_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_transformation *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
struct uwsgi_transformation *current_ut = ut;
|
||||
if (current_ut->chunk) {
|
||||
uwsgi_buffer_destroy(current_ut->chunk);
|
||||
}
|
||||
if (current_ut->ub) {
|
||||
uwsgi_buffer_destroy(current_ut->ub);
|
||||
}
|
||||
if (current_ut->fd > -1) {
|
||||
close(current_ut->fd);
|
||||
}
|
||||
ut = ut->next;
|
||||
free(current_ut);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_transformation *), void *data) {
|
||||
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
|
||||
while(ut) {
|
||||
old_ut = ut;
|
||||
ut = ut->next;
|
||||
}
|
||||
|
||||
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
|
||||
ut->func = func;
|
||||
ut->fd = -1;
|
||||
ut->data = data;
|
||||
|
||||
if (old_ut) {
|
||||
old_ut->next = ut;
|
||||
}
|
||||
else {
|
||||
wsgi_req->transformations = ut;
|
||||
}
|
||||
|
||||
return ut;
|
||||
}
|
||||
+305
-59
@@ -71,11 +71,30 @@ void set_user_harakiri(int sec) {
|
||||
uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
|
||||
return;
|
||||
}
|
||||
// a 0 seconds value, reset the timer
|
||||
if (sec == 0) {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
|
||||
if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].user_harakiri = 0;
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uspool->user_harakiri = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
|
||||
if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
|
||||
uspool->user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,14 +225,20 @@ void uwsgi_set_cgroup() {
|
||||
usl = uwsgi.cgroup;
|
||||
|
||||
while (usl) {
|
||||
if (mkdir(usl->value, 0700)) {
|
||||
uwsgi_log("using Linux cgroup %s\n", usl->value);
|
||||
int mode = strtol(uwsgi.cgroup_dir_mode, 0, 8);
|
||||
if (mkdir(usl->value, mode)) {
|
||||
if (errno != EEXIST) {
|
||||
uwsgi_error("mkdir()");
|
||||
exit(1);
|
||||
}
|
||||
if (chmod(usl->value, mode)) {
|
||||
uwsgi_error("chmod()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("using Linux cgroup %s with mode %o\n", usl->value, mode);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("created Linux cgroup %s\n", usl->value);
|
||||
uwsgi_log("created Linux cgroup %s with mode %o\n", usl->value, mode);
|
||||
}
|
||||
|
||||
cgroup_taskfile = uwsgi_concat2(usl->value, "/tasks");
|
||||
@@ -222,12 +247,11 @@ void uwsgi_set_cgroup() {
|
||||
uwsgi_error_open(cgroup_taskfile);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(cgroup, "%d", (int) getpid()) <= 0) {
|
||||
uwsgi_log("could not set cgroup\n");
|
||||
if (fprintf(cgroup, "%d\n", (int) getpid()) <= 0 || ferror(cgroup) || fclose(cgroup)) {
|
||||
uwsgi_error("could not set cgroup");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("assigned process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
|
||||
fclose(cgroup);
|
||||
free(cgroup_taskfile);
|
||||
|
||||
|
||||
@@ -248,11 +272,10 @@ void uwsgi_set_cgroup() {
|
||||
cgroup_taskfile = uwsgi_concat3(usl->value, "/", uslo->value);
|
||||
cgroup = fopen(cgroup_taskfile, "w");
|
||||
if (cgroup) {
|
||||
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
|
||||
if (fprintf(cgroup, "%s\n", cgroup_opt) <= 0 || ferror(cgroup) || fclose(cgroup)) {
|
||||
uwsgi_log("could not set cgroup option %s to %s\n", uslo->value, cgroup_opt);
|
||||
exit(1);
|
||||
}
|
||||
fclose(cgroup);
|
||||
uwsgi_log("set %s to %s\n", cgroup_opt, cgroup_taskfile);
|
||||
}
|
||||
free(cgroup_taskfile);
|
||||
@@ -576,6 +599,16 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
int tmp_id;
|
||||
uint64_t tmp_rt, rss = 0, vsz = 0;
|
||||
|
||||
// apply transformations
|
||||
if (wsgi_req->transformations) {
|
||||
if (uwsgi_apply_final_transformations(wsgi_req) == 0) {
|
||||
if (wsgi_req->transformed_chunk && wsgi_req->transformed_chunk_len > 0) {
|
||||
uwsgi_response_write_body_do(wsgi_req, wsgi_req->transformed_chunk, wsgi_req->transformed_chunk_len);
|
||||
}
|
||||
}
|
||||
uwsgi_free_transformations(wsgi_req);
|
||||
}
|
||||
|
||||
// check if headers should be sent
|
||||
if (wsgi_req->headers) {
|
||||
if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) {
|
||||
@@ -599,6 +632,19 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = rss;
|
||||
}
|
||||
|
||||
if (!wsgi_req->do_not_account) {
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
|
||||
// this is used for MAX_REQUESTS
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests++;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply final routes after accounting
|
||||
uwsgi_apply_final_routes(wsgi_req);
|
||||
#endif
|
||||
|
||||
// close the connection with the client
|
||||
if (!wsgi_req->fd_closed) {
|
||||
@@ -622,15 +668,6 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
}
|
||||
|
||||
if (!wsgi_req->do_not_account) {
|
||||
uwsgi.workers[0].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
|
||||
// this is used for MAX_REQUESTS
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests++;
|
||||
}
|
||||
|
||||
// after_request hook
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->after_request)
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req);
|
||||
@@ -650,12 +687,14 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
set_user_harakiri(0);
|
||||
}
|
||||
|
||||
// this is racy in multithread mode
|
||||
if (wsgi_req->response_size > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].tx += wsgi_req->response_size;
|
||||
}
|
||||
if (wsgi_req->headers_size > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].tx += wsgi_req->headers_size;
|
||||
if (!wsgi_req->do_not_account) {
|
||||
// this is racy in multithread mode
|
||||
if (wsgi_req->response_size > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].tx += wsgi_req->response_size;
|
||||
}
|
||||
if (wsgi_req->headers_size > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].tx += wsgi_req->headers_size;
|
||||
}
|
||||
}
|
||||
|
||||
// defunct process reaper
|
||||
@@ -688,6 +727,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// free chunked input
|
||||
if (wsgi_req->chunked_input_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->chunked_input_buf);
|
||||
}
|
||||
|
||||
// free websocket engine
|
||||
if (wsgi_req->websocket_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
|
||||
@@ -1122,12 +1166,43 @@ void parse_sys_envs(char **envs) {
|
||||
}
|
||||
|
||||
// get the application id
|
||||
int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
|
||||
int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, int modifier1) {
|
||||
|
||||
int i;
|
||||
struct stat st;
|
||||
int found;
|
||||
|
||||
char *app_name = key;
|
||||
uint16_t app_name_len = key_len;
|
||||
|
||||
if (app_name_len == 0 && wsgi_req) {
|
||||
app_name = wsgi_req->appid;
|
||||
app_name_len = wsgi_req->appid_len;
|
||||
if (app_name_len == 0) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
app_name = wsgi_req->script_name;
|
||||
app_name_len = wsgi_req->script_name_len;
|
||||
}
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
char *vhost_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
|
||||
app_name = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, vhost_name, app_name_len);
|
||||
free(vhost_name);
|
||||
if (!app_name) {
|
||||
uwsgi_log("unable to add UWSGI_APPID to the uwsgi buffer, consider increasing it\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost KEY=%.*s\n", app_name_len, app_name);
|
||||
#endif
|
||||
}
|
||||
wsgi_req->appid = app_name;
|
||||
wsgi_req->appid_len = app_name_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
// reset check
|
||||
found = 0;
|
||||
@@ -1158,17 +1233,11 @@ int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modifier1 == -1)
|
||||
return i;
|
||||
if (modifier1 == uwsgi_apps[i].modifier1)
|
||||
return i;
|
||||
if (modifier1 == -1) return i;
|
||||
if (modifier1 == uwsgi_apps[i].modifier1) return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.no_default_app) {
|
||||
return uwsgi.default_app;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1506,6 +1575,25 @@ int uwsgi_logic_opt_for_glob(char *key, char *value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_for_times(char *key, char *value) {
|
||||
|
||||
int num = atoi(uwsgi.logic_opt_data);
|
||||
int i;
|
||||
char str_num[11];
|
||||
|
||||
for (i = 1; i <= num; i++) {
|
||||
int ret = uwsgi_num2str2(i, str_num);
|
||||
// security check
|
||||
if (ret < 0 || ret > 11) {
|
||||
exit(1);
|
||||
}
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
@@ -1745,18 +1833,21 @@ void init_magic_table(char *magic_table[]) {
|
||||
}
|
||||
|
||||
char *uwsgi_get_last_char(char *what, char c) {
|
||||
int i;
|
||||
char *ptr = NULL;
|
||||
|
||||
for (i = 0; i < (int) strlen(what); i++) {
|
||||
if (what[i] == c) {
|
||||
ptr = what + i;
|
||||
}
|
||||
size_t len = strlen(what);
|
||||
while(len--) {
|
||||
if (what[len] == c) return what + len;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_get_last_charn(char *what, size_t len, char c) {
|
||||
while(len--) {
|
||||
if (what[len] == c) return what + len;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_num2str(int num) {
|
||||
|
||||
char *str = uwsgi_malloc(11);
|
||||
@@ -1765,6 +1856,12 @@ char *uwsgi_num2str(int num) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char *uwsgi_64bit2str(int64_t num) {
|
||||
char *str = uwsgi_malloc(sizeof(MAX64_STR)+1);
|
||||
snprintf(str, sizeof(MAX64_STR)+1, "%lld", (long long) num);
|
||||
return str;
|
||||
}
|
||||
|
||||
int uwsgi_num2str2(int num, char *ptr) {
|
||||
|
||||
return snprintf(ptr, 11, "%d", num);
|
||||
@@ -1878,7 +1975,7 @@ int uwsgi_list_has_str(char *list, char *str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char hex2num(char *str) {
|
||||
static char hex2num(char *str) {
|
||||
|
||||
char val = 0;
|
||||
|
||||
@@ -2158,6 +2255,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
|
||||
uwsgi_string->next = NULL;
|
||||
uwsgi_string->custom = 0;
|
||||
uwsgi_string->custom2 = 0;
|
||||
uwsgi_string->custom_ptr = NULL;
|
||||
|
||||
return uwsgi_string;
|
||||
}
|
||||
@@ -2990,6 +3088,36 @@ void escape_shell_arg(char *src, size_t len, char *dst) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
void escape_json(char *src, size_t len, char *dst) {
|
||||
|
||||
size_t i;
|
||||
char *ptr = dst;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (src[i] == '\t') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 't';
|
||||
}
|
||||
else if (src[i] == '\n') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'n';
|
||||
}
|
||||
else if (src[i] == '\r') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'r';
|
||||
}
|
||||
else if (src[i] == '"') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '"';
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++ = 0;
|
||||
}
|
||||
|
||||
void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
uint16_t i;
|
||||
@@ -3035,14 +3163,18 @@ void http_url_decode(char *buf, uint16_t * len, char *dst) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
we scan the table in reverse, as updated values are at the end
|
||||
*/
|
||||
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
|
||||
*len = wsgi_req->hvec[i + 1].iov_len;
|
||||
return wsgi_req->hvec[i + 1].iov_base;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len)) {
|
||||
*len = wsgi_req->hvec[i].iov_len;
|
||||
return wsgi_req->hvec[i].iov_base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3075,6 +3207,10 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
|
||||
}
|
||||
}
|
||||
|
||||
if ((mountpoint_len == 0 || (mountpoint_len =- 1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
|
||||
return wi;
|
||||
}
|
||||
|
||||
@@ -3094,7 +3230,7 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
|
||||
uwsgi_log("[uwsgi-check-touches] File %s was removed\n", touch->value);
|
||||
#endif
|
||||
touch->custom2 = 1;
|
||||
return touch->value;
|
||||
return touch->custom_ptr ? touch->custom_ptr : touch->value;
|
||||
}
|
||||
else if (!touch->custom && !touch->custom2) {
|
||||
uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
|
||||
@@ -3109,14 +3245,14 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
touch->custom2 = 0;
|
||||
return touch->value;
|
||||
return touch->custom_ptr ? touch->custom_ptr : touch->value;
|
||||
}
|
||||
else if (touch->custom && (uint64_t) tr_st.st_mtime > touch->custom) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
return touch->value;
|
||||
return touch->custom_ptr ? touch->custom_ptr : touch->value;
|
||||
}
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
}
|
||||
@@ -3138,14 +3274,22 @@ char *uwsgi_chomp(char *str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char *uwsgi_tmpname(char *base, char *id) {
|
||||
char *template = uwsgi_concat3(base, "/", id);
|
||||
if (mkstemp(template) < 0) {
|
||||
free(template);
|
||||
return NULL;
|
||||
int uwsgi_tmpfd() {
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
|
||||
int fd = mkstemp(template);
|
||||
unlink(template);
|
||||
free(template);
|
||||
return fd;
|
||||
}
|
||||
|
||||
return template;
|
||||
FILE *uwsgi_tmpfile() {
|
||||
int fd = uwsgi_tmpfd();
|
||||
if (fd < 0) return NULL;
|
||||
return fdopen(fd, "w+");
|
||||
}
|
||||
|
||||
int uwsgi_file_to_string_list(char *filename, struct uwsgi_string_list **list) {
|
||||
@@ -3195,10 +3339,9 @@ void uwsgi_write_pidfile(char *pidfile_name) {
|
||||
uwsgi_error_open(pidfile_name);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) < 0) {
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
fclose(pidfile);
|
||||
}
|
||||
|
||||
char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
|
||||
@@ -3461,6 +3604,7 @@ int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separ
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
*ptr++ = src[i];
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
@@ -3809,3 +3953,105 @@ char *uwsgi_get_header(struct wsgi_request *wsgi_req, char *hh, uint16_t len, ui
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
static char *uwsgi_hex_table[] = {
|
||||
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
|
||||
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
|
||||
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
|
||||
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
|
||||
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
|
||||
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
|
||||
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
|
||||
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
|
||||
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
|
||||
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
|
||||
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
|
||||
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
|
||||
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
|
||||
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
|
||||
};
|
||||
|
||||
char *uwsgi_str_to_hex(char *src, size_t slen) {
|
||||
char *dst = uwsgi_malloc(slen*2);
|
||||
char *ptr = dst;
|
||||
size_t i;
|
||||
for(i=0;i<slen;i++) {
|
||||
memcpy(ptr, uwsgi_hex_table[ (int) src[i] ], 2);
|
||||
ptr+=2;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
// dst has to be 3 times buf size (USE IT ONLY FOR PATH_INFO !!!)
|
||||
void http_url_encode(char *buf, uint16_t *len, char *dst) {
|
||||
|
||||
uint16_t i;
|
||||
char *ptr = dst;
|
||||
for(i=0;i<*len;i++) {
|
||||
if ((buf[i] >= 'A' && buf[i] <= 'Z') ||
|
||||
(buf[i] >= 'a' && buf[i] <= 'z') ||
|
||||
(buf[i] >= '0' && buf[i] <= '9') ||
|
||||
buf[i] == '-' || buf[i] == '_' || buf[i] == '.' || buf[i] == '~' || buf[i] == '/' ) {
|
||||
*ptr++= buf[i];
|
||||
}
|
||||
else {
|
||||
char *h = uwsgi_hex_table[(int) buf[i]];
|
||||
*ptr++= '%';
|
||||
*ptr++= h[0];
|
||||
*ptr++= h[1];
|
||||
}
|
||||
}
|
||||
|
||||
*len = ptr-dst;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_takeover() {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
uwsgi_spooler_run();
|
||||
}
|
||||
else if (uwsgi.muleid) {
|
||||
uwsgi_mule_run();
|
||||
}
|
||||
else {
|
||||
uwsgi_worker_run();
|
||||
}
|
||||
}
|
||||
|
||||
// create a message pipe
|
||||
void create_msg_pipe(int *fd, int bufsize) {
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
|
||||
#endif
|
||||
uwsgi_error("create_msg_pipe()/socketpair()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(fd[0]);
|
||||
uwsgi_socket_nb(fd[1]);
|
||||
|
||||
if (bufsize) {
|
||||
if (setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
|
||||
uwsgi_error("create_msg_pipe()/setsockopt()");
|
||||
}
|
||||
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
|
||||
uwsgi_error("create_msg_pipe()/setsockopt()");
|
||||
}
|
||||
|
||||
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
|
||||
uwsgi_error("create_msg_pipe()/setsockopt()");
|
||||
}
|
||||
if (setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
|
||||
uwsgi_error("create_msg_pipe()/setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_binary_path() {
|
||||
return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
|
||||
}
|
||||
|
||||
+342
-81
@@ -24,6 +24,7 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct uwsgi_server uwsgi;
|
||||
pid_t masterpid;
|
||||
|
||||
#if defined(__APPLE__) && defined(UWSGI_AS_SHARED_LIBRARY)
|
||||
#include <crt_externs.h>
|
||||
@@ -64,14 +65,16 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"no-harakiri-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"no-harakiri-after-req-hook", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
|
||||
{"backtrace-depth", no_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
|
||||
{"backtrace-depth", required_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
|
||||
{"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MULE_HARAKIRI, 0},
|
||||
#ifdef UWSGI_XML
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
|
||||
|
||||
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
|
||||
@@ -79,7 +82,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -108,6 +113,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -163,12 +169,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
|
||||
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
|
||||
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
|
||||
{"emperor-stats", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"emperor-stats-server", required_argument, 0, "run the Emperor stats server", uwsgi_opt_set_str, &uwsgi.emperor_stats, 0},
|
||||
{"early-emperor", no_argument, 0, "spawn the emperor as soon as possibile", uwsgi_opt_true, &uwsgi.early_emperor, 0},
|
||||
@@ -176,6 +184,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
|
||||
{"emperor-max-throttle", required_argument, 0, "set max throttling level (in milliseconds) for bad behaving vassals (default 3 minutes)", uwsgi_opt_set_int, &uwsgi.emperor_max_throttle, 0},
|
||||
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
|
||||
{"emperor-on-demand-extension", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-ext", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -191,6 +206,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"print-sym", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"print-symbol", required_argument, 0, "print content of the specified binary symbol", uwsgi_print_sym, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"reaper", no_argument, 'r', "call waitpid(-1,...) after each request to get rid of zombies", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_REAPER, 0},
|
||||
{"max-requests", required_argument, 'R', "reload workers after the specified amount of managed requests", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MAX_REQUESTS, 0},
|
||||
{"min-worker-lifetime", required_argument, 0, "number of seconds worker must run before being reloaded (default is 60)", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MIN_WORKER_LIFETIME, 0},
|
||||
@@ -203,6 +221,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
|
||||
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
|
||||
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
|
||||
{"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store, UWSGI_OPT_MASTER},
|
||||
@@ -213,8 +234,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cache-udp-server", required_argument, 0, "bind the cache udp server (used only for set/update/delete) to the specified socket", uwsgi_opt_add_string_list, &uwsgi.cache_udp_server, UWSGI_OPT_MASTER},
|
||||
{"cache-udp-node", required_argument, 0, "send cache update/deletion to the specified cache udp server", uwsgi_opt_add_string_list, &uwsgi.cache_udp_node, UWSGI_OPT_MASTER},
|
||||
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
|
||||
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
|
||||
|
||||
{"add-cache-item", required_argument, 0, "add an item in the cache", uwsgi_opt_add_string_list, &uwsgi.add_cache_item, 0},
|
||||
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
|
||||
#ifdef UWSGI_ZLIB
|
||||
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
|
||||
#endif
|
||||
|
||||
{"cache2", required_argument, 0, "create a new generation shared cache (keyval syntax)", uwsgi_opt_add_string_list, &uwsgi.cache2, 0},
|
||||
|
||||
@@ -236,6 +262,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
|
||||
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
|
||||
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
|
||||
{"mule-msg-size", optional_argument, 0, "set mule message buffer size", uwsgi_opt_set_int, &uwsgi.mule_msg_size, UWSGI_OPT_MASTER},
|
||||
|
||||
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
|
||||
@@ -256,6 +283,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
|
||||
#ifdef UWSGI_CAP
|
||||
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
|
||||
@@ -270,9 +299,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exec-as-user", required_argument, 0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user, 0},
|
||||
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
|
||||
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
|
||||
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_YAML
|
||||
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -281,20 +309,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_SQLITE3
|
||||
{"sqlite3", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"sqlite", required_argument, 0, "load config from sqlite3 db", uwsgi_opt_load_sqlite3, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
#endif
|
||||
#ifdef UWSGI_LDAP
|
||||
{"ldap", required_argument, 0, "load configuration from ldap server", uwsgi_opt_load_ldap, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema", no_argument, 0, "dump uWSGI ldap schema", uwsgi_opt_ldap_dump, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ldap-schema-ldif", no_argument, 0, "dump uWSGI ldap schema in ldif format", uwsgi_opt_ldap_dump_ldif, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
|
||||
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
|
||||
@@ -307,6 +326,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-sndbuf", required_argument, 0, "set SO_SNDBUF", uwsgi_opt_set_64bit, &uwsgi.so_sndbuf, 0},
|
||||
{"socket-rcvbuf", required_argument, 0, "set SO_RCVBUF", uwsgi_opt_set_64bit, &uwsgi.so_rcvbuf, 0},
|
||||
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
|
||||
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
|
||||
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
|
||||
@@ -328,6 +349,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"touch-chain-reload", required_argument, 0, "trigger chain reload if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_chain_reload, UWSGI_OPT_MASTER},
|
||||
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
|
||||
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
@@ -363,6 +386,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node", required_argument, 0, "add a node to a legion", uwsgi_opt_legion_node, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-freq", required_argument, 0, "set the frequency of legion packets", uwsgi_opt_set_int, &uwsgi.legion_freq, UWSGI_OPT_MASTER},
|
||||
{"legion-tolerance", required_argument, 0, "set the tolerance of legion subsystem", uwsgi_opt_set_int, &uwsgi.legion_tolerance, UWSGI_OPT_MASTER},
|
||||
@@ -371,10 +395,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-joined", required_argument, 0, "action to call on new node joining legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-node-left", required_argument, 0, "action to call node leaving legion", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
@@ -393,7 +420,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ssl-verbose", no_argument, 0, "be verbose about SSL errors", uwsgi_opt_true, &uwsgi.ssl_verbose, 0},
|
||||
// force master, as ssl sessions caching initialize locking early
|
||||
{"ssl-sessions-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-session-use-cache", no_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_true, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-session-use-cache", optional_argument, 0, "use uWSGI cache for ssl sessions storage", uwsgi_opt_set_str, &uwsgi.ssl_sessions_use_cache, UWSGI_OPT_MASTER},
|
||||
{"ssl-sessions-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
|
||||
{"ssl-session-timeout", required_argument, 0, "set SSL sessions timeout (default: 300 seconds)", uwsgi_opt_set_int, &uwsgi.ssl_sessions_timeout, 0},
|
||||
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
|
||||
@@ -434,8 +461,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER},
|
||||
#endif
|
||||
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"segfault-alarm", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -506,6 +539,38 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
|
||||
|
||||
{"final-route", required_argument, 0, "add a final route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"final-route-status", required_argument, 0, "add a final route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"final-route-host", required_argument, 0, "add a final route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"final-route-uri", required_argument, 0, "add a final route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"final-route-qs", required_argument, 0, "add a final route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"final-route-remote-addr", required_argument, 0, "add a final route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"final-route-user-agent", required_argument, 0, "add a final route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"final-route-remote-user", required_argument, 0, "add a final route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"final-route-referer", required_argument, 0, "add a final route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"final-route-label", required_argument, 0, "add a final routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"final-route-if", required_argument, 0, "add a final route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"final-route-if-not", required_argument, 0, "add a final route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"final-route-run", required_argument, 0, "always run the specified final route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"error-route", required_argument, 0, "add an error route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"error-route-status", required_argument, 0, "add an error route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"error-route-host", required_argument, 0, "add an error route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"error-route-uri", required_argument, 0, "add an error route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"error-route-qs", required_argument, 0, "add an error route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"error-route-remote-addr", required_argument, 0, "add an error route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"error-route-user-agent", required_argument, 0, "add an error route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"error-route-remote-user", required_argument, 0, "add an error route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"error-route-referer", required_argument, 0, "add an error route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"error-route-label", required_argument, 0, "add an error routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"error-route-if", required_argument, 0, "add an error route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -519,6 +584,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"websockets-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
{"websocket-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
|
||||
|
||||
{"chunked-input-limit", required_argument, 0, "set the max size of a chunked input part (default 1MB, in bytes)", uwsgi_opt_set_64bit, &uwsgi.chunked_input_limit, 0},
|
||||
{"chunked-input-timeout", required_argument, 0, "set default timeout for chunked input", uwsgi_opt_set_int, &uwsgi.chunked_input_timeout, 0},
|
||||
|
||||
{"clock", required_argument, 0, "set a clock source", uwsgi_opt_set_str, &uwsgi.requested_clock, 0},
|
||||
|
||||
{"clock-list", no_argument, 0, "list enabled clocks", uwsgi_opt_true, &uwsgi.clock_list, 0},
|
||||
@@ -561,6 +629,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-gzip-ext", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
{"static-gzip-suffix", required_argument, 0, "check for a gzip version of all requested static files with the specified ext/suffix", uwsgi_opt_add_string_list, &uwsgi.static_gzip_ext, UWSGI_OPT_MIME},
|
||||
|
||||
{"honour-range", no_argument, 0, "enable support for the HTTP Range header", uwsgi_opt_true, &uwsgi.honour_range, 0},
|
||||
|
||||
{"offload-threads", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
{"offload-thread", required_argument, 0, "set the number of offload threads to spawn (per-worker, default 0)", uwsgi_opt_set_int, &uwsgi.offload_threads, 0},
|
||||
|
||||
@@ -573,9 +643,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
|
||||
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
|
||||
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
|
||||
#ifdef __linux__
|
||||
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup, 0},
|
||||
{"cgroup-opt", required_argument, 0, "set value in specified cgroup option", uwsgi_opt_add_string_list, &uwsgi.cgroup_opt, 0},
|
||||
{"cgroup-dir-mode", required_argument, 0, "set permission for cgroup directory (default is 700)", uwsgi_opt_set_str, &uwsgi.cgroup_dir_mode, 0},
|
||||
{"namespace", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
|
||||
{"namespace-keep-mount", required_argument, 0, "keep the specified mountpoint in your namespace", uwsgi_opt_add_string_list, &uwsgi.ns_keep_mount, 0},
|
||||
{"ns", required_argument, 0, "run in a new namespace under the specified rootfs", uwsgi_opt_set_str, &uwsgi.ns, 0},
|
||||
@@ -592,6 +664,15 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"zerg-server", required_argument, 0, "enable the zerg server on the specified UNIX socket", uwsgi_opt_set_str, &uwsgi.zerg_server, UWSGI_OPT_MASTER},
|
||||
|
||||
{"cron", required_argument, 0, "add a cron task", uwsgi_opt_add_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron2", required_argument, 0, "add a cron task (key=val syntax)", uwsgi_opt_add_cron2, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-cron", required_argument, 0, "add a unique cron task", uwsgi_opt_add_unique_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-harakiri", required_argument, 0, "set the maximum time (in seconds) we wait for cron command to complete", uwsgi_opt_set_int, &uwsgi.cron_harakiri, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-cron", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-legion", required_argument, 0, "add a cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-legion-cron", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
{"unique-cron-legion", required_argument, 0, "add a unique cron task runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_unique_legion_cron, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"loop", required_argument, 0, "select the uWSGI loop engine", uwsgi_opt_set_str, &uwsgi.loop, 0},
|
||||
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
@@ -599,6 +680,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-attach-daemon", required_argument, 0, "same as --attach-daemon but daemon runs only on legion lord node", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-smart-attach-daemon", required_argument, 0, "same as --smart-attach-daemon but daemon runs only on legion lord node", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-smart-attach-daemon2", required_argument, 0, "same as --smart-attach-daemon2 but daemon runs only on legion lord node", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -614,6 +701,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
|
||||
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
|
||||
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
@@ -779,8 +867,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
char *section = uwsgi_get_last_char(filename, ':');
|
||||
if (section) {
|
||||
*section = 0;
|
||||
if (section == filename) {
|
||||
goto reuse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we have a special case for symlinks
|
||||
if (uwsgi_is_link(filename)) {
|
||||
if (filename[0] != '/') {
|
||||
@@ -834,6 +926,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
if (uwsgi_get_last_char(magic_table['s'], '.'))
|
||||
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
|
||||
|
||||
reuse:
|
||||
if (section) {
|
||||
magic_table['x'] = section+1;
|
||||
*section = ':';
|
||||
@@ -925,6 +1018,10 @@ void gracefully_kill(int signum) {
|
||||
}
|
||||
|
||||
void end_me(int signum) {
|
||||
if (getpid() != masterpid && uwsgi.skip_atexit) {
|
||||
_exit(UWSGI_END_CODE);
|
||||
// never here
|
||||
}
|
||||
exit(UWSGI_END_CODE);
|
||||
}
|
||||
|
||||
@@ -1034,6 +1131,9 @@ void grace_them_all(int signum) {
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
|
||||
// the Emperor (as an example) cannot nuke itself
|
||||
if (uwsgi.disable_nuclear_blast) return;
|
||||
|
||||
if (!uwsgi.workers) {
|
||||
reap_them_all(0);
|
||||
}
|
||||
@@ -1178,7 +1278,6 @@ void what_i_am_doing() {
|
||||
}
|
||||
|
||||
|
||||
pid_t masterpid;
|
||||
|
||||
int unconfigured_hook(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
|
||||
@@ -1348,7 +1447,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
env_count++;
|
||||
}
|
||||
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * env_count);
|
||||
uwsgi.environ = uwsgi_malloc(sizeof(char *) * (env_count+1));
|
||||
for (i = 0; i < env_count; i++) {
|
||||
uwsgi.environ[i] = strdup(environ[i]);
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -1356,6 +1455,7 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
|
||||
#endif
|
||||
environ[i] = uwsgi.environ[i];
|
||||
}
|
||||
uwsgi.environ[env_count] = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("max space for custom process name = %d\n", uwsgi.max_procname);
|
||||
@@ -1405,15 +1505,28 @@ void uwsgi_backtrace(int depth) {
|
||||
|
||||
bt_strings = backtrace_symbols(btrace, bt_size);
|
||||
|
||||
uwsgi_log("*** backtrace of %d ***\n", (int) getpid());
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
uwsgi_buffer_append(ub, "*** backtrace of ",17);
|
||||
uwsgi_buffer_num64(ub, (int64_t) getpid());
|
||||
uwsgi_buffer_append(ub, " ***\n", 5);
|
||||
for (i = 0; i < bt_size; i++) {
|
||||
uwsgi_log("%s\n", bt_strings[i]);
|
||||
uwsgi_buffer_append(ub, bt_strings[i], strlen(bt_strings[i]));
|
||||
uwsgi_buffer_append(ub, "\n", 1);
|
||||
}
|
||||
|
||||
free(btrace);
|
||||
uwsgi_log("*** end of backtrace ***\n");
|
||||
|
||||
uwsgi_buffer_append(ub, "*** end of backtrace ***\n", 25);
|
||||
|
||||
uwsgi_log("%.*s", ub->pos, ub->buf);
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.alarm_segfault;
|
||||
while(usl) {
|
||||
uwsgi_alarm_trigger(usl->value, ub->buf, ub->pos);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1423,6 +1536,8 @@ void uwsgi_segfault(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -1436,6 +1551,8 @@ void uwsgi_fpe(int signum) {
|
||||
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
|
||||
if (uwsgi.use_abort) abort();
|
||||
|
||||
// restore default handler to generate core
|
||||
signal(signum, SIG_DFL);
|
||||
kill(getpid(), signum);
|
||||
@@ -1603,10 +1720,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
int i;
|
||||
|
||||
#ifdef UNBIT
|
||||
//struct uidsec_struct us;
|
||||
#endif
|
||||
|
||||
struct utsname uuts;
|
||||
|
||||
// signal mask is inherited, and sme process manager could make a real mess...
|
||||
@@ -1750,6 +1863,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// set a couple of 'static' magic vars
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -2028,6 +2142,8 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_file_write_do(uwsgi.file_write_list);
|
||||
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
@@ -2108,6 +2224,20 @@ int uwsgi_start(void *v_argv) {
|
||||
// automatically fix options
|
||||
sanitize_args();
|
||||
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
// start the Emperor if needed
|
||||
if (!uwsgi.early_emperor && uwsgi.emperor) {
|
||||
uwsgi_emperor_start();
|
||||
@@ -2132,19 +2262,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
|
||||
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
@@ -2160,18 +2277,9 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
uwsgi_log("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
|
||||
uwsgi.async_waiting_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
if (!uwsgi.async_waiting_fd_table) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
memset(uwsgi.async_waiting_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
if (!uwsgi.async_proto_fd_table) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
memset(uwsgi.async_proto_fd_table, 0, sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
// 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);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -2331,7 +2439,8 @@ int uwsgi_start(void *v_argv) {
|
||||
!uwsgi.udp_socket &&
|
||||
!uwsgi.emperor &&
|
||||
!uwsgi.command_mode &&
|
||||
!uwsgi.daemons_cnt
|
||||
!uwsgi.daemons_cnt &&
|
||||
!uwsgi.crons
|
||||
#ifdef UWSGI_SSL
|
||||
&& !uwsgi.legions
|
||||
#endif
|
||||
@@ -2394,7 +2503,14 @@ unsafe:
|
||||
if (uwsgi.crons) {
|
||||
struct uwsgi_cron *ucron = uwsgi.crons;
|
||||
while (ucron) {
|
||||
uwsgi_log("command \"%s\" registered as uWSGI-cron task\n", ucron->command);
|
||||
#ifdef UWSGI_SSL
|
||||
if (ucron->legion) {
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task for legion \"%s\"\n", ucron->command, ucron->legion);
|
||||
ucron = ucron->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-cron] command \"%s\" registered as cron task\n", ucron->command);
|
||||
ucron = ucron->next;
|
||||
}
|
||||
}
|
||||
@@ -2530,11 +2646,9 @@ next:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
|
||||
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for request plugins, and eventually print a warning
|
||||
int rp_available = 0;
|
||||
@@ -2730,6 +2844,16 @@ next2:
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_worker_run();
|
||||
// never here
|
||||
_exit(0);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_worker_run() {
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.lazy || uwsgi.lazy_apps) {
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
@@ -3119,6 +3243,18 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
}
|
||||
|
||||
usl = uwsgi.exec_post_app;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_init_worker_mount_apps() {
|
||||
@@ -3161,6 +3297,67 @@ void uwsgi_opt_true(char *opt, char *value, void *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
gid = ugroup->gr_gid;
|
||||
}
|
||||
if (gid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_gid(): invalid gid %d\n", (int) gid);
|
||||
exit(1);
|
||||
}
|
||||
if (setgid(gid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_gid()/setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gid = getgid();
|
||||
if (!gid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate gid: %d\n", (int) gid);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
uid = upasswd->pw_uid;
|
||||
}
|
||||
if (uid <= 0) {
|
||||
uwsgi_log("uwsgi_opt_set_immediate_uid(): invalid uid %d\n", uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("uwsgi_opt_set_immediate_uid()/setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uid = getuid();
|
||||
if (!uid) {
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("immediate uid: %d\n", (int) uid);
|
||||
}
|
||||
|
||||
void uwsgi_opt_safe_fd(char *opt, char *value, void *foobar) {
|
||||
int fd = atoi(value);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("invalid file descriptor: %d\n", fd);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_add_safe_fd(fd);
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
@@ -3202,7 +3399,9 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
|
||||
uint16_t *ptr = (uint16_t *) key;
|
||||
|
||||
if (value) {
|
||||
*ptr = (strtoul(value, NULL, 10));
|
||||
unsigned long n = strtoul(value, NULL, 10);
|
||||
if (n > 65535) n = 65535;
|
||||
*ptr = n;
|
||||
}
|
||||
else {
|
||||
*ptr = 1;
|
||||
@@ -3710,12 +3909,10 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
|
||||
|
||||
void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
if (uwsgi_endswith(filename, ".ini")) {
|
||||
uwsgi_opt_load_ini(opt, filename, none);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef UWSGI_XML
|
||||
if (uwsgi_endswith(filename, ".xml")) {
|
||||
uwsgi_opt_load_xml(opt, filename, none);
|
||||
@@ -3742,6 +3939,9 @@ void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback to pluggable system
|
||||
uwsgi_opt_load_config(opt, filename, none);
|
||||
}
|
||||
|
||||
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
@@ -3763,12 +3963,25 @@ void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_ini_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_load_config(char *opt, char *filename, void *none) {
|
||||
struct uwsgi_configurator *uc = uwsgi.configurators;
|
||||
while(uc) {
|
||||
if (uwsgi_endswith(filename, uc->name)) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uc->func(filename, uwsgi.magic_table);
|
||||
return;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to load configuration from %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
||||
@@ -3784,13 +3997,6 @@ void uwsgi_opt_load_yml(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SQLITE3
|
||||
void uwsgi_opt_load_sqlite3(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_sqlite3_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_JSON
|
||||
void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
@@ -3798,12 +4004,6 @@ void uwsgi_opt_load_json(char *opt, char *filename, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
void uwsgi_opt_load_ldap(char *opt, char *url, void *none) {
|
||||
uwsgi_ldap_config(url);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_custom_option *uco = uwsgi.custom_options, *old_uco;
|
||||
@@ -3872,20 +4072,61 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
||||
// report CFLAGS used for compiling the server
|
||||
// use that values to build external plugins
|
||||
void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
|
||||
size_t len = sizeof(UWSGI_CFLAGS);
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
fprintf(stdout, "%.*s\n", (int) len / 2, base);
|
||||
fprintf(stdout, "%s\n", uwsgi_get_cflags());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *uwsgi_get_cflags() {
|
||||
size_t len = sizeof(UWSGI_CFLAGS);
|
||||
char *src = UWSGI_CFLAGS;
|
||||
char *ptr = uwsgi_malloc((len / 2) + 1);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
*ptr ++= 0;
|
||||
return base;
|
||||
}
|
||||
|
||||
// report uwsgi.h used for compiling the server
|
||||
// use that values to build external plugins
|
||||
extern char *uwsgi_dot_h;
|
||||
char *uwsgi_get_dot_h() {
|
||||
char *src = uwsgi_dot_h;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
#ifdef UWSGI_ZLIB
|
||||
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
|
||||
if (!ub) {
|
||||
free(base);
|
||||
return "";
|
||||
}
|
||||
// add final null byte
|
||||
uwsgi_buffer_append(ub, "\0", 1);
|
||||
free(base);
|
||||
// base is the final blob
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
|
||||
fprintf(stdout, "%s\n", uwsgi_get_dot_h());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
|
||||
|
||||
char buf[8192];
|
||||
@@ -3920,3 +4161,23 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
|
||||
};
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
|
||||
char **sym = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (sym) {
|
||||
uwsgi_log("%s", *sym);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *symbol_start = uwsgi_concat2(symbol, "_start");
|
||||
char *symbol_end = uwsgi_concat2(symbol, "_end");
|
||||
|
||||
char *sym_s = dlsym(RTLD_DEFAULT, symbol_start);
|
||||
char *sym_e = dlsym(RTLD_DEFAULT, symbol_end);
|
||||
|
||||
if (sym_s && sym_e) {
|
||||
uwsgi_log("%.*s", sym_e - sym_s, sym_s);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+162
-19
@@ -12,6 +12,58 @@ int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_expires(struct wsgi_request *wsgi_req, uint64_t t) {
|
||||
// 30+1
|
||||
char expires[31];
|
||||
int len = uwsgi_http_date((time_t) t, expires);
|
||||
if (!len) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, len);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_date(struct wsgi_request *wsgi_req, char *hkey, uint16_t hlen, uint64_t t) {
|
||||
// 30+1
|
||||
char d[31];
|
||||
int len = uwsgi_http_date((time_t) t, d);
|
||||
if (!len) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, hkey, hlen, d, len);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_last_modified(struct wsgi_request *wsgi_req, uint64_t t) {
|
||||
// 30+1
|
||||
char lm[31];
|
||||
int len = uwsgi_http_date((time_t) t, lm);
|
||||
if (!len) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, lm, len);
|
||||
}
|
||||
|
||||
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
|
||||
char buf[6+(sizeof(UMAX64_STR)*3)+4];
|
||||
if (end == 0) {
|
||||
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)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
|
||||
}
|
||||
|
||||
int uwsgi_response_prepare_headers_int(struct wsgi_request *wsgi_req, int status) {
|
||||
char status_str[11];
|
||||
uwsgi_num2str2(status, status_str);
|
||||
return uwsgi_response_prepare_headers(wsgi_req, status_str, 3);
|
||||
}
|
||||
|
||||
// status could be NNN or NNN message
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
|
||||
|
||||
@@ -24,7 +76,19 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
|
||||
|
||||
// reset the buffer (could be useful for rollbacks...)
|
||||
wsgi_req->headers->pos = 0;
|
||||
// reset headers count
|
||||
wsgi_req->header_cnt = 0;
|
||||
struct uwsgi_buffer *hh = NULL;
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply error routes
|
||||
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_error_routing = 0;
|
||||
#endif
|
||||
if (status_len <= 4) {
|
||||
char *new_sc = NULL;
|
||||
size_t new_sc_len = 0;
|
||||
@@ -47,7 +111,6 @@ int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status,
|
||||
if (!hh) {wsgi_req->write_errors++; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->status = uwsgi_str3_num(status);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
@@ -56,6 +119,24 @@ error:
|
||||
}
|
||||
|
||||
//each protocol has its header generator
|
||||
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *hh = wsgi_req->socket->proto_add_header(wsgi_req, key, key_len, value, value_len);
|
||||
if (!hh) { wsgi_req->write_errors++ ; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
wsgi_req->header_cnt++;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_response_add_header(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
|
||||
@@ -75,21 +156,14 @@ int uwsgi_response_add_header(struct wsgi_request *wsgi_req, char *key, uint16_t
|
||||
rh = rh->next;
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
}
|
||||
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *hh = wsgi_req->socket->proto_add_header(wsgi_req, key, key_len, value, value_len);
|
||||
if (!hh) { wsgi_req->write_errors++ ; return -1;}
|
||||
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
|
||||
wsgi_req->header_cnt++;
|
||||
uwsgi_buffer_destroy(hh);
|
||||
return 0;
|
||||
error:
|
||||
uwsgi_buffer_destroy(hh);
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
|
||||
|
||||
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) {
|
||||
@@ -141,10 +215,32 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
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) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
|
||||
if (t_ret == 0) {
|
||||
buf = wsgi_req->transformed_chunk;
|
||||
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) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -156,7 +252,7 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
sendbody:
|
||||
|
||||
if (len == 0) return UWSGI_OK;
|
||||
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
@@ -186,12 +282,22 @@ sendbody:
|
||||
}
|
||||
|
||||
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
|
||||
}
|
||||
|
||||
int can_close = 1;
|
||||
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len, int can_close) {
|
||||
|
||||
if (fd == wsgi_req->sendfile_fd) can_close = 0;
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->write_errors) {
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->ignore_body) {
|
||||
if (can_close) close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
@@ -207,11 +313,15 @@ sendfile:
|
||||
if (len == 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (pos >= (size_t)st.st_size) {
|
||||
if (can_close) close(fd);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
len = st.st_size;
|
||||
}
|
||||
|
||||
@@ -263,6 +373,7 @@ sendfile:
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -297,3 +408,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
simplified write to client
|
||||
(generally used as fallback)
|
||||
*/
|
||||
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+116
@@ -1,5 +1,83 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
|
||||
uwsgi_crc32(crc32, buf, len);
|
||||
return uwsgi_deflate(z, buf, len, dlen);
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_gzip(char *buf, size_t len) {
|
||||
z_stream z;
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
uint32_t gzip_crc32 = 0;
|
||||
char *gzipped = NULL;
|
||||
char *gzipped0 = NULL;
|
||||
size_t dlen = 0;
|
||||
size_t dlen0 = 0;
|
||||
|
||||
uwsgi_crc32(&gzip_crc32, NULL, 0);
|
||||
if (uwsgi_deflate_init(&z, NULL, 0)) return NULL;
|
||||
uwsgi_crc32(&gzip_crc32, buf, len);
|
||||
|
||||
gzipped = uwsgi_deflate(&z, buf, len, &dlen);
|
||||
if (!gzipped) goto end;
|
||||
gzipped0 = uwsgi_deflate(&z, NULL, 0, &dlen0);
|
||||
if (!gzipped0) goto end;
|
||||
|
||||
ub = uwsgi_buffer_new(10 + dlen + dlen0 + 8);
|
||||
if (uwsgi_buffer_append(ub, gzheader, 10)) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped, dlen)) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, gzip_crc32)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end;
|
||||
end:
|
||||
if (gzipped) free(gzipped);
|
||||
if (gzipped0) free(gzipped0);
|
||||
deflateEnd(&z);
|
||||
return ub;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
|
||||
z_stream z;
|
||||
|
||||
z.zalloc = Z_NULL;
|
||||
z.zfree = Z_NULL;
|
||||
z.opaque = Z_NULL;
|
||||
if (inflateInit(&z) != Z_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
unsigned char out[8192];
|
||||
|
||||
z.next_in = (unsigned char *)buf;
|
||||
z.avail_in = len;
|
||||
z.next_out = out;
|
||||
|
||||
do {
|
||||
z.avail_out = 8192;
|
||||
z.next_out = out;
|
||||
int ret = inflate(&z, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
ub = NULL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
while (z.avail_out == 0);
|
||||
end:
|
||||
inflateEnd(&z);
|
||||
return ub;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
@@ -17,6 +95,44 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
|
||||
z->zalloc = Z_NULL;
|
||||
z->zfree = Z_NULL;
|
||||
z->opaque = Z_NULL;
|
||||
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
if (dict && dict_len) {
|
||||
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
|
||||
uwsgi_crc32(crc32, NULL, 0);
|
||||
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fix and free a gzip stream
|
||||
int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t len) {
|
||||
size_t dlen0 = 0;
|
||||
char *gzipped0 = uwsgi_deflate(z, NULL, 0, &dlen0);
|
||||
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;
|
||||
deflateEnd(z);
|
||||
return 0;
|
||||
end:
|
||||
if (gzipped0) free(gzipped0);
|
||||
deflateEnd(z);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_deflate(z_stream *z, char *buf, size_t len, size_t *dlen) {
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
config = {}
|
||||
|
||||
config['immediate-uid'] = 'roberto'
|
||||
config['immediate-gid'] = 'roberto'
|
||||
config['http-socket'] = ':9090'
|
||||
config['env'] = { 'FOO=bar', 'TEST=topogigio' }
|
||||
config['module'] = 'werkzeug.testapp:test_app'
|
||||
|
||||
return config
|
||||
@@ -0,0 +1,8 @@
|
||||
config = {}
|
||||
|
||||
config[1] = { ['http-socket']=':9090' }
|
||||
config[2] = { ['env']='FOO=bar' }
|
||||
config[3] = { ['env']='TEST=topogigio' }
|
||||
config[4] = { ['module']='werkzeug.testapp:test_app' }
|
||||
|
||||
return config
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#AEC84D" d="M170.667,41.334"/>
|
||||
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
|
||||
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
|
||||
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
|
||||
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
|
||||
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
|
||||
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
|
||||
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
|
||||
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
|
||||
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
|
||||
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
|
||||
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
|
||||
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
|
||||
<g>
|
||||
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
|
||||
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
|
||||
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
|
||||
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
|
||||
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
|
||||
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
|
||||
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
|
||||
"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
|
||||
L204.667,32.667z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
|
||||
"/>
|
||||
</g>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
|
||||
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
|
||||
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
|
||||
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
|
||||
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
|
||||
S685.666,30.334,631,33.001z"/>
|
||||
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -1,3 +0,0 @@
|
||||
ngx_addon_name=ngx_http_uwsgi_module
|
||||
HTTP_MODULES="$HTTP_MODULES ngx_http_uwsgi_module"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uwsgi_module.c"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
|
||||
uwsgi_param QUERY_STRING $query_string;
|
||||
uwsgi_param REQUEST_METHOD $request_method;
|
||||
uwsgi_param CONTENT_TYPE $content_type;
|
||||
uwsgi_param CONTENT_LENGTH $content_length;
|
||||
|
||||
uwsgi_param REQUEST_URI $request_uri;
|
||||
uwsgi_param PATH_INFO $document_uri;
|
||||
uwsgi_param DOCUMENT_ROOT $document_root;
|
||||
uwsgi_param SERVER_PROTOCOL $server_protocol;
|
||||
|
||||
uwsgi_param REMOTE_ADDR $remote_addr;
|
||||
uwsgi_param REMOTE_PORT $remote_port;
|
||||
uwsgi_param SERVER_ADDR $server_addr;
|
||||
uwsgi_param SERVER_PORT $server_port;
|
||||
uwsgi_param SERVER_NAME $server_name;
|
||||
@@ -0,0 +1,295 @@
|
||||
#include <uwsgi.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_airbrake_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *apikey;
|
||||
char *env;
|
||||
};
|
||||
|
||||
struct uwsgi_airbrake_opt {
|
||||
char *name;
|
||||
CURLoption option;
|
||||
void (*func)(CURL *, CURLoption, char *, struct uwsgi_airbrake_config*);
|
||||
};
|
||||
|
||||
static void uwsgi_airbrake_ssl(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
curl_easy_setopt(curl, option, (long)CURLUSESSL_ALL);
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_int(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
curl_easy_setopt(curl, option, atoi(arg));
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_set_apikey(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
uacc->apikey = arg;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_set_env(CURL *curl, CURLoption option, char *arg, struct uwsgi_airbrake_config *uacc) {
|
||||
uacc->env = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_airbrake_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
{"apikey", 0, uwsgi_airbrake_set_apikey},
|
||||
{"env", 0, uwsgi_airbrake_set_env},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_airbrake_ssl},
|
||||
{"timeout", CURLOPT_TIMEOUT, uwsgi_airbrake_int},
|
||||
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_airbrake_int},
|
||||
{NULL, 0, NULL},
|
||||
};
|
||||
|
||||
static void uwsgi_airbrake_setopt(CURL *curl, char *opt, struct uwsgi_airbrake_config *uacc) {
|
||||
struct uwsgi_airbrake_opt *o = uaco;
|
||||
char *equal = strchr(opt,'=');
|
||||
if (!equal) {
|
||||
if (!uacc->first) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, opt);
|
||||
uacc->first = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
uacc->first = 1;
|
||||
*equal = 0;
|
||||
while(o->name) {
|
||||
if (!strcmp(o->name, opt)) {
|
||||
if (o->func) {
|
||||
o->func(curl, o->option, equal+1, uacc);
|
||||
}
|
||||
else {
|
||||
curl_easy_setopt(curl, o->option, equal+1);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) {
|
||||
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
|
||||
xmlChar *xmlbuff;
|
||||
int buffersize;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr notice_node = NULL, node = NULL, line_node = NULL, errnode = NULL;
|
||||
char *msg = NULL;
|
||||
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
notice_node = xmlNewNode(NULL, BAD_CAST "notice");
|
||||
xmlNewProp(notice_node, BAD_CAST "version", BAD_CAST "2.3");
|
||||
xmlDocSetRootElement(doc, notice_node);
|
||||
|
||||
xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST uacc->apikey);
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "notifier", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST "uWSGI");
|
||||
xmlNewChild(node, NULL, BAD_CAST "version", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewChild(node, NULL, BAD_CAST "url", BAD_CAST "https://github.com/unbit/uwsgi");
|
||||
|
||||
// request env
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "request", NULL);
|
||||
node = xmlNewChild(node, NULL, BAD_CAST "cgi-data", NULL);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST UWSGI_VERSION);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "uwsgi_version");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST __VERSION__);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "compiled_with_version");
|
||||
|
||||
struct utsname uuts;
|
||||
#ifdef __sun__
|
||||
if (uname(&uuts) < 0) {
|
||||
#else
|
||||
if (uname(&uuts)) {
|
||||
#endif
|
||||
uwsgi_error("uname()");
|
||||
}
|
||||
else {
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.sysname);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_sysname");
|
||||
|
||||
char *os_version = uwsgi_concat3(uuts.release, "-", uuts.version);
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST os_version);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_version");
|
||||
free(os_version);
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.machine);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "machine");
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.nodename);
|
||||
xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "nodename");
|
||||
|
||||
}
|
||||
// end request env
|
||||
|
||||
node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
|
||||
xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
|
||||
if (uacc->env) {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST uacc->env);
|
||||
}
|
||||
else {
|
||||
xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
|
||||
}
|
||||
|
||||
errnode = xmlNewChild(notice_node, NULL, BAD_CAST "error", NULL);
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "class", BAD_CAST "RuntimeError");
|
||||
node = xmlNewChild(errnode, NULL, BAD_CAST "backtrace", NULL);
|
||||
|
||||
char *ctx = NULL;
|
||||
char *text = uwsgi_str(ut->buf);
|
||||
char *p = strtok_r(text, "\n", &ctx);
|
||||
while (p) {
|
||||
// skip log messages
|
||||
if (!uwsgi_startswith(p, "***", 3))
|
||||
goto next;
|
||||
// backtrace line looks like this: uwsgi(simple_loop_run+0xc5) [0x451555]
|
||||
// we take binary/lib as filename
|
||||
// and extract method name from remaining string
|
||||
char *n = strchr(p, '(');
|
||||
if (n) {
|
||||
*n = 0;
|
||||
|
||||
char *pls = strchr(n+1, '+');
|
||||
if (pls) {
|
||||
*pls = 0;
|
||||
}
|
||||
|
||||
if (!strcmp("uwsgi_backtrace", n+1) || !strcmp("what_i_am_doing", n+1)) {
|
||||
goto next;
|
||||
}
|
||||
else if (!strcmp("uwsgi_fpe", n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI FPE at ", n+1, " in ", p);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!msg) {
|
||||
if (strlen(n+1)) {
|
||||
msg = uwsgi_concat4("uWSGI segfault at ", n+1, " in ", p);
|
||||
}
|
||||
else {
|
||||
// method name might be missing
|
||||
msg = uwsgi_concat2("uWSGI segfault in ", p);
|
||||
}
|
||||
}
|
||||
|
||||
// skip empty lines
|
||||
if (!p)
|
||||
goto next;
|
||||
|
||||
line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);
|
||||
|
||||
if ((n+1)[0] == ')') {
|
||||
xmlNewProp(line_node, BAD_CAST "method", BAD_CAST "()");
|
||||
}
|
||||
else {
|
||||
xmlNewProp(line_node, BAD_CAST "method", BAD_CAST n+1);
|
||||
}
|
||||
|
||||
xmlNewProp(line_node, BAD_CAST "file", BAD_CAST p);
|
||||
|
||||
//xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
|
||||
}
|
||||
next:
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
}
|
||||
|
||||
xmlNewChild(errnode, NULL, BAD_CAST "message", BAD_CAST msg);
|
||||
|
||||
xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
free(msg);
|
||||
free(text);
|
||||
|
||||
return (char *) xmlbuff;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
// 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_READFUNCTION, NULL);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
|
||||
// fill curl options
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
uwsgi_airbrake_setopt(curl, uwsgi_str(p), uacc);
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
ut->pos = 0;
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
|
||||
char *notice = uwsgi_format_airbrake_backtrace(ut);
|
||||
|
||||
curl_slist_append(expect, "Accept: */*");
|
||||
curl_slist_append(expect, "Content-Type: text/xml; charset=utf-8");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notice);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(notice));
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
free(notice);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_airbrake_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_airbrake_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_airbrake_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_load(void) {
|
||||
uwsgi_register_alarm("airbrake", uwsgi_airbrake_init, uwsgi_airbrake_func);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin airbrake_plugin = {
|
||||
.name = "airbrake",
|
||||
.on_load = uwsgi_airbrake_load,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from uwsgiconfig import spcall
|
||||
|
||||
NAME='airbrake'
|
||||
|
||||
CFLAGS = [spcall('xml2-config --cflags')]
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lcurl', spcall('xml2-config --libs')]
|
||||
GCC_LIST = ['airbrake_plugin']
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -154,6 +154,7 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
@@ -168,7 +169,8 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (ret < 0) return;
|
||||
if (ret == 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
|
||||
Vendored
+9
-5
@@ -40,7 +40,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
|
||||
if (vallen > 0) {
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
@@ -49,7 +49,7 @@ static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL);
|
||||
char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
uwsgi_response_write_body_do(wsgi_req, value, vallen);
|
||||
free(value);
|
||||
@@ -77,8 +77,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
|
||||
// cache get
|
||||
if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
|
||||
uint64_t vallen = 0;
|
||||
uint64_t expires = 0;
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get2(uc, ucmc->key, ucmc->key_len, &vallen);
|
||||
char *value = uwsgi_cache_get3(uc, ucmc->key, ucmc->key_len, &vallen, &expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return;
|
||||
@@ -88,6 +89,9 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
|
||||
if (uwsgi_buffer_append_keynum(ub, "size", 4, vallen)) goto error;
|
||||
if (expires) {
|
||||
if (uwsgi_buffer_append_keynum(ub, "expires", 7, expires)) goto error;
|
||||
}
|
||||
if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
|
||||
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
|
||||
// unlock !!!
|
||||
@@ -205,7 +209,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
case 0:
|
||||
// get
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
wsgi_req->uh->pktsize = vallen;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
|
||||
@@ -242,7 +246,7 @@ static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
case 5:
|
||||
// get (uwsgi + stream)
|
||||
if (wsgi_req->uh->pktsize > 0) {
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL);
|
||||
value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen, NULL, NULL);
|
||||
if (value) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
|
||||
+103
-14
@@ -9,9 +9,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct carbon_server_list {
|
||||
char *value; // server address
|
||||
int healthy;
|
||||
int errors;
|
||||
char *hostname;
|
||||
char *port;
|
||||
struct carbon_server_list *next;
|
||||
};
|
||||
|
||||
@@ -33,6 +34,11 @@ struct uwsgi_carbon {
|
||||
char *root_node;
|
||||
char *hostname_dot_replacement;
|
||||
char *hostname;
|
||||
int resolve_hostname;
|
||||
char *idle_avg;
|
||||
int push_avg;
|
||||
int zero_avg;
|
||||
uint64_t last_requests;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
} u_carbon;
|
||||
|
||||
@@ -46,6 +52,9 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
|
||||
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
|
||||
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
|
||||
{"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},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -59,15 +68,37 @@ static void carbon_post_init() {
|
||||
|
||||
while(usl) {
|
||||
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
|
||||
u_server->value = usl->value;
|
||||
u_server->healthy = 1;
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p = strtok(usl->value, ":");
|
||||
while (p) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
else if (!u_server->port) {
|
||||
u_server->port = uwsgi_str(p);
|
||||
}
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
|
||||
if (u_server->hostname) free(u_server->hostname);
|
||||
if (u_server->port) free(u_server->port);
|
||||
free(u_server);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u_carbon.servers_data) {
|
||||
u_server->next = u_carbon.servers_data;
|
||||
}
|
||||
u_carbon.servers_data = u_server;
|
||||
|
||||
uwsgi_log("[carbon] added server %s\n", usl->value);
|
||||
uwsgi_log("[carbon] added server %s:%s\n", u_server->hostname, u_server->port);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -80,7 +111,7 @@ static void carbon_post_init() {
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
|
||||
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
|
||||
if (!u_carbon.id) {
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
@@ -95,6 +126,22 @@ static void carbon_post_init() {
|
||||
}
|
||||
}
|
||||
|
||||
u_carbon.push_avg = 1;
|
||||
u_carbon.zero_avg = 0;
|
||||
if (!u_carbon.idle_avg) {
|
||||
u_carbon.idle_avg = "last";
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "zero")) {
|
||||
u_carbon.zero_avg = 1;
|
||||
}
|
||||
else if (!strcmp(u_carbon.idle_avg, "none")) {
|
||||
u_carbon.push_avg = 0;
|
||||
}
|
||||
else if (strcmp(u_carbon.idle_avg, "last")) {
|
||||
uwsgi_log("[carbon] invalid value for carbon-idle-avg: \"%s\"\n", u_carbon.idle_avg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!u_carbon.last_busyness_values) {
|
||||
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
|
||||
}
|
||||
@@ -145,6 +192,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
int i;
|
||||
int fd;
|
||||
int wok;
|
||||
char *ip;
|
||||
char *carbon_address = NULL;
|
||||
|
||||
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];
|
||||
@@ -157,31 +206,44 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (retry_cycle && usl->healthy)
|
||||
// skip healthy servers during retry cycle
|
||||
goto nxt;
|
||||
|
||||
|
||||
if (retry_cycle && usl->healthy == 0)
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->hostname, usl->errors);
|
||||
|
||||
if (!retry_cycle) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
|
||||
if (u_carbon.resolve_hostname) {
|
||||
ip = uwsgi_resolve_ip(usl->hostname);
|
||||
if (!ip) {
|
||||
uwsgi_log("[carbon] Could not resolve hostname %s\n", usl->hostname);
|
||||
goto nxt;
|
||||
}
|
||||
carbon_address = uwsgi_concat3(ip, ":", usl->port);
|
||||
}
|
||||
else {
|
||||
carbon_address = uwsgi_concat3(usl->hostname, ":", usl->port);
|
||||
}
|
||||
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
|
||||
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",
|
||||
usl->value, u_carbon.max_retries);
|
||||
carbon_address, u_carbon.max_retries);
|
||||
usl->healthy = 0;
|
||||
usl->errors = 0;
|
||||
}
|
||||
usl->healthy = 0;
|
||||
usl->errors++;
|
||||
free(carbon_address);
|
||||
goto nxt;
|
||||
}
|
||||
free(carbon_address);
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
@@ -196,6 +258,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
unsigned long long worker_busyness = 0;
|
||||
unsigned long long total_harakiri = 0;
|
||||
|
||||
int do_avg_push;
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
@@ -246,8 +310,19 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -268,8 +343,20 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
do_avg_push = 1;
|
||||
uint64_t c_total_avg_rt = (active_workers ? total_avg_rt / active_workers : 0);
|
||||
if (!u_carbon.last_requests || u_carbon.last_requests == uwsgi.workers[0].requests) {
|
||||
if (!u_carbon.push_avg) {
|
||||
do_avg_push = 0;
|
||||
}
|
||||
else if (u_carbon.zero_avg) {
|
||||
c_total_avg_rt = 0;
|
||||
}
|
||||
}
|
||||
if (do_avg_push) {
|
||||
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) c_total_avg_rt, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
}
|
||||
|
||||
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
@@ -297,6 +384,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
|
||||
u_carbon.last_requests = uwsgi.workers[0].requests;
|
||||
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
|
||||
+112
-46
@@ -18,7 +18,7 @@ struct uwsgi_cgi {
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
@@ -30,7 +30,7 @@ void uwsgi_opt_add_cgi(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
static void uwsgi_opt_add_cgi_maphelper(char *opt, char *value, void *foobar) {
|
||||
char *val = strchr(value, '=');
|
||||
if (!val) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
@@ -66,7 +66,7 @@ struct uwsgi_option uwsgi_cgi_options[] = {
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
static void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
struct stat st;
|
||||
@@ -123,7 +123,7 @@ void uwsgi_cgi_apps() {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_init(){
|
||||
static int uwsgi_cgi_init(){
|
||||
|
||||
void (*cgi_sym)(void);
|
||||
|
||||
@@ -161,7 +161,7 @@ int uwsgi_cgi_init(){
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_helper(char *filename) {
|
||||
static char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
struct uwsgi_dyn_dict *helpers = uc.helpers;
|
||||
size_t len = strlen(filename);
|
||||
@@ -179,7 +179,7 @@ char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
char *key = buf, *value = NULL;
|
||||
@@ -214,7 +214,7 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
// "Status: NNN"
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, key+8, header_size - 8)) return -1;
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
@@ -229,13 +229,13 @@ int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "302 Found", 9)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
@@ -266,7 +266,7 @@ send_body:
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
static char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
|
||||
int best_found = 0;
|
||||
@@ -323,7 +323,7 @@ char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_f
|
||||
return path;
|
||||
}
|
||||
|
||||
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
static int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
@@ -380,18 +380,12 @@ int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_cgi_run(struct wsgi_request *, char *, size_t, char *, char *, char *, char *, int, int);
|
||||
|
||||
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char **argv;
|
||||
int nargs = 0;
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
int is_a_file = 0;
|
||||
@@ -399,7 +393,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
size_t docroot_len = 0;
|
||||
size_t full_path_len = 0;
|
||||
char *helper = NULL;
|
||||
char *command = NULL;
|
||||
char *path_info = NULL;
|
||||
char *script_name = NULL;
|
||||
|
||||
@@ -533,11 +526,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
else {
|
||||
command = full_path;
|
||||
// get the helper
|
||||
if (!is_a_file) {
|
||||
helper = uwsgi_cgi_get_helper(full_path);
|
||||
|
||||
if (helper == NULL) {
|
||||
@@ -551,28 +541,43 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base);
|
||||
if (need_free) free(docroot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_cgi_run(struct wsgi_request *wsgi_req, char *docroot, size_t docroot_len, char *full_path, char *helper, char *path_info, char *script_name, int is_a_file, int discard_base) {
|
||||
|
||||
int cgi_pipe[2];
|
||||
int post_pipe[2];
|
||||
int nargs = 0;
|
||||
int waitpid_status;
|
||||
ssize_t len;
|
||||
int i;
|
||||
char **argv;
|
||||
|
||||
char *command = full_path;
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
|
||||
if (pipe(cgi_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (pipe(post_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
uwsgi_error("pipe()");
|
||||
uwsgi_error("uwsgi_cgi_run()/pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
pid_t cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("uwsgi_cgi_run()/fork()");
|
||||
close(cgi_pipe[0]);
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
@@ -582,9 +587,6 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
close(post_pipe[0]);
|
||||
|
||||
@@ -795,7 +797,7 @@ clear2:
|
||||
}
|
||||
*base = '/';
|
||||
}
|
||||
else {
|
||||
else if (docroot_len > 0) {
|
||||
if (chdir(docroot)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
@@ -837,9 +839,8 @@ clear2:
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +865,7 @@ clear2:
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
uwsgi_error("uwsgi_cgi_run()/execvp()");
|
||||
}
|
||||
|
||||
// never here
|
||||
@@ -872,11 +873,73 @@ clear2:
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
static void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_cgi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_command = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub_command) return UWSGI_ROUTE_BREAK;
|
||||
struct uwsgi_buffer *ub_helper = NULL;
|
||||
if (ur->data2_len) {
|
||||
ub_helper = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub_helper) {
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uwsgi_is_file(ub_command->buf)) {
|
||||
uwsgi_404(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
if (access(ub_command->buf, X_OK)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
// we need a NULL suffix-ed copy of the docroot
|
||||
char *docroot = uwsgi_concat2n(wsgi_req->document_root, wsgi_req->document_root_len, "", 0);
|
||||
uwsgi_cgi_run(wsgi_req, wsgi_req->document_root, wsgi_req->document_root_len, ub_command->buf, ub_helper ? ub_helper->buf : NULL, NULL, NULL, 0, 0 );
|
||||
free(docroot);
|
||||
uwsgi_buffer_destroy(ub_command);
|
||||
if (ub_helper) uwsgi_buffer_destroy(ub_helper);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cgi_helper(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
char *space = strchr(args, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid cgihelper syntax, must be \"cgihelper:helper command\"\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
ur->data = space+1;
|
||||
ur->data_len = strlen(space+1);
|
||||
ur->data2 = args;
|
||||
ur->data2_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_cgi(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cgi;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
static void uwsgi_cgi_register_router() {
|
||||
uwsgi_register_router("cgi", uwsgi_router_cgi);
|
||||
uwsgi_register_router("cgihelper", uwsgi_router_cgi_helper);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin cgi_plugin = {
|
||||
|
||||
@@ -887,5 +950,8 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.options = uwsgi_cgi_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
.after_request = uwsgi_cgi_after_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = uwsgi_cgi_register_router,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -44,10 +44,6 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
peers->in = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// add timeout
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
// check retry
|
||||
if (cs->retry) {
|
||||
peers->can_retry = 1;
|
||||
}
|
||||
peers->prev = old_peers;
|
||||
|
||||
if (old_peers) {
|
||||
@@ -293,18 +289,17 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (peer->failed) {
|
||||
|
||||
if (peer->soopt) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": %s\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, strerror(peer->soopt));
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\" (%d retries): %s\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, peer->retries, strerror(peer->soopt));
|
||||
}
|
||||
else if (peer->timed_out) {
|
||||
if (peer->instance_address_len > 0) {
|
||||
if (peer->connecting) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\": timeout\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address);
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\" (%d retries): timeout\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, peer->retries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -701,7 +696,8 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
if (ucr->use_cache) {
|
||||
ucr->cache = uwsgi_cache_by_name(ucr->use_cache);
|
||||
if (!ucr->cache) {
|
||||
uwsgi_log("unable to find cache \"%s\"\n", ucr->use_cache);
|
||||
uwsgi_log("!!! unable to find cache \"%s\" !!!\n", ucr->use_cache);
|
||||
exit(1);
|
||||
}
|
||||
ucr->mapper = uwsgi_cr_map_use_cache;
|
||||
}
|
||||
@@ -899,7 +895,7 @@ int uwsgi_corerouter_init(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
if (ucr->has_sockets) {
|
||||
|
||||
if (ucr->use_cache && !uwsgi.cache_max_items) {
|
||||
if (ucr->use_cache && !uwsgi.caches) {
|
||||
uwsgi_log("you need to create a uwsgi cache to use the %s (add --cache <n>)\n", ucr->name);
|
||||
exit(1);
|
||||
}
|
||||
@@ -945,7 +941,7 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
uwsgi_error("corerouter_send_stats()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
}\
|
||||
peer->out_pos += len;
|
||||
|
||||
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
|
||||
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
|
||||
if (len < 0) {\
|
||||
cr_try_again;\
|
||||
uwsgi_cr_error(peer, f);\
|
||||
return -1;\
|
||||
}\
|
||||
buf##_pos += len;
|
||||
ubuf##_pos += len;
|
||||
|
||||
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
continue;
|
||||
if (!strcmp(ushared->gateways[i].name, ucr->name)) {
|
||||
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
|
||||
uwsgi_error("send()");
|
||||
uwsgi_error("uwsgi_corerouter_manage_subscription()/send()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +154,14 @@ XS(XS_coroae_accept_request) {
|
||||
|
||||
request:
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
@@ -171,7 +176,7 @@ end:
|
||||
}
|
||||
|
||||
XS(XS_coroae_sighandler) {
|
||||
int sigfd = (int) XSANY.any_ptr;
|
||||
int sigfd = (long) XSANY.any_ptr;
|
||||
uwsgi_receive_signal(sigfd, "worker", uwsgi.mywid);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -13,8 +13,9 @@ class FakeClass {
|
||||
|
||||
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
|
||||
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
|
||||
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
|
||||
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
|
||||
}
|
||||
|
||||
extern "C" int uwsgi_cplusplus_init(){
|
||||
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
FakeClass *fc;
|
||||
|
||||
// empty request ?
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Invalid request. skip.\n");
|
||||
goto clear;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ clear:
|
||||
|
||||
|
||||
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
|
||||
// call log_request(wsgi_req) if you want a standard logline
|
||||
uwsgi_log("logging c++ request\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
|
||||
int uwsgi_cplusplus_init(void);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <uwsgi.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static void curl_cron_func(struct uwsgi_cron *uc, time_t now) {
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
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]);
|
||||
// use 1 minute as the cron resolution
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
|
||||
uwsgi_log("[uwsgi-curl-cron] requesting %s\n", uc->command);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log("[uwsgi-curl-cron] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
static void uwsgi_opt_add_cron_curl(char *opt, char *value, void *foobar) {
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(value);
|
||||
uc->func = curl_cron_func;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
static void uwsgi_opt_add_legion_cron_curl(char *opt, char *value, void *foobar) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
char *legion = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
|
||||
uc->legion = legion;
|
||||
uc->func = curl_cron_func;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct uwsgi_option curl_cron_options[] = {
|
||||
{"curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL", uwsgi_opt_add_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion-curl-cron", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-cron-curl", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"curl-cron-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
{"cron-curl-legion", required_argument, 0, "add a cron task invoking the specified url via CURL runnable only when the instance is a lord of the specified legion", uwsgi_opt_add_legion_cron_curl, NULL, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{ 0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
struct uwsgi_plugin curl_cron_plugin = {
|
||||
.name = "curl_cron",
|
||||
.options = curl_cron_options,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='curl_cron'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lcurl']
|
||||
GCC_LIST = ['curl_cron']
|
||||
@@ -453,7 +453,8 @@ static int amqp_wait_connection_tune(int fd) {
|
||||
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
char *ptr = (char *) fh;
|
||||
ssize_t len = 0, rlen;
|
||||
size_t len = 0;
|
||||
ssize_t rlen;
|
||||
|
||||
while(len < 7) {
|
||||
rlen = recv(fd, ptr, 7-len, 0);
|
||||
|
||||
@@ -49,7 +49,7 @@ void uwsgi_imperial_monitor_amqp_event(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
|
||||
if (msgsize > 0) {
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0);
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0, NULL);
|
||||
}
|
||||
|
||||
end0:
|
||||
@@ -88,7 +88,7 @@ end0:
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0);
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
@@ -60,7 +60,9 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
vassal_gid = tmp_gid;
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
|
||||
const char *socket_name = p.getStringField("socket");
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
|
||||
NAME='emperor_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
|
||||
|
||||
@@ -68,7 +68,11 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
|
||||
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
|
||||
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
|
||||
char *socket_name = NULL;
|
||||
if (PQnfields(res) > 5) {
|
||||
socket_name = PQgetvalue(res, i, 5);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,15 +64,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
int64_t more = 0;
|
||||
size_t more_size = sizeof(more);
|
||||
int i;
|
||||
zmq_msg_t msg[5];
|
||||
zmq_msg_t msg[6];
|
||||
|
||||
zmq_msg_init(&msg[0]);
|
||||
zmq_msg_init(&msg[1]);
|
||||
zmq_msg_init(&msg[2]);
|
||||
zmq_msg_init(&msg[3]);
|
||||
zmq_msg_init(&msg[4]);
|
||||
zmq_msg_init(&msg[5]);
|
||||
|
||||
for(i=0;i<5;i++) {
|
||||
for(i=0;i<6;i++) {
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
|
||||
#else
|
||||
@@ -105,6 +106,11 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
char *ez_gid = NULL;
|
||||
size_t ez_gid_len = 0;
|
||||
|
||||
char *ez_socket_name = NULL;
|
||||
size_t ez_socket_name_len = 0;
|
||||
|
||||
char *socket_name = NULL;
|
||||
|
||||
// config
|
||||
if (i > 1) {
|
||||
ez_config = zmq_msg_data(&msg[2]);
|
||||
@@ -123,6 +129,12 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
ez_gid_len = zmq_msg_size(&msg[4]);
|
||||
}
|
||||
|
||||
// gid
|
||||
if (i > 4) {
|
||||
ez_socket_name = zmq_msg_data(&msg[5]);
|
||||
ez_socket_name_len = zmq_msg_size(&msg[5]);
|
||||
}
|
||||
|
||||
char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);
|
||||
|
||||
// ok let's start checking commands
|
||||
@@ -142,10 +154,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid);
|
||||
if (ez_socket_name) {
|
||||
socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
|
||||
if (config) {
|
||||
free(config);
|
||||
}
|
||||
if (socket_name) {
|
||||
free(socket_name);
|
||||
}
|
||||
}
|
||||
// destroy an instance
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
|
||||
@@ -158,7 +176,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor-zeromq] unkonwn command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
}
|
||||
|
||||
free(name);
|
||||
@@ -168,6 +186,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
zmq_msg_close(&msg[2]);
|
||||
zmq_msg_close(&msg[3]);
|
||||
zmq_msg_close(&msg[4]);
|
||||
zmq_msg_close(&msg[5]);
|
||||
}
|
||||
|
||||
// this is the event manager
|
||||
|
||||
@@ -172,6 +172,9 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
|
||||
cr_peer_connected(peer, "fr_instance_connected()");
|
||||
|
||||
// we are connected, we cannot retry anymore
|
||||
peer->can_retry = 0;
|
||||
|
||||
// fix modifiers
|
||||
peer->in->buf[0] = peer->session->main_peer->modifier1;
|
||||
peer->in->buf[3] = peer->session->main_peer->modifier2;
|
||||
@@ -217,6 +220,8 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
if (new_peer->instance_address_len == 0)
|
||||
return -1;
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
cr_connect(new_peer, fr_instance_connected);
|
||||
}
|
||||
|
||||
|
||||
+21
-8
@@ -2,6 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_rack ur;
|
||||
extern struct uwsgi_plugin rack_plugin;
|
||||
|
||||
struct ufib {
|
||||
int enabled;
|
||||
@@ -15,8 +16,7 @@ struct uwsgi_option fiber_options[] = {
|
||||
|
||||
|
||||
VALUE uwsgi_fiber_request() {
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->suspended = 0;
|
||||
async_schedule_to_req_green();
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -31,30 +31,43 @@ VALUE rb_fiber_schedule_to_req() {
|
||||
|
||||
rb_fiber_resume(ufiber.fib[id], 0, NULL);
|
||||
|
||||
if (uwsgi.wsgi_req->suspended) {
|
||||
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static void fiber_schedule_to_req() {
|
||||
|
||||
int id = uwsgi.wsgi_req->async_id;
|
||||
uint8_t modifier1 = uwsgi.wsgi_req->uh->modifier1;
|
||||
|
||||
// call it in the main core
|
||||
if (uwsgi.p[modifier1]->suspend) {
|
||||
uwsgi.p[modifier1]->suspend(NULL);
|
||||
}
|
||||
|
||||
int error = 0;
|
||||
rb_protect(rb_fiber_schedule_to_req, 0, &error);
|
||||
|
||||
// call it in the main core
|
||||
if (uwsgi.p[modifier1]->resume) {
|
||||
uwsgi.p[modifier1]->resume(NULL);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rack_plugin.exception_log(NULL);
|
||||
rb_gc_unregister_address(&ufiber.fib[id]);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
|
||||
}
|
||||
rb_fiber_yield(0, NULL);
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
|
||||
}
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
|
||||
environment was not blessed by the Go community.
|
||||
|
||||
Instead of completely dropping support for Go, we studied how the gccgo project works and we
|
||||
decided it was a better approach for uWSGI.
|
||||
|
||||
This new plugin works by initializing a new "go runtime" after each fork().
|
||||
|
||||
The runtime calls the Go main function (developed by the user), and pass the whole
|
||||
uWSGI control to it.
|
||||
|
||||
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
|
||||
manages mules, spoolers and workers)
|
||||
|
||||
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
|
||||
from your apps are native goroutines)
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin gccgo_plugin;
|
||||
|
||||
struct uwsgi_gccgo{
|
||||
struct uwsgi_string_list *libs;
|
||||
char *args;
|
||||
} ugccgo;
|
||||
|
||||
/*
|
||||
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
*/
|
||||
|
||||
struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
// no_split_stack is the key to avoid crashing !!!
|
||||
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
|
||||
|
||||
void runtime_check(void);
|
||||
void runtime_args(int, char **);
|
||||
void runtime_osinit(void);
|
||||
void runtime_schedinit(void);
|
||||
void *__go_go(void *, void *);
|
||||
void runtime_main(void);
|
||||
void runtime_mstart(void *);
|
||||
|
||||
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
|
||||
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
|
||||
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
|
||||
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
|
||||
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
|
||||
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
|
||||
|
||||
static void mainstart(void *arg __attribute__((unused))) {
|
||||
runtime_main();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) __asm__ ("main.main");
|
||||
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
|
||||
|
||||
void (*uwsgigo_hook_init)(void);
|
||||
void (*uwsgigo_hook_main)(void);
|
||||
|
||||
void uwsgigo_main_init(void) {
|
||||
uwsgigo_hook_init();
|
||||
}
|
||||
|
||||
void uwsgigo_main_main(void) {
|
||||
uwsgigo_hook_main();
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_request_body_read(struct wsgi_request *wsgi_req, char *p, uint64_t len) {
|
||||
ssize_t rlen = 0;
|
||||
char *buf = uwsgi_request_body_read(wsgi_req, len, &rlen);
|
||||
if (buf == uwsgi.empty) {
|
||||
return 0;
|
||||
}
|
||||
else if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, buf, rlen);
|
||||
return (int) rlen;
|
||||
}
|
||||
|
||||
int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *handler) {
|
||||
return uwsgi_register_signal(signum, receiver, handler, gccgo_plugin.modifier1);
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_initialize() {
|
||||
struct uwsgi_string_list *usl = ugccgo.libs;
|
||||
while(usl) {
|
||||
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!handle) {
|
||||
uwsgi_log("unable to open go shared library: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(handle, "main.main");
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (!uwsgigo_hook_init || !uwsgigo_hook_main) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go runtime initialization
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
argc++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
free(argv_list);
|
||||
}
|
||||
runtime_check();
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
int n = 0;
|
||||
while(p) {
|
||||
argv[n] = p;
|
||||
n++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
runtime_args(argc, argv);
|
||||
}
|
||||
else {
|
||||
char *argv[2] = {0,0};
|
||||
runtime_args(0, argv);
|
||||
}
|
||||
runtime_osinit();
|
||||
runtime_schedinit();
|
||||
__go_go(mainstart, NULL);
|
||||
runtime_mstart(runtime_m());
|
||||
// never here
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->async_environ = uwsgigo_env(wsgi_req);
|
||||
int i;
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
uwsgigo_env_add(wsgi_req->async_environ, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
|
||||
i++;
|
||||
}
|
||||
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
|
||||
uwsgigo_signal_handler(handler, signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin gccgo_plugin = {
|
||||
.name = "gccgo",
|
||||
.modifier1 = 11,
|
||||
.options = uwsgi_gccgo_options,
|
||||
//.on_load = uwsgi_gccgo_on_load,
|
||||
.request = uwsgi_gccgo_request,
|
||||
.after_request = uwsgi_gccgo_after_request,
|
||||
.post_fork = uwsgi_gccgo_initialize,
|
||||
.signal_handler = uwsgi_gccgo_signal_handler,
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
package uwsgi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
//extern uwsgi_takeover
|
||||
func uwsgi_takeover()
|
||||
//extern uwsgi_response_write_body_do
|
||||
func uwsgi_response_write_body_do(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_response_prepare_headers_int
|
||||
func uwsgi_response_prepare_headers_int(*interface{}, int) int
|
||||
//extern uwsgi_response_add_header
|
||||
func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
|
||||
//extern uwsgi_gccgo_helper_request_body_read
|
||||
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_gccgo_helper_register_signal
|
||||
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
|
||||
|
||||
var uwsgi_signals_gc [256]func(uint8)
|
||||
|
||||
func Env(wsgi_req *interface{}) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
return &env
|
||||
}
|
||||
|
||||
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
|
||||
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
r *http.Request
|
||||
wsgi_req *interface{}
|
||||
headers http.Header
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
uwsgi_response_write_body_do(w.wsgi_req, &p[0], uint64(len(p)))
|
||||
return len(p), err
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) WriteHeader(status int) {
|
||||
uwsgi_response_prepare_headers_int(w.wsgi_req, status )
|
||||
if w.headers.Get("Content-Type") == "" {
|
||||
w.headers.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
for k := range w.headers {
|
||||
for _, v := range w.headers[k] {
|
||||
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
|
||||
v = strings.TrimSpace(v)
|
||||
kb := []byte(k)
|
||||
vb := []byte(v)
|
||||
uwsgi_response_add_header(w.wsgi_req, &kb[0], uint16(len(k)), &vb[0], uint16(len(v)))
|
||||
}
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Header() http.Header {
|
||||
return w.headers
|
||||
}
|
||||
|
||||
|
||||
type BodyReader struct {
|
||||
wsgi_req *interface{}
|
||||
}
|
||||
|
||||
// there is no close in request body
|
||||
func (br *BodyReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *BodyReader) Read(p []byte) (n int, err error) {
|
||||
var rlen int = uwsgi_request_body_read(br.wsgi_req, &p[0], uint64(len(p)))
|
||||
if (rlen == 0) {
|
||||
err = io.EOF;
|
||||
return 0, err
|
||||
} else if (rlen == -1) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
return 0, err
|
||||
}
|
||||
return rlen, err
|
||||
}
|
||||
|
||||
func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
|
||||
httpReq, err := cgi.RequestFromMap(*env)
|
||||
if err == nil {
|
||||
httpReq.Body = &BodyReader{wsgi_req}
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
}
|
||||
|
||||
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
var b []byte = []byte(receiver)
|
||||
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
|
||||
return false
|
||||
}
|
||||
uwsgi_signals_gc[signum] = handler
|
||||
return true
|
||||
}
|
||||
|
||||
func SignalHandler(handler func(uint8), signum uint8) {
|
||||
handler(signum)
|
||||
}
|
||||
|
||||
func Run() {
|
||||
uwsgi_takeover()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user