mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ef7819080 | ||
|
|
319ad13af2 | ||
|
|
fe28e90ae3 | ||
|
|
f604a0a533 | ||
|
|
4ab78d42a3 | ||
|
|
c631e7dae6 | ||
|
|
da8e88d638 | ||
|
|
4707d9250d | ||
|
|
d719960411 | ||
|
|
734818c995 | ||
|
|
a35335a820 | ||
|
|
aca4dbfbe7 | ||
|
|
b036029b32 | ||
|
|
52f3e757ed | ||
|
|
c4ce1cf7d8 | ||
|
|
48175d0759 | ||
|
|
2932168db7 | ||
|
|
e8d96b8f84 | ||
|
|
bd15fd9da1 | ||
|
|
6e98eda963 | ||
|
|
ec9bb3601e | ||
|
|
02e4840b29 | ||
|
|
d7e8523fcf | ||
|
|
41464c3bfa | ||
|
|
a3617d0b5a | ||
|
|
10ff849ebd | ||
|
|
c2f7d487d0 | ||
|
|
395cf57e21 | ||
|
|
4c854a83c9 | ||
|
|
881b3b7e0c | ||
|
|
bb28e4279b | ||
|
|
c65b8ce162 | ||
|
|
8a303b1965 | ||
|
|
adca811941 | ||
|
|
f79e9d8773 | ||
|
|
629fbf4f07 | ||
|
|
da9ce52294 | ||
|
|
205605a3c4 | ||
|
|
e39127be92 | ||
|
|
0b2458d74a | ||
|
|
9d661122bd | ||
|
|
8518747a51 | ||
|
|
2f6450a560 | ||
|
|
c72889c10f | ||
|
|
bb7456e3f8 | ||
|
|
5aff13543e | ||
|
|
c7d967d43c | ||
|
|
1a42194304 | ||
|
|
312563437c | ||
|
|
5972ac1ed7 | ||
|
|
75d4123b34 | ||
|
|
89ef4f68a9 | ||
|
|
ed72677e52 | ||
|
|
08ab27c36c | ||
|
|
af8bb8fd05 | ||
|
|
57bade7eae | ||
|
|
3c6de0e84d | ||
|
|
24e3fea334 | ||
|
|
6af77aab8b | ||
|
|
12325633ed | ||
|
|
3a108b61ee | ||
|
|
b2eaf384ac | ||
|
|
3d17ef9603 | ||
|
|
3b031872f7 | ||
|
|
e97d39f37c | ||
|
|
763f715279 | ||
|
|
af9f79f3eb | ||
|
|
01ab3e2895 | ||
|
|
7a34344632 | ||
|
|
9714cb6790 | ||
|
|
aa981d03e8 | ||
|
|
9a09164fc3 | ||
|
|
9674a81323 | ||
|
|
aba7280691 | ||
|
|
ef9908b058 | ||
|
|
4da4fb4cbd | ||
|
|
b4f8a3b179 | ||
|
|
b48a955848 | ||
|
|
5ea4e3bcc3 | ||
|
|
6732cb01a8 | ||
|
|
0b5ca736d4 | ||
|
|
a2358c6bec | ||
|
|
10775dd2ac | ||
|
|
d33d12c642 | ||
|
|
af3ccfeed4 | ||
|
|
1d64267aba | ||
|
|
9bbef9b0c5 | ||
|
|
c95ec82b03 | ||
|
|
46108a00f0 | ||
|
|
d6c3fd7771 | ||
|
|
ad783ccaf0 | ||
|
|
f58be4241f | ||
|
|
cb1d22d88b | ||
|
|
6c8453d98e | ||
|
|
061de3b037 | ||
|
|
ded065ef38 | ||
|
|
822959238c | ||
|
|
4ebb9d7b46 | ||
|
|
cc49964c43 | ||
|
|
3787d5e84a | ||
|
|
7329606a6a | ||
|
|
5facafadea | ||
|
|
d3102df2bf | ||
|
|
87860da238 | ||
|
|
4a8aa01f40 | ||
|
|
9d35067b4b | ||
|
|
1c29be3745 | ||
|
|
bf3c3a3768 | ||
|
|
b25de79ae4 | ||
|
|
ba663ef2cc | ||
|
|
19185640a5 | ||
|
|
eafe8c4fff | ||
|
|
bdd3e69024 | ||
|
|
b5a7ab3688 | ||
|
|
cc0fa8dee6 | ||
|
|
14941cc1c0 | ||
|
|
910cb3a790 | ||
|
|
355e989eea | ||
|
|
bfcd9dad25 | ||
|
|
73ed5fd7cf | ||
|
|
d21cc0970c | ||
|
|
eb8b03139d | ||
|
|
1558145985 | ||
|
|
4ea9a29e62 | ||
|
|
72c8d9cd5e | ||
|
|
fb4fc38f14 | ||
|
|
de25db9e75 | ||
|
|
4ba558430d | ||
|
|
e4711484ac | ||
|
|
5081a3f635 | ||
|
|
b31fa366a2 | ||
|
|
c1b24b390a | ||
|
|
b7461442b0 | ||
|
|
c072e9b609 | ||
|
|
5236c58255 | ||
|
|
4f5280ea2b | ||
|
|
4d1c3fcaea | ||
|
|
310acaf4cc | ||
|
|
8111acaad1 | ||
|
|
c80b10d2b2 | ||
|
|
9807192bd1 | ||
|
|
9386c97851 | ||
|
|
7f3e9b10c4 | ||
|
|
360719582b | ||
|
|
a1a6d4a248 | ||
|
|
015ea78927 | ||
|
|
ad32841aaa | ||
|
|
2a3771dccf | ||
|
|
26af8af48f | ||
|
|
5829c3a843 | ||
|
|
c723d6d9d5 | ||
|
|
2c0c9a918a | ||
|
|
8f9bc7170e | ||
|
|
ee002167d4 | ||
|
|
4ddeb26cca | ||
|
|
a1514e2eaf | ||
|
|
5d1c7ab8b0 | ||
|
|
27698e34f5 | ||
|
|
c06b4773c7 | ||
|
|
e431936a8e | ||
|
|
de3d22a401 | ||
|
|
22778d9de7 | ||
|
|
069f517b04 | ||
|
|
1017dda1ec | ||
|
|
581b4a4216 | ||
|
|
e1f00cbf96 | ||
|
|
32ad0a7b87 | ||
|
|
aa4b9b16fb | ||
|
|
73721ab73a | ||
|
|
90cc3dc389 | ||
|
|
f4f4d5a6c0 | ||
|
|
4bd2410ee7 | ||
|
|
6bc264d33b | ||
|
|
c7d1c6818b | ||
|
|
937e68bf67 | ||
|
|
434fb96be7 | ||
|
|
e2fe86027c | ||
|
|
06ca891d94 | ||
|
|
57c00c9b12 | ||
|
|
b320e1e222 | ||
|
|
c72ddc9dd8 | ||
|
|
c37a386674 | ||
|
|
ad6a79b5b7 | ||
|
|
ff733cd50b | ||
|
|
53128a2391 | ||
|
|
d01fc8804c | ||
|
|
e520d7a58f | ||
|
|
7846ea636c | ||
|
|
0025ad8329 | ||
|
|
1a1f270f4e | ||
|
|
517f4498f5 | ||
|
|
87a165477f | ||
|
|
1e657f0b77 | ||
|
|
a8e399db1e | ||
|
|
66f9607404 | ||
|
|
27319c2da3 | ||
|
|
de21abb21c | ||
|
|
94cae4ac17 | ||
|
|
3b5e1f98f5 | ||
|
|
594f67c6d7 | ||
|
|
f1b415df2f | ||
|
|
c07e0ef581 | ||
|
|
0d4f6501b0 | ||
|
|
d2cbb7eea2 | ||
|
|
f4cb3c67c1 | ||
|
|
a51877cd1d | ||
|
|
c0c3287f74 | ||
|
|
83378802af | ||
|
|
f05d712923 | ||
|
|
5b2df55b8e | ||
|
|
865ec4dd8f | ||
|
|
6ddf1afc81 | ||
|
|
7bd44f4f14 | ||
|
|
a92c2003ee | ||
|
|
97a8c5e4b6 | ||
|
|
a5aa31f13e | ||
|
|
1a0161cb6b | ||
|
|
b8c17baf7c | ||
|
|
e161ea3f0a | ||
|
|
fb827a274b | ||
|
|
7281318ef6 | ||
|
|
80be7385ed | ||
|
|
8913dda413 | ||
|
|
b8ad90104b | ||
|
|
2646109986 | ||
|
|
cf247c828a | ||
|
|
28106e624e | ||
|
|
30e8420342 | ||
|
|
99e4d55e9b | ||
|
|
f9daec9e43 | ||
|
|
68a2902ce3 | ||
|
|
4b2db3de57 | ||
|
|
c4c526df17 | ||
|
|
15ad5531b0 | ||
|
|
c0af1c1094 | ||
|
|
9b89333244 | ||
|
|
1863030078 | ||
|
|
15055ffa0d | ||
|
|
8391ce28f7 | ||
|
|
b38791a357 | ||
|
|
53ba043168 | ||
|
|
d46a8dba7b | ||
|
|
1e62afc161 | ||
|
|
03cf6e868f | ||
|
|
e1da28ccc3 | ||
|
|
4173ca36cb | ||
|
|
c393de492d | ||
|
|
f9a716d70f | ||
|
|
2e8655c203 | ||
|
|
42b7164f33 | ||
|
|
602d49b045 | ||
|
|
58a67df534 | ||
|
|
de6cc04685 | ||
|
|
33763e074d | ||
|
|
32b0f8efb6 | ||
|
|
644618963a | ||
|
|
97ac31376e | ||
|
|
e5ec0f0221 | ||
|
|
5875ddc355 | ||
|
|
f7d5f4692d | ||
|
|
d85bc64aa9 | ||
|
|
a18ed0503c | ||
|
|
77a4e3771b | ||
|
|
7523eb1cb0 | ||
|
|
46f8ee9410 | ||
|
|
f0aa9f9fd2 | ||
|
|
73d5cadd8c | ||
|
|
1a0e2076d5 | ||
|
|
6db3dab5ea | ||
|
|
20856549c1 | ||
|
|
d570845592 | ||
|
|
eed27c0aac | ||
|
|
daef139496 | ||
|
|
3690d836b0 | ||
|
|
93faeb4177 | ||
|
|
095b9154e0 | ||
|
|
f86aa55220 | ||
|
|
40f7aecbba | ||
|
|
5d9d67caa4 | ||
|
|
0f00d6fb23 | ||
|
|
61b0e68641 | ||
|
|
6ed38ced3c | ||
|
|
7a681a97b5 | ||
|
|
41008fa594 | ||
|
|
fb13084b87 | ||
|
|
3f9023281e | ||
|
|
4e21fe6607 | ||
|
|
7a95c726cd | ||
|
|
940401e0f8 | ||
|
|
86bfb20903 | ||
|
|
e21cf87285 | ||
|
|
65f1445b64 | ||
|
|
f87761d092 | ||
|
|
0c712ac28d | ||
|
|
db301531d0 | ||
|
|
4c82a72fd5 | ||
|
|
7417e582c3 | ||
|
|
e32564c7b2 | ||
|
|
798bc482dc | ||
|
|
c7e7f756bc | ||
|
|
24358701f7 | ||
|
|
f1e392c0a0 | ||
|
|
5e8d38d8bc | ||
|
|
4650d2edbb | ||
|
|
b153033514 | ||
|
|
6dcbce5eb7 | ||
|
|
4ceeab439a | ||
|
|
8b1a6be9da | ||
|
|
baeb864075 | ||
|
|
c88e1c3619 | ||
|
|
1b04df7c5e | ||
|
|
237f11dba3 | ||
|
|
313f1c2f29 | ||
|
|
f0862f3bc7 | ||
|
|
1a8850ffe5 | ||
|
|
e640f812ba | ||
|
|
75ea170472 | ||
|
|
1b14b1926e | ||
|
|
edaed7ab01 | ||
|
|
6cceece3d7 | ||
|
|
2add03edb8 | ||
|
|
7aab9bae51 | ||
|
|
46c2c1d885 | ||
|
|
544e97fac0 | ||
|
|
265a700498 | ||
|
|
a657b4b0aa | ||
|
|
ac97c8cf34 | ||
|
|
545f3ee608 | ||
|
|
fcd1a36420 | ||
|
|
47a8ab3da9 | ||
|
|
c4375a8e7a | ||
|
|
a6c5bd3bb3 | ||
|
|
d53127e8cf | ||
|
|
851dd987ab | ||
|
|
cf582af970 | ||
|
|
d0ec331b6b | ||
|
|
cc75f5f7b3 | ||
|
|
3d08b7fdd0 | ||
|
|
7a92449fc3 | ||
|
|
4b3c34469d | ||
|
|
55bf34561e | ||
|
|
7e79dc0405 | ||
|
|
d3053523ab | ||
|
|
e32185cc14 | ||
|
|
8e3e3cf27b | ||
|
|
e2cea376e8 | ||
|
|
2a27b66d96 | ||
|
|
522717ca99 | ||
|
|
5ee106170b | ||
|
|
d62f04a5a6 | ||
|
|
eefe5048b2 | ||
|
|
8f792fde2d | ||
|
|
d8ef2d8300 | ||
|
|
e69dd5cb6a | ||
|
|
8acd57d87e | ||
|
|
a42aa1a273 | ||
|
|
4b2b7ccf82 | ||
|
|
e0fa180a23 | ||
|
|
06ea1fcd1b | ||
|
|
567bcc582d | ||
|
|
844f8c71fa | ||
|
|
bddbbb93cd | ||
|
|
310cc83d36 | ||
|
|
23dcdc5863 | ||
|
|
1286e1835c | ||
|
|
613f2ed939 | ||
|
|
46108f8d0c | ||
|
|
28dcfa4131 | ||
|
|
b48597d3c3 | ||
|
|
fe4c6ba13e | ||
|
|
4049493ffd | ||
|
|
0c9b6e98f7 | ||
|
|
ce33d0be5a | ||
|
|
4f0fb90bff | ||
|
|
66eff0107a | ||
|
|
82f83e610f | ||
|
|
cf7df391ad | ||
|
|
244c9f8204 | ||
|
|
26dc19df7d | ||
|
|
7b8bff1a08 | ||
|
|
0b010124ef | ||
|
|
c7bde15f39 | ||
|
|
b941e4f2f0 | ||
|
|
536c6e7e29 | ||
|
|
dfe4abec35 | ||
|
|
693b80d7d3 | ||
|
|
c9e6475ef4 | ||
|
|
b745132ebd | ||
|
|
19686cb19f | ||
|
|
e0c0593b5b | ||
|
|
415a8af363 | ||
|
|
d44777b1b4 | ||
|
|
e3ff3037b4 | ||
|
|
7add30fd31 | ||
|
|
501cd0349b | ||
|
|
7b4e3f6601 | ||
|
|
8622c2780c | ||
|
|
13de7b6d5b | ||
|
|
53cb864f9c | ||
|
|
72f693f02a | ||
|
|
fb80e32682 | ||
|
|
1db3426ee1 | ||
|
|
a44879e384 | ||
|
|
c0075c817d | ||
|
|
177dc3322b | ||
|
|
21ef4fc89b | ||
|
|
f467643f6f | ||
|
|
3db41e7e05 | ||
|
|
73151729c6 | ||
|
|
5d9c415028 | ||
|
|
b92ed4da4e | ||
|
|
2d1a9a03d2 | ||
|
|
5d6edd2321 | ||
|
|
365f4ba83f | ||
|
|
66e30ae293 | ||
|
|
728425de19 | ||
|
|
b0af1f800b | ||
|
|
543271e856 | ||
|
|
a1564a44fa | ||
|
|
571029cfd3 | ||
|
|
579eaa630a | ||
|
|
9530c8ffe0 | ||
|
|
0d8690091b | ||
|
|
5b5e3a1ec1 | ||
|
|
869ae5e3ed | ||
|
|
d6dc8d86f8 | ||
|
|
758745be68 | ||
|
|
2adfa56d6a | ||
|
|
a4c728f5df | ||
|
|
5c06341b7f | ||
|
|
6f57902a9b | ||
|
|
a3e118893d | ||
|
|
ff2d3c29d6 | ||
|
|
59a8df85f2 | ||
|
|
e303bd182a | ||
|
|
dcef9a497c | ||
|
|
8d4fd66aaf | ||
|
|
471bd23acf | ||
|
|
ffcef81dd0 | ||
|
|
317df5d06b | ||
|
|
ad7b5efd6f | ||
|
|
891f770724 | ||
|
|
0b6d715982 | ||
|
|
76c2415516 | ||
|
|
3260faca17 | ||
|
|
feb493158c | ||
|
|
a5c1556cb7 | ||
|
|
89e640bdd9 | ||
|
|
3ade8daff8 | ||
|
|
049ea3fbed | ||
|
|
715d26beed | ||
|
|
1f5064094c | ||
|
|
7ed522dc29 | ||
|
|
2086500405 | ||
|
|
8f79409ed1 | ||
|
|
c2a3cd1476 | ||
|
|
e195a5d72c | ||
|
|
c86b757904 | ||
|
|
6800d2ac95 | ||
|
|
90fda2b4bb | ||
|
|
bf7ded9058 | ||
|
|
6615dc3a62 | ||
|
|
c35054085c | ||
|
|
fdf2bd7f96 | ||
|
|
1c10b9dfe1 | ||
|
|
6854394e5c | ||
|
|
78a0d5f432 | ||
|
|
5fe5aa70a4 | ||
|
|
e9c0c6bd0b | ||
|
|
5d12b3dc9c | ||
|
|
169a4b66db | ||
|
|
fbd6329db9 | ||
|
|
69c2e56857 | ||
|
|
18f7d1edd3 | ||
|
|
3f7cd5ff92 | ||
|
|
785e1dbf83 | ||
|
|
bc6acf8d14 | ||
|
|
3a099d0b2e | ||
|
|
f9ad5e4144 | ||
|
|
ce9f6650a0 | ||
|
|
fdeef04343 | ||
|
|
fe72ec82e1 | ||
|
|
fd0f308273 | ||
|
|
f4e9ab43cb | ||
|
|
3a141b523c | ||
|
|
2d731532be | ||
|
|
d545cd5be0 | ||
|
|
261d05d67e | ||
|
|
639995785a | ||
|
|
817e076cae | ||
|
|
713370f343 | ||
|
|
5594503a56 | ||
|
|
d57e5d46fb | ||
|
|
ee2db5fabd | ||
|
|
0c4cd6f378 | ||
|
|
8c32b9665c | ||
|
|
7405a01654 | ||
|
|
5d27691b4b | ||
|
|
19bbcfbf4c | ||
|
|
fa1064db87 | ||
|
|
850ac69ca1 | ||
|
|
943edeb30c | ||
|
|
01815a354b | ||
|
|
2f4412aca1 | ||
|
|
2782bb7594 | ||
|
|
074c1298d5 | ||
|
|
55a7911611 | ||
|
|
013ad3044d | ||
|
|
dcf4217b9d | ||
|
|
876dfc31a9 | ||
|
|
fd03bdbe00 | ||
|
|
83612649d5 | ||
|
|
3c4db7e97e | ||
|
|
088c70efdc | ||
|
|
2b19029dd0 | ||
|
|
4fb5a84378 | ||
|
|
b3107d9a25 | ||
|
|
bf32988f3e | ||
|
|
1bf3dd7bf4 | ||
|
|
07fd84f89f | ||
|
|
3a8db4a97a | ||
|
|
aea30a26f5 | ||
|
|
8f5d1cdae7 | ||
|
|
53913357e0 | ||
|
|
098416f444 | ||
|
|
c98cb09c7c | ||
|
|
bb1ef28d69 | ||
|
|
1d5b05265d | ||
|
|
d9fef3c30e | ||
|
|
e5dfb9efc3 | ||
|
|
02bab15e86 | ||
|
|
6f4ddead09 | ||
|
|
b361248ff6 | ||
|
|
e9c42ceaa5 | ||
|
|
5d7029744a | ||
|
|
1084a3afa8 | ||
|
|
ed254bffee | ||
|
|
733784d7dd | ||
|
|
cb5b26bcb4 | ||
|
|
0065152bb1 | ||
|
|
03266203fd | ||
|
|
4a5f68f9d8 | ||
|
|
83e31a1c27 | ||
|
|
0efed5ef9c | ||
|
|
cdfef1281d | ||
|
|
e00907e142 | ||
|
|
6dcbcf39e3 | ||
|
|
044579a8e0 | ||
|
|
d2b52b4663 | ||
|
|
7f75b2c02c | ||
|
|
24a3f671e5 | ||
|
|
875100e3c8 | ||
|
|
34bc7c0cfd | ||
|
|
b39a10ff7c | ||
|
|
02331904de | ||
|
|
d1a4ae694e | ||
|
|
7a5ffc1124 | ||
|
|
19c5bfb42c | ||
|
|
893bf3686b | ||
|
|
e54fa9bcd4 | ||
|
|
c1eb5ab0fe | ||
|
|
461914dde4 | ||
|
|
85662578e4 | ||
|
|
a59c0ae795 | ||
|
|
3a860155ee | ||
|
|
27553c2967 | ||
|
|
9a8ac9af3c | ||
|
|
2f5daffe99 | ||
|
|
75cd31dce4 | ||
|
|
f7150d1b41 | ||
|
|
d6a6b65338 | ||
|
|
979f6027b4 | ||
|
|
7dc059c75b | ||
|
|
b639b5974f | ||
|
|
0de08c553c | ||
|
|
80788ac695 | ||
|
|
1494c621c1 | ||
|
|
605e5b5173 | ||
|
|
4cf2213051 | ||
|
|
3aa36668e5 | ||
|
|
1c0b5b42e9 | ||
|
|
702dc44fad | ||
|
|
2cae07aa52 | ||
|
|
b5616ff25c | ||
|
|
b7b7521975 | ||
|
|
dce3263ee3 | ||
|
|
9796e05ca1 | ||
|
|
5cc0d459ec | ||
|
|
531a850a71 | ||
|
|
4c36280287 | ||
|
|
70be8eb55e | ||
|
|
f8b757b21e | ||
|
|
3a63d352bb | ||
|
|
60467705c5 | ||
|
|
eada0c09e0 | ||
|
|
8e851aa6a1 | ||
|
|
eaf7bb967d | ||
|
|
7be45c77b1 | ||
|
|
5e2b460dc8 | ||
|
|
16143e698f | ||
|
|
4259946e3b | ||
|
|
0a750d76ee | ||
|
|
e4a9f5f0dd | ||
|
|
d5b7698f89 | ||
|
|
a481e8508e | ||
|
|
a53b57497b | ||
|
|
d871357b2d | ||
|
|
2d57db55f4 | ||
|
|
bae45ce03a | ||
|
|
44cc4336f1 | ||
|
|
44f6e214fd | ||
|
|
3e46f81d2b | ||
|
|
e4532b9a50 | ||
|
|
2694be562c | ||
|
|
fadb9edd7f | ||
|
|
d85e0790de | ||
|
|
bc46c4d704 | ||
|
|
a73a010188 | ||
|
|
4e8c8ef317 | ||
|
|
e402e7805d | ||
|
|
302b8f026b | ||
|
|
630054b72a | ||
|
|
a05f459b2b | ||
|
|
207979580a | ||
|
|
f69526f8bf | ||
|
|
e249d567a1 | ||
|
|
a23ba653da | ||
|
|
0644d53572 | ||
|
|
f58f51294d | ||
|
|
86194eb93e | ||
|
|
0a89f375e6 | ||
|
|
6282178b3c | ||
|
|
8e14d68022 | ||
|
|
e86bd0c070 | ||
|
|
bf991f8892 | ||
|
|
b341678d20 | ||
|
|
5f59365d88 | ||
|
|
5130a7bb33 | ||
|
|
cc84a596d6 | ||
|
|
e67bed431a | ||
|
|
72613a9f48 | ||
|
|
c048ea0615 | ||
|
|
957ca1b7ed | ||
|
|
d80a6df039 | ||
|
|
94f9bd9d91 | ||
|
|
b480efe672 | ||
|
|
4fc306d979 | ||
|
|
56abccbdeb | ||
|
|
f218af0735 | ||
|
|
9b69c62780 | ||
|
|
eb5d67e07f | ||
|
|
e7391987b1 | ||
|
|
02cbe15575 | ||
|
|
a5a657f0d4 | ||
|
|
67567c86e0 | ||
|
|
445d02da45 | ||
|
|
4a05df41ce | ||
|
|
5c0c2f6b45 | ||
|
|
0ab55fef46 | ||
|
|
dd344bfe38 | ||
|
|
e92a889bcc | ||
|
|
419d656a83 | ||
|
|
3c3d58bfe9 | ||
|
|
1989099cc5 | ||
|
|
1446e3f0a9 | ||
|
|
00fc31289d | ||
|
|
2c463ad6af | ||
|
|
e641ae05c4 | ||
|
|
a13e0075ee | ||
|
|
e617a7b88e | ||
|
|
cbdeb4caad | ||
|
|
59314d692f | ||
|
|
3dfa56b279 | ||
|
|
920d5d7416 | ||
|
|
dcb654d7fb | ||
|
|
a563da1223 | ||
|
|
1e26cda615 | ||
|
|
97133b27ce | ||
|
|
b428bd3b87 | ||
|
|
05136e74b4 | ||
|
|
9f28a8bdf1 | ||
|
|
d9361f1fee | ||
|
|
835230b1a4 | ||
|
|
f88f51c553 | ||
|
|
1996305eb1 | ||
|
|
c7ad50e950 | ||
|
|
0ec0c29d67 | ||
|
|
75af117e8a | ||
|
|
2b04cefe4e | ||
|
|
0e41c4111a | ||
|
|
5f5d382c64 | ||
|
|
3e867fe401 | ||
|
|
153142b8b0 | ||
|
|
5562c0c047 | ||
|
|
f4a1f800ba | ||
|
|
bdbc5e5605 | ||
|
|
4104f825ff | ||
|
|
efa01ea404 | ||
|
|
982559ae66 | ||
|
|
60002e8de8 | ||
|
|
25d671e0f6 | ||
|
|
5a58281a3f | ||
|
|
c422231806 | ||
|
|
4979883fe5 | ||
|
|
8158a624d3 | ||
|
|
06403b5fce | ||
|
|
bc482652fc | ||
|
|
58aa5755e0 | ||
|
|
bca835c58a | ||
|
|
4b0f68a57a | ||
|
|
b693d73ebe | ||
|
|
dfab80447b | ||
|
|
bbde0c866a | ||
|
|
7b3514f757 | ||
|
|
6d5fb3b252 | ||
|
|
87e8f118d3 | ||
|
|
3ae78cc0a8 | ||
|
|
7ef921356f | ||
|
|
378185d997 | ||
|
|
c4b15a8509 | ||
|
|
96ef9d155b | ||
|
|
d5e6412b20 | ||
|
|
eebe757c16 | ||
|
|
43a21d32cb | ||
|
|
9f9eb5ef17 | ||
|
|
0116c62980 | ||
|
|
fae446e495 | ||
|
|
6f7054df18 | ||
|
|
0f31c21f4a | ||
|
|
bd3e234703 | ||
|
|
71bfd63623 | ||
|
|
98b89dc83c | ||
|
|
97ec789bbe | ||
|
|
14b403c046 | ||
|
|
bc01d25068 | ||
|
|
69808c34a8 | ||
|
|
273181daf5 | ||
|
|
8d2394eba1 | ||
|
|
6f5b468b11 | ||
|
|
c9e759bc14 | ||
|
|
e6d064f5c1 | ||
|
|
8f7ed02475 | ||
|
|
f7edcebbdc | ||
|
|
a19b392ba6 | ||
|
|
287df9ef86 | ||
|
|
de7be379c4 | ||
|
|
1e4d41795c | ||
|
|
e2e973a20e | ||
|
|
5d993fbfc0 | ||
|
|
a94a8ea287 | ||
|
|
55d8677a46 | ||
|
|
4004aeb54e | ||
|
|
2de2898d86 | ||
|
|
8c1b48a88d | ||
|
|
9bd3022a5e | ||
|
|
eb0ce609f0 | ||
|
|
5353eba35b | ||
|
|
4f94ceed5e | ||
|
|
cd29998b40 | ||
|
|
9aad6be26a | ||
|
|
19edee88bc | ||
|
|
42e6a7d024 | ||
|
|
1890290d05 | ||
|
|
c85231be96 | ||
|
|
0ca89771d6 | ||
|
|
d203b12464 | ||
|
|
b64690bdd6 | ||
|
|
e76c696678 | ||
|
|
f1ad2090fc | ||
|
|
f0be3c3966 | ||
|
|
8b7abc956f | ||
|
|
25a8af392b | ||
|
|
ebe1b3497e | ||
|
|
6a7246fe5a | ||
|
|
1d64e46fcd | ||
|
|
6d5e089e4e | ||
|
|
845bc1d41b | ||
|
|
007cd73ac5 | ||
|
|
651a7e4078 | ||
|
|
c3423370ec | ||
|
|
500f1e37f6 | ||
|
|
699a9bfa8e | ||
|
|
90aa7f0d0e | ||
|
|
527819703e | ||
|
|
47adc8fe48 | ||
|
|
865ad5d631 | ||
|
|
877b99c1d5 | ||
|
|
45bb124200 | ||
|
|
147af04342 | ||
|
|
b30e54bdc1 | ||
|
|
1b7484cf22 | ||
|
|
c04513f8bd | ||
|
|
c29db6ee6f | ||
|
|
0d60b001fb | ||
|
|
ea7d428c1b | ||
|
|
55ac61dbb0 | ||
|
|
048878b197 | ||
|
|
1e479de839 | ||
|
|
5b34f6c515 | ||
|
|
8fcf83769c | ||
|
|
d1ca55da55 | ||
|
|
375328623b | ||
|
|
be15137a49 | ||
|
|
43d89b2eaf | ||
|
|
d590a189ed | ||
|
|
c26861bff6 | ||
|
|
b4923deae2 | ||
|
|
20e7a65d92 | ||
|
|
fc895d105e | ||
|
|
e0e8dbe6b6 | ||
|
|
8e5834dcbb | ||
|
|
668c173969 | ||
|
|
4c19a941eb | ||
|
|
9761153ab0 | ||
|
|
140a1b1587 | ||
|
|
e5f5f40f3c | ||
|
|
2e13622ecc | ||
|
|
a4fb281859 | ||
|
|
75ba4e2220 | ||
|
|
24b17da2ea | ||
|
|
c4664fe6e3 | ||
|
|
a1ab298609 | ||
|
|
533f9f8323 | ||
|
|
6d5912f307 | ||
|
|
3d2b7c136a | ||
|
|
f25d147908 | ||
|
|
e119c8cc53 | ||
|
|
73e94350df | ||
|
|
9d8ee5aec8 | ||
|
|
c3bbd5f54f | ||
|
|
e17be93cb6 | ||
|
|
1013ca340a | ||
|
|
b87e7c0af8 | ||
|
|
615348c5a1 | ||
|
|
cae0f9bc2e | ||
|
|
93b23e3de0 | ||
|
|
eebb00d2b3 | ||
|
|
11f9b04fd1 | ||
|
|
bde996de75 | ||
|
|
552163a3bd | ||
|
|
2e6af966a9 | ||
|
|
c1775967c8 | ||
|
|
034a0a594d | ||
|
|
63a66ea82a | ||
|
|
6f155ebf17 | ||
|
|
f39d8cc5fb | ||
|
|
aecba7e710 | ||
|
|
c365eeec76 | ||
|
|
5bd06402de | ||
|
|
ec899a45d5 | ||
|
|
513c9cee3d | ||
|
|
850f2abd5c | ||
|
|
8d7940ebee | ||
|
|
195e9c398e | ||
|
|
c998d6bd1b | ||
|
|
34be14ece1 | ||
|
|
c0d6f33d54 | ||
|
|
d5210283ca | ||
|
|
545784d7af | ||
|
|
e9726b1e75 | ||
|
|
e08b2cccf9 | ||
|
|
0ba1b982d1 | ||
|
|
374c02c46e | ||
|
|
5ed59690a0 | ||
|
|
2de489f301 | ||
|
|
40a722294f | ||
|
|
9598c525cf | ||
|
|
3ed6c5e943 | ||
|
|
0f178c17ee | ||
|
|
1c963b72a3 | ||
|
|
bd1b3b8b12 | ||
|
|
f9a843dfd5 | ||
|
|
9df8f4ae2b | ||
|
|
87f649b71b | ||
|
|
3585bb0a6e | ||
|
|
750bbd64b2 | ||
|
|
19c567cef3 | ||
|
|
5024368854 | ||
|
|
3200f88363 | ||
|
|
650c77d0d1 | ||
|
|
3fa29515f2 | ||
|
|
012435747e | ||
|
|
733077a437 | ||
|
|
6b3fa74800 | ||
|
|
d673627c79 | ||
|
|
8b423d00e9 | ||
|
|
201086c854 | ||
|
|
2441cf36b3 | ||
|
|
df0f2a549e | ||
|
|
9b7cbab37c | ||
|
|
ac46cb2371 | ||
|
|
c858c88bb3 | ||
|
|
a05f5d9860 | ||
|
|
e6914b91e1 | ||
|
|
b624bd2d35 | ||
|
|
e3c9b2c0bf | ||
|
|
576a1e7cb2 | ||
|
|
55c3ba73d3 | ||
|
|
2246d30bbe | ||
|
|
789e333736 | ||
|
|
283904107f | ||
|
|
8d92261852 | ||
|
|
e8f5d82b78 | ||
|
|
0a8643155e | ||
|
|
61793201c7 | ||
|
|
41f2982074 | ||
|
|
27b86f1b79 | ||
|
|
d69892c91e | ||
|
|
296549d1bf | ||
|
|
7d2f147172 | ||
|
|
aa56f99ee2 | ||
|
|
ca82b99f42 | ||
|
|
d204a5b844 | ||
|
|
0a98550770 | ||
|
|
0c0c2736a7 | ||
|
|
27e2d984ce | ||
|
|
14eeae09b1 | ||
|
|
16eb47070d | ||
|
|
1f69f58593 | ||
|
|
1b4421e013 | ||
|
|
f13400d592 | ||
|
|
e29f0323ea | ||
|
|
15a582d046 | ||
|
|
1e01f8be17 | ||
|
|
8cc73991a3 | ||
|
|
ecce74ade5 | ||
|
|
836efaaf70 | ||
|
|
46f8e7dc00 | ||
|
|
88cd033ca6 | ||
|
|
984df3bcdf | ||
|
|
7673cdb1aa | ||
|
|
8af700ce37 | ||
|
|
ffb8752190 | ||
|
|
71fa3ab3af | ||
|
|
09501cfa74 | ||
|
|
d84ae12733 | ||
|
|
05f292abe6 | ||
|
|
a75833d322 | ||
|
|
ca3f56de5c | ||
|
|
9d75f2c9c7 | ||
|
|
a58cbf92b0 | ||
|
|
7bac76fae5 | ||
|
|
9c71b39edd | ||
|
|
52f731c6b7 | ||
|
|
735d1cb689 | ||
|
|
5a0977f412 | ||
|
|
1da1fccbc7 | ||
|
|
ca5a528818 | ||
|
|
a9ef806a37 | ||
|
|
de112b7788 | ||
|
|
ef7baba274 | ||
|
|
3a9d13b011 | ||
|
|
5b5493aab0 | ||
|
|
5f208d8f12 | ||
|
|
47c077d066 | ||
|
|
d2ac69b6c1 | ||
|
|
8860cac7dd | ||
|
|
28bcc73c70 | ||
|
|
af20c2d8f0 | ||
|
|
44213ca510 | ||
|
|
ab21a1ac00 | ||
|
|
a67f366501 | ||
|
|
b32251e5aa | ||
|
|
16e0accb74 | ||
|
|
c6ce291cbf | ||
|
|
b7525475d8 | ||
|
|
f35a36ac02 | ||
|
|
3b53f89a24 | ||
|
|
764d94e41b | ||
|
|
0292e15497 | ||
|
|
bde4ac7b2f | ||
|
|
c71fa3abd1 | ||
|
|
d2abdb5d3a | ||
|
|
1392791837 | ||
|
|
6f7d9634d5 | ||
|
|
82b95114a8 | ||
|
|
d90e701acd | ||
|
|
42993022bb | ||
|
|
29b1e46252 | ||
|
|
260cea639f | ||
|
|
208aea8aca | ||
|
|
f164d401d3 | ||
|
|
5e1c34a08b | ||
|
|
9c7b596a0d | ||
|
|
5ff34ac6d0 | ||
|
|
e304e34929 | ||
|
|
6d7848248d | ||
|
|
dbc0da0586 | ||
|
|
fecdcf9d10 | ||
|
|
bfd0ab2301 | ||
|
|
8002777e75 | ||
|
|
d57d5acb30 | ||
|
|
43e6664dd9 | ||
|
|
d0c6dff83e | ||
|
|
54b40f5978 | ||
|
|
1c59c03261 | ||
|
|
ce23fd38ab | ||
|
|
4818efa7de | ||
|
|
ea19e74229 | ||
|
|
fe353de5a8 | ||
|
|
1d89266f2e | ||
|
|
61d79394ca | ||
|
|
491f2828b5 | ||
|
|
431e05d4f4 | ||
|
|
ae6780a487 | ||
|
|
5707a70141 | ||
|
|
e9a7bd7da1 | ||
|
|
91e45daf6c | ||
|
|
9f69998075 | ||
|
|
4f6270976b | ||
|
|
328caa43f2 | ||
|
|
368408374a | ||
|
|
c3a90db493 | ||
|
|
5bc0320877 | ||
|
|
622ed620b9 | ||
|
|
1b859413de | ||
|
|
95432fd8e3 | ||
|
|
b3f3c5d7b3 | ||
|
|
02cef20462 | ||
|
|
3edebe34ae | ||
|
|
28c9b75fb5 | ||
|
|
a2735e10b7 | ||
|
|
e03d26fd63 | ||
|
|
7c4c346e64 | ||
|
|
67b3c0c4a8 | ||
|
|
dadca785e4 | ||
|
|
accebe5597 | ||
|
|
792965bedd | ||
|
|
1bb1bafe0c | ||
|
|
28c11324ca | ||
|
|
42d940c38e | ||
|
|
c1ea05b925 | ||
|
|
9435693865 | ||
|
|
14da582637 | ||
|
|
b2d4a795a1 | ||
|
|
493696705b | ||
|
|
d827c6f09a | ||
|
|
df000b0cb2 | ||
|
|
d9630a32c7 | ||
|
|
71cc6f61bd | ||
|
|
46eb832cc7 | ||
|
|
11b2e4b430 | ||
|
|
11775532ee | ||
|
|
f3388db8ba | ||
|
|
25ac86393f | ||
|
|
b3432a95e1 | ||
|
|
e34d169fa6 | ||
|
|
de84accb7a | ||
|
|
187577cbb5 | ||
|
|
72109b72d2 | ||
|
|
f6c01d11e9 | ||
|
|
d695ef4f57 | ||
|
|
16c6dcc573 | ||
|
|
3df19b286a | ||
|
|
6f1b08762d | ||
|
|
a4a379f9d6 | ||
|
|
3d3d0304bc | ||
|
|
26135018a3 | ||
|
|
4bd381bb99 | ||
|
|
cf08972e82 | ||
|
|
d57a58d1e7 | ||
|
|
f10789965e | ||
|
|
94145bd300 | ||
|
|
cdcb61d10d | ||
|
|
56146a34af | ||
|
|
991e818449 | ||
|
|
80083cba76 | ||
|
|
2c44fd5aa2 | ||
|
|
1561dd38fc | ||
|
|
8152648f66 | ||
|
|
c1507d0381 | ||
|
|
f0fb603af2 | ||
|
|
93e891153f | ||
|
|
26ece717b6 | ||
|
|
93767335ca | ||
|
|
7cbe751a39 | ||
|
|
c45df83f19 | ||
|
|
fabce61a58 | ||
|
|
5c9ccae598 | ||
|
|
6c9d7239f2 | ||
|
|
4b75e2577e | ||
|
|
08c9d942a4 | ||
|
|
3b59b4ad21 | ||
|
|
7682eec52a | ||
|
|
694517bbe7 | ||
|
|
7f443fdd05 | ||
|
|
01ab891c11 | ||
|
|
052aacfd36 | ||
|
|
80a6d2ccfb | ||
|
|
b4ce175bdf | ||
|
|
f6f52d32dc | ||
|
|
865b2de9bb | ||
|
|
4a8233a041 | ||
|
|
f856ad78a3 | ||
|
|
653267cbe6 | ||
|
|
8b53df27ab | ||
|
|
c4b7c2b58c | ||
|
|
66f82f364c | ||
|
|
6d269607d2 | ||
|
|
8370977e5b | ||
|
|
e2c335ff73 | ||
|
|
816b9d0343 | ||
|
|
2922e1ba35 | ||
|
|
c86f341d29 | ||
|
|
73cdd68283 | ||
|
|
81641686bc | ||
|
|
14c58c8e62 | ||
|
|
74b8f2587c | ||
|
|
bebe041061 | ||
|
|
2e5d3d2952 | ||
|
|
c2d155b8ff | ||
|
|
fda368ff08 | ||
|
|
19cf592e77 | ||
|
|
260cac6b59 | ||
|
|
673275e708 | ||
|
|
a6bc778c25 | ||
|
|
ef2f5879b6 | ||
|
|
ee725bf625 | ||
|
|
5388fa442c | ||
|
|
913493fd2e | ||
|
|
6d4a8c6619 | ||
|
|
4a57115336 | ||
|
|
1dd754a0d5 | ||
|
|
509b78d906 | ||
|
|
363366d012 | ||
|
|
26d4fd4e00 | ||
|
|
09ee97e775 | ||
|
|
1400a95cec | ||
|
|
5e96c4ca79 | ||
|
|
3c068b2a00 | ||
|
|
81fd7757c1 | ||
|
|
1db64b72ae | ||
|
|
ab1bed236c | ||
|
|
e503999392 | ||
|
|
2392eb7e0b | ||
|
|
c62b54f18d | ||
|
|
603d46c1ae | ||
|
|
c0e0ae551d | ||
|
|
a0a2507c05 | ||
|
|
6eed48b28d | ||
|
|
9c5d289098 | ||
|
|
42ab7f23d8 | ||
|
|
c9c2f4232e | ||
|
|
d4f23cc6bd | ||
|
|
b0db67d4d4 | ||
|
|
703cad6715 | ||
|
|
667d67460f | ||
|
|
35cf9ae328 | ||
|
|
c04131af4b | ||
|
|
9cc4db1a12 | ||
|
|
b326500913 | ||
|
|
a26579fcf5 | ||
|
|
a2b9c44433 | ||
|
|
c3b97da1d4 | ||
|
|
048cf0232a | ||
|
|
89c113bee6 | ||
|
|
6b9969a302 | ||
|
|
a6e7513d2a | ||
|
|
8a04f4810f | ||
|
|
1d9d443de0 | ||
|
|
00e5809a71 | ||
|
|
07ba4a040b | ||
|
|
7b319d230a | ||
|
|
641bc2daec | ||
|
|
fbaa30cc08 | ||
|
|
a0c2c9056b | ||
|
|
30ab5fd76b | ||
|
|
30beab4017 | ||
|
|
4ec1493b09 | ||
|
|
e7cbe9709e | ||
|
|
aacaeba525 | ||
|
|
6e4da5efb7 | ||
|
|
87443a4ff2 |
@@ -17,3 +17,33 @@ eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
|
||||
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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
- this is a incomplete list of all the contributors of the project -
|
||||
|
||||
Roberto De Ioris, Unbit, <roberto@unbit.it>
|
||||
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
|
||||
Yann Malet, Lincoln Loop
|
||||
Simon Litchfield
|
||||
Masahiro Honma, <hiratara@cpan.org>
|
||||
Łukasz Wróblewski <admin@nri.pl>
|
||||
Giacomo Bagnoli, Asidev
|
||||
Guido Notari, Link I.T. S.p.a.
|
||||
Marco Beri, Link I.T. S.p.a.
|
||||
Leonid Borisenko
|
||||
Cal Leeming, Simplicity Media Ltd
|
||||
Luigi Scarso
|
||||
Corey Farwell
|
||||
Charles Duffy
|
||||
Lukas Lalinsky
|
||||
Steven Fernandez
|
||||
Łukasz Mierzwa
|
||||
Roy Marples
|
||||
@@ -1,3 +1,231 @@
|
||||
*** december 2011 ***
|
||||
|
||||
* 1.0 [20111230]
|
||||
|
||||
- adaptive process spawning (--cheaper option)
|
||||
- new control options --stop, --reload, --suspend, --resume, --pause
|
||||
- stats framework
|
||||
- new subscription system
|
||||
- support for mime types in static file serving
|
||||
- posix capablities support
|
||||
- uWSGI mules and farms
|
||||
- support for multiple --touch-reload options
|
||||
- new logging subsystem
|
||||
- new custom locking subsystem
|
||||
- process name handling
|
||||
- better (and faster) HTTP parser
|
||||
- perl and python threading improvements
|
||||
- new plugins: rrdtool, carbon, cgi, php
|
||||
- various improvements in the Rack/ruby plugin
|
||||
- Linux KSM support
|
||||
- refactored ping and nagios plugins
|
||||
- support for signals in lazy mode
|
||||
- optimized static-file serving
|
||||
- support for linux unshare()
|
||||
|
||||
*** august 2011 ***
|
||||
|
||||
* 0.9.9 [20110829]
|
||||
|
||||
- various spooler improvements
|
||||
- upload progress optimizations and fixes
|
||||
- new emperor mode: Tyrant
|
||||
- allows multiple --ini options
|
||||
- better binary path detection
|
||||
- gevent loop engine support
|
||||
- resolve domain names in socket logging
|
||||
- snmp fixes and reintroduction of the snmp-api
|
||||
- fixed grunt mode
|
||||
- you can specify build profile via env var UWSGI_PROFILE
|
||||
- reintroduction of string-based multiapp
|
||||
- new option --emperor-throttle
|
||||
- improved queue and sharedarea subsystems
|
||||
- uWSGI can now be built as a shared library
|
||||
- new api attribute: uwsgi.magic_table
|
||||
- improved apache2 module
|
||||
- new option --pyshell
|
||||
- allow threads in gateways
|
||||
- fastrouter improvements
|
||||
- the application list is now shared and exported to the api
|
||||
- allows setting the thread stack size
|
||||
- UWSGI_APPID for better multiapp hosting
|
||||
- better reloading in lazy mode
|
||||
- native pump support
|
||||
- various rack fixes
|
||||
- support for attaching binary data in the executable
|
||||
- new option --set
|
||||
- extreme-optimized http protocol parser
|
||||
- WSGI handler optimizations
|
||||
|
||||
*** july 2011 ***
|
||||
|
||||
* 0.9.8.3 [20110723]
|
||||
|
||||
- implemented uwsgi.SymZipImporter to load embedded zip files
|
||||
- OSX Lion is officially supported
|
||||
- fixed xinetd support (example file added in contrib)
|
||||
- suppot for systemd socket activation
|
||||
- added --freebind option (Linux only)
|
||||
|
||||
* 0.9.8.2 [20110719]
|
||||
|
||||
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
|
||||
- spooler has been extremely improved
|
||||
- new option --chown-socket
|
||||
- added uwsgidecorators for elegant uwsgi api access from python
|
||||
- the rack plugin is now stable
|
||||
- support for embedding config and generic files in the server binary
|
||||
- high-performance cache-server
|
||||
- accept() is now locked on all threads in the same workers
|
||||
- preliminary implementation of hooks in emperor
|
||||
- support for C++ in server core
|
||||
- tcp port auto-bind
|
||||
- implemented workers, workerN and spooler signal target
|
||||
- prefork/multithread uwsgi.signal_wait() implementation
|
||||
- export uwsgi.node in WSGI vars
|
||||
- new option --import (python plugin)
|
||||
- support for unlimited number of Linux cgroups
|
||||
- broodlord mode
|
||||
|
||||
*** june 2011 ***
|
||||
|
||||
* 0.9.8.1 [20110625]
|
||||
|
||||
- the build system has been improved
|
||||
- various threading fixes
|
||||
- fix python GIL status after reload
|
||||
- new option --propagate-touch
|
||||
- fixed uwsgi.sendfile
|
||||
- fixed readline() support in wsgi.input
|
||||
- fixed dynamic touch reload
|
||||
- new option --logto2
|
||||
- export %c in config files
|
||||
- fixed libyaml support
|
||||
- support passing modifiers in subscription system
|
||||
- reset random seed in spooler
|
||||
- subscribe from a list in a text file
|
||||
- allow binding on port 0 (auto-assignment)
|
||||
- reset random seed on grunt
|
||||
- fix vhost mode for empty hostname
|
||||
- fixed python3+virtualenv support
|
||||
- tasks are now allowed to chdir() in spooler
|
||||
- better zeromq+clustering support
|
||||
- clustering has been refactored
|
||||
- fixed rpc
|
||||
- report correct worker id in cheap mode
|
||||
- fixed a fd-leak in attach-daemon
|
||||
- use setsid() in attach-daemon
|
||||
- zerg mode
|
||||
- added psgix.harakiri
|
||||
- allows magic vars in sqlite3 config db
|
||||
- added UWSGI_FASTROUTER_KEY var
|
||||
- slowdown async-queue-is-full messages
|
||||
- new option --cron
|
||||
- --vassals-start-hook and --vassals-stop-hook
|
||||
- the proxy plugin has been removed
|
||||
|
||||
* 0.9.8 [20110605]
|
||||
|
||||
- support for --callable in virtualhosting mode
|
||||
- a NetBSD fix
|
||||
- abstract unix socket can be prefixed with \0 (nginx-style)
|
||||
- add /lib to the linker in sun-like systems
|
||||
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
|
||||
|
||||
* 0.9.8-rc4 [20110602]
|
||||
|
||||
- fixed REMOTE_ADDR when --protocol=http
|
||||
- official support for OpenIndiana
|
||||
- added a welcome.py test script
|
||||
- new api attribute uwsgi.version_info
|
||||
- improved the admin plugin
|
||||
- two new management flag for backlog queue monitoring
|
||||
- fixed uwsgi_log for bigger loglines
|
||||
- new option --early-emperor to allows out-of-jail emperors
|
||||
- emperor can now spawn other emperors (sub-emperors)
|
||||
- fixed idle mode in single-process
|
||||
- fixed solaris iovec
|
||||
|
||||
*** may 2011 ***
|
||||
|
||||
* 0.9.8-rc3 [20110530]
|
||||
|
||||
- snapshotting support
|
||||
- fixed python 3.x spooler
|
||||
- improvements for grunt processes
|
||||
- better abstract unix socket
|
||||
- --log-socket allows logging to generic DGRAM sockets
|
||||
- a bunch of solaris fixes
|
||||
- new option --no-fd-passing for fastrouter
|
||||
- --fastrouter-subscription-slot to set the number of slot in subscription server
|
||||
- unlimited shared sockets
|
||||
- fixed netlink compilation
|
||||
- auto-reconnect on emperor+amqp server disconnection
|
||||
- various emperor fixes
|
||||
- unlimited fastrouter sockets
|
||||
- better cgroup support
|
||||
- --add-header option allow adding of custom HTTP response headers
|
||||
- cheap and idle operational modes
|
||||
|
||||
|
||||
* 0.9.8-rc2 [20110521]
|
||||
|
||||
- new option --die-on-term
|
||||
- fixed touch reload
|
||||
- a couple of optimizations for wsgi.input
|
||||
- systemd integration
|
||||
|
||||
* 0.9.8-rc1 [20110514]
|
||||
|
||||
- massive code cleanup and refactoring
|
||||
- added vassals loyalty concept
|
||||
- fixed virtualhosting with dynamic virtualenv
|
||||
- fixed reloading on grand-central-dispatch-enabled OSX
|
||||
- improved PSGI support with uGreen and async support
|
||||
- improved Rack support with complete fiber+async in ruby 1.9
|
||||
- support for JSON config files
|
||||
- native multi-protocol support (added fastcgi and http)
|
||||
- Mongrel2 support
|
||||
- support for templates in vassals
|
||||
- various threading fixes
|
||||
- gcc-4.6 support
|
||||
- support for logging via zeromq
|
||||
- support for configuration passed via pipe/stdin
|
||||
- pythonpath entries are now unlimited
|
||||
- socket entries are unlimited
|
||||
- pythonpath can be a glob
|
||||
- lazy mode added
|
||||
- new language-independent profiling subsystem
|
||||
- support for configuration stored in a sqlite3 db
|
||||
- allow workers to survive to syslogd death (when --log-syslog is used)
|
||||
- fix traceback in Python 3.x
|
||||
- support for uwsgi signals in threads
|
||||
- plugin autoloading
|
||||
- graceful reloading for threads
|
||||
- new wsgi.input object
|
||||
- support for alternative allocators (tcmalloc and jemalloc)
|
||||
|
||||
|
||||
*** april 2011 ***
|
||||
|
||||
* 0.9.7.2 [20110406]
|
||||
|
||||
- new option --touch-reload <file> to reload the stack on <file> modification
|
||||
--static-map <mountpoint=documentroot> allows to serve static files
|
||||
- fixed --post-limit management
|
||||
- disallow empty socket names
|
||||
- implemented exception_info WSGI support
|
||||
- new options --reload-on-as <n> and --reload-on-rss <n> allows
|
||||
to recycle workers when their memory usage is higher than <n> MB
|
||||
- fixed syslog support (use --log-syslog[=facility] to enable it)
|
||||
- improved plugin loading system
|
||||
- added support for RabbitMQ as event dispatcher for the Emperor
|
||||
- fixed FreeBSD memory report
|
||||
- PSGI plugin can be compiled without ithreads
|
||||
- various Emperor fixes
|
||||
- fixed a regression with setgroups()
|
||||
- support for shared sockets (used in jails within network namespaces)
|
||||
|
||||
*** march 2011 ***
|
||||
|
||||
* 0.9.7.1 [20110326]
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.4 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.5 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.6 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python2.7 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.0 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.1 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python3.2 uwsgiconfig.py --build
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
python uwsgiconfig.py --build pylua
|
||||
+113
-54
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -51,7 +51,6 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define MAX_VARS 64
|
||||
#define DEFAULT_SOCK "/tmp/uwsgi.sock"
|
||||
|
||||
typedef struct {
|
||||
@@ -73,6 +72,8 @@ typedef struct {
|
||||
char script_name[256];
|
||||
char scheme[9];
|
||||
int cgi_mode ;
|
||||
int max_vars;
|
||||
int empty_remote_user;
|
||||
} uwsgi_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
@@ -83,8 +84,18 @@ static uint16_t uwsgi_swap16(uint16_t x) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static int uwsgi_add_var(struct iovec *vec, int i, char *key, char *value, uint16_t *pkt_size) {
|
||||
static int uwsgi_add_var(struct iovec *vec, int i, request_rec *r, char *key, char *value, uint16_t *pkt_size) {
|
||||
|
||||
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
if (i+6 > c->max_vars) {
|
||||
#else
|
||||
if (i+4 > c->max_vars) {
|
||||
#endif
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: max number of uwsgi variables reached. consider increasing it with uWSGImaxVars directive");
|
||||
return i;
|
||||
}
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
char *ptr;
|
||||
@@ -150,6 +161,9 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
|
||||
c->modifier1 = 0 ;
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->script_name[0] = 0;
|
||||
c->empty_remote_user = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -164,6 +178,14 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
|
||||
c->modifier1 = 0 ;
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->empty_remote_user = 1;
|
||||
c->script_name[0] = 0;
|
||||
if (dir) {
|
||||
if (strcmp(dir, "/")) {
|
||||
strncpy(c->script_name, dir, 255);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -243,11 +265,8 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
uwsgi_cfg *c = ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
struct iovec uwsgi_vars[(MAX_VARS*6)+1] ;
|
||||
#else
|
||||
struct iovec uwsgi_vars[(MAX_VARS*4)+1] ;
|
||||
#endif
|
||||
struct iovec *uwsgi_vars;
|
||||
|
||||
int vecptr = 1 ;
|
||||
char pkt_header[4];
|
||||
uint16_t pkt_size = 0;
|
||||
@@ -315,68 +334,58 @@ static int uwsgi_handler(request_rec *r) {
|
||||
}
|
||||
|
||||
|
||||
#if APR_IS_BIGENDIAN
|
||||
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*6)+1);
|
||||
#else
|
||||
uwsgi_vars = malloc(sizeof(struct iovec) * (c->max_vars*4)+1);
|
||||
#endif
|
||||
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_METHOD", (char *) r->method, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "QUERY_STRING", r->args ? r->args : "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_NAME", (char *) ap_get_server_name(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
|
||||
//
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
|
||||
else if (c->empty_remote_user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
|
||||
}
|
||||
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "DOCUMENT_ROOT", (char *) ap_document_root(r), &pkt_size) ;
|
||||
|
||||
if (c->scheme[0] != 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
}
|
||||
|
||||
if (c->script_name[0] == '/') {
|
||||
if (c->script_name[1] == 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", c->script_name, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
|
||||
}
|
||||
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
|
||||
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
if (r->path_info) {
|
||||
if (strlen(r->path_info) <= 0) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->path_info, &pkt_size) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
|
||||
|
||||
headers = apr_table_elts(r->headers_in);
|
||||
h = (apr_table_entry_t *) headers->elts;
|
||||
|
||||
// check for max vars (a bit ugly)
|
||||
cnt = headers->nelts ;
|
||||
if (cnt + 11 > MAX_VARS) {
|
||||
cnt = MAX_VARS -11;
|
||||
}
|
||||
|
||||
for(i=0;i< cnt;i++) {
|
||||
for(i=0;i< headers->nelts;i++) {
|
||||
if (h[i].key){
|
||||
if (!strcasecmp(h[i].key, "Content-Type")) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_TYPE", h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_TYPE", h[i].val, &pkt_size) ;
|
||||
}
|
||||
else if (!strcasecmp(h[i].key, "Content-Length")) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "CONTENT_LENGTH", h[i].val, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
penv = apr_pstrcat(r->pool, "HTTP_", h[i].key, NULL);
|
||||
@@ -388,7 +397,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
*cp = toupper(*cp);
|
||||
}
|
||||
}
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, penv, h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, penv, h[i].val, &pkt_size) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,7 +406,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
headers = apr_table_elts(r->subprocess_env);
|
||||
h = (apr_table_entry_t*) headers->elts;
|
||||
for (i = 0; i < headers->nelts; ++i) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, h[i].key, h[i].val, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, h[i].key, h[i].val, &pkt_size) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -418,11 +427,13 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() %s", strerror(errno));
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt != pkt_size+4) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: writev() returned wrong size");
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
@@ -434,6 +445,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: read() client block failed !");
|
||||
close(uwsgi_poll.fd);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -458,6 +470,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (cnt == 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
@@ -467,6 +480,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (errno != ECONNRESET) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else {
|
||||
@@ -489,6 +503,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
if (r->connection->aborted) {
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
apr_brigade_write(bb, NULL, NULL, buf, cnt);
|
||||
@@ -508,6 +523,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -521,6 +537,7 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
if (!c->cgi_mode) {
|
||||
if (uwsgi_http_status_read == 0) {
|
||||
free(uwsgi_vars);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -528,11 +545,13 @@ static int uwsgi_handler(request_rec *r) {
|
||||
|
||||
if (hret = ap_scan_script_header_err_brigade(r, bb, NULL)) {
|
||||
apr_brigade_destroy(bb);
|
||||
free(uwsgi_vars);
|
||||
return hret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(uwsgi_vars);
|
||||
return ap_pass_brigade(r->output_filters, bb) ;
|
||||
}
|
||||
|
||||
@@ -564,6 +583,22 @@ static const char * cmd_uwsgi_force_wsgi_scheme(cmd_parms *cmd, void *cfg, const
|
||||
|
||||
}
|
||||
|
||||
static const char *cmd_uwsgi_max_vars(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
uwsgi_cfg *c ;
|
||||
int val ;
|
||||
|
||||
if (cfg) {
|
||||
c = cfg ;
|
||||
}
|
||||
else {
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
c->max_vars = atoi(value);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_modifier1(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
|
||||
uwsgi_cfg *c ;
|
||||
@@ -598,7 +633,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
|
||||
c->cgi_mode = 1 ;
|
||||
}
|
||||
|
||||
@@ -699,6 +734,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
|
||||
uwsgi_cfg *c ;
|
||||
|
||||
if (cfg) {
|
||||
c = cfg ;
|
||||
}
|
||||
else {
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
|
||||
c->empty_remote_user = 1;
|
||||
}
|
||||
else {
|
||||
c->empty_remote_user = 0;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
|
||||
}
|
||||
|
||||
static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
|
||||
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
|
||||
@@ -707,6 +764,8 @@ static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
|
||||
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
|
||||
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
|
||||
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
|
||||
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct wsgi_request *find_wsgi_req_proto_by_fd(int fd) {
|
||||
return uwsgi.async_proto_fd_table[fd];
|
||||
}
|
||||
|
||||
struct wsgi_request *find_wsgi_req_by_fd(int fd) {
|
||||
return uwsgi.async_waiting_fd_table[fd];
|
||||
}
|
||||
@@ -195,14 +199,23 @@ void *async_loop(void *arg1) {
|
||||
int interesting_fd, i;
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
int timeout;
|
||||
int is_a_new_connection;
|
||||
int proto_parser_status;
|
||||
|
||||
time_t now, last_now = 0;
|
||||
|
||||
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
|
||||
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
uwsgi.async_runqueue_cnt = 0;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
}
|
||||
|
||||
// set a default request manager
|
||||
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
@@ -235,49 +248,105 @@ void *async_loop(void *arg1) {
|
||||
async_expire_timeouts();
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<uwsgi.async_nevents;i++) {
|
||||
// manage events
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
// new request coming in
|
||||
if (interesting_fd == uwsgi.sockets[0].fd) {
|
||||
uwsgi.wsgi_req = find_first_available_wsgi_req();
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
continue;
|
||||
}
|
||||
is_a_new_connection = 0;
|
||||
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id );
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
// new request coming in ?
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
|
||||
if (interesting_fd == uwsgi_sock->fd) {
|
||||
|
||||
is_a_new_connection = 1;
|
||||
|
||||
uwsgi.wsgi_req = find_first_available_wsgi_req();
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
now = time(NULL);
|
||||
if (now > last_now) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
last_now = now;
|
||||
}
|
||||
break;;
|
||||
}
|
||||
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
|
||||
#endif
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
|
||||
#endif
|
||||
|
||||
// on linux we do not need to reset the socket to blocking state
|
||||
#ifndef __linux__
|
||||
if (uwsgi.numproc > 1) {
|
||||
/* re-set blocking socket */
|
||||
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi.sockets[0].arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
continue;
|
||||
if (uwsgi.numproc > 1) {
|
||||
/* re-set blocking socket */
|
||||
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, uwsgi_sock->arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wsgi_req_simple_recv(uwsgi.wsgi_req)) {
|
||||
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (!is_a_new_connection) {
|
||||
// proto event
|
||||
uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
|
||||
if (uwsgi.wsgi_req) {
|
||||
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
|
||||
// reset timeout
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
#ifndef UWSGI_EVENT_USE_PORT
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
#endif
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
// put request in the runqueue
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
continue;
|
||||
}
|
||||
else if (proto_parser_status == -1) {
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
continue;
|
||||
}
|
||||
// re-add timer
|
||||
async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// put request in the runqueue
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
}
|
||||
else {
|
||||
// app event
|
||||
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
|
||||
// unknown fd, remove it (for safety)
|
||||
@@ -324,7 +393,7 @@ void *async_loop(void *arg1) {
|
||||
|
||||
next_async_request = current_request->next;
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status == UWSGI_OK) {
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
// remove all the monitored fds and timeout
|
||||
while(uwsgi.wsgi_req->waiting_fds) {
|
||||
#ifndef UWSGI_EVENT_USE_PORT
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import struct
|
||||
import sys
|
||||
import os
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
print("i am the bootstrap for uwsgi.SymbolsImporter")
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
|
||||
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("pygments_zip"))
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("django_zip:djenv/lib/python2.6/site-packages"))
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsZipImporter("djapp_zip"))
|
||||
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
sys.meta_path.insert(0, uwsgi.ZipImporter("data://0"))
|
||||
@@ -0,0 +1,3 @@
|
||||
import uwsgi
|
||||
|
||||
print uwsgi.extract("data://0")
|
||||
@@ -0,0 +1 @@
|
||||
object file for embedded files will be put here
|
||||
+18
-3
@@ -1,7 +1,10 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
sctp = false
|
||||
spooler = true
|
||||
@@ -12,22 +15,34 @@ threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embed_files = bootstrap3.py,django.zip,djapp.zip
|
||||
@@ -0,0 +1,4 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
|
||||
embed_files = embedme.py,uwsgidecorators.py
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = libuwsgi.so
|
||||
embedded_plugins = null
|
||||
as_shared_library = true
|
||||
+4
-32
@@ -1,33 +1,5 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
snmp = true
|
||||
sctp = false
|
||||
erlang = false
|
||||
spooler = false
|
||||
embedded = false
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
nagios = true
|
||||
proxy = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ugreen = false
|
||||
http = true
|
||||
evdis = false
|
||||
ldap = true
|
||||
routing = false
|
||||
stackless = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
plugins = python, ping, rack
|
||||
bin_name = uwsgi
|
||||
plugin_dir = .
|
||||
embedded_plugins =
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
inherit = default
|
||||
plugins = python, ping, rack, psgi, cache, http, fastrouter
|
||||
plugin_dir = plugins
|
||||
embedded_plugins = null
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = +,lua
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = libuwsgi.so
|
||||
embedded_plugins = symcall
|
||||
as_shared_library = true
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = pyuwsgi.so
|
||||
embedded_plugins = pyuwsgi,python,ping,cache,nagios,rpc,ugreen
|
||||
as_shared_library = true
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = rack, ping, nagios, rpc
|
||||
embedded_plugins = rack, ping, cache, nagios, rpc, fastrouter, http, ugreen
|
||||
|
||||
+13
-1
@@ -2,6 +2,9 @@
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
spooler = true
|
||||
@@ -10,14 +13,23 @@ udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
nagios = false
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = true
|
||||
pcre = false
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
plugins =
|
||||
bin_name = /opt/unbit/bin/uwsgi
|
||||
append_version = unbit
|
||||
plugin_dir = /opt/unbit/uwsgi_plugins
|
||||
embedded_plugins =
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
json = false
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_plugins
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
ini = true
|
||||
yaml = false
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
spooler = true
|
||||
embedded = true
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins =
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
@@ -2,145 +2,91 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint64_t ovl;
|
||||
struct uwsgi_subscriber *usub;
|
||||
struct uwsgi_subscriber_name *ret = NULL;
|
||||
|
||||
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
|
||||
|
||||
if (usub == NULL || !ovl) return NULL;
|
||||
|
||||
if (!usub->nodes) return NULL;
|
||||
|
||||
if (usub && ovl) {
|
||||
ret = &usub->names[usub->current];
|
||||
// dead node
|
||||
if (ret->len == 0) {
|
||||
if (usub->current == usub->nodes-1) {
|
||||
usub->nodes--;
|
||||
}
|
||||
// retry with another node (if available)
|
||||
if (usub->nodes > 0) {
|
||||
usub->current++;
|
||||
if (usub->current >= usub->nodes) usub->current = 0;
|
||||
return uwsgi_get_subscriber(udict, key, keylen);
|
||||
}
|
||||
}
|
||||
|
||||
if (usub->nodes > 1) {
|
||||
usub->current++;
|
||||
if (usub->current >= usub->nodes) usub->current = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_add_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *address, uint64_t address_len) {
|
||||
|
||||
char *ptr;
|
||||
uint64_t vallen = 0;
|
||||
struct uwsgi_subscriber *usub, nusub;
|
||||
int found = 0;
|
||||
int i;
|
||||
|
||||
ptr = uwsgi_dict_get(udict, key, keylen, &vallen);
|
||||
if (ptr && vallen) {
|
||||
usub = (struct uwsgi_subscriber *) ptr;
|
||||
for(i=0;i<(int)usub->nodes;i++) {
|
||||
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, address, address_len)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
found = usub->nodes;
|
||||
// check for unallocated slot
|
||||
for(i=0;i<(int)usub->nodes;i++) {
|
||||
if (usub->names[i].len == 0) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
usub->names[found].len = address_len;
|
||||
memcpy(usub->names[found].name, address, address_len);
|
||||
if (found == (int) usub->nodes) {
|
||||
usub->nodes++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
nusub.nodes = 1;
|
||||
nusub.current = 0;
|
||||
memcpy(nusub.names[0].name, address, address_len);
|
||||
uwsgi_dict_set(udict, key, keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
|
||||
|
||||
void uwsgi_init_cache() {
|
||||
int i;
|
||||
|
||||
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
if (!uwsgi.cache_blocksize)
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
if (!blocksize) blocksize = 4096;
|
||||
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uwsgi.cache_hashtable) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (blocksize % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
memset(uwsgi.cache_hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
|
||||
udict->blocksize = blocksize;
|
||||
udict->max_items = items;
|
||||
uwsgi.cache_unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uwsgi.cache_unused_stack) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->hashtable) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
memset(uwsgi.cache_unused_stack, 0, sizeof(uint64_t) * uwsgi.cache_max_items);
|
||||
|
||||
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
// the first cache item is always zero
|
||||
uwsgi.shared->cache_first_available_item = 1;
|
||||
uwsgi.shared->cache_unused_stack_ptr = 0;
|
||||
|
||||
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->unused_stack) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
//uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (uwsgi.cache_store) {
|
||||
uwsgi.cache_filesize = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
|
||||
int cache_fd;
|
||||
struct stat cst;
|
||||
|
||||
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
|
||||
if (stat(uwsgi.cache_store, &cst)) {
|
||||
uwsgi_log("creating a new cache store file: %s\n", uwsgi.cache_store);
|
||||
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (cache_fd >= 0) {
|
||||
// fill the caching store
|
||||
if (ftruncate(cache_fd, uwsgi.cache_filesize)) {
|
||||
uwsgi_log("ftruncate()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((size_t) cst.st_size != uwsgi.cache_filesize || !S_ISREG(cst.st_mode)) {
|
||||
uwsgi_log("invalid cache store file. Please remove it or fix cache blocksize/items to match its size\n");
|
||||
exit(1);
|
||||
}
|
||||
cache_fd = open(uwsgi.cache_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
uwsgi_log("recovered cache from backing store file: %s\n", uwsgi.cache_store);
|
||||
}
|
||||
|
||||
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->items) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
if (cache_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.cache_store);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
|
||||
uwsgi_cache_fix();
|
||||
|
||||
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->data) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
|
||||
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
|
||||
}
|
||||
}
|
||||
if (!uwsgi.cache_items) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0;i< (int) udict->max_items;i++) {
|
||||
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
|
||||
}
|
||||
/*
|
||||
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uwsgi.cache) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
udict->first_available_item = 1;
|
||||
udict->unused_stack_ptr = 0;
|
||||
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
|
||||
|
||||
udict->lock = uwsgi_mmap_shared_lock();
|
||||
uwsgi_lock_init(udict->lock);
|
||||
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
|
||||
|
||||
return udict;
|
||||
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
|
||||
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
|
||||
}
|
||||
|
||||
uint32_t djb33x_hash(char *key, int keylen) {
|
||||
@@ -156,89 +102,6 @@ uint32_t djb33x_hash(char *key, int keylen) {
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = djb33x_hash(key, keylen);
|
||||
|
||||
int hash_key = hash % 0xffff;
|
||||
|
||||
uint64_t slot = udict->hashtable[hash_key];
|
||||
|
||||
struct uwsgi_dict_item *udi;
|
||||
|
||||
udi = &udict->items[slot];
|
||||
|
||||
// first round
|
||||
if (udi->djbhash != hash) goto cycle;
|
||||
if (udi->keysize != keylen) goto cycle;
|
||||
if (memcmp(udi->key, key, keylen)) goto cycle;
|
||||
|
||||
return slot;
|
||||
|
||||
cycle:
|
||||
while(udi->next) {
|
||||
slot = udi->next;
|
||||
udi = &udict->items[slot];
|
||||
if (udi->djbhash != hash) continue;
|
||||
if (udi->keysize != keylen) continue;
|
||||
if (!memcmp(udi->key, key, keylen)) return slot;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
|
||||
|
||||
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
|
||||
if (index) {
|
||||
*valsize = udict->items[index].valsize;
|
||||
udict->items[index].hits++;
|
||||
return udict->data+(index*udict->blocksize);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint64_t index = 0;
|
||||
struct uwsgi_dict_item *udi;
|
||||
int ret = -1;
|
||||
|
||||
index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
if (index) {
|
||||
udi = &udict->items[index] ;
|
||||
udi->keysize = 0;
|
||||
udi->valsize = 0;
|
||||
udict->unused_stack_ptr++;
|
||||
udict->unused_stack[udict->unused_stack_ptr] = index;
|
||||
// try to return to initial condition...
|
||||
if (index == udict->first_available_item-1) {
|
||||
udict->first_available_item--;
|
||||
}
|
||||
ret = 0;
|
||||
// relink collisioned entry
|
||||
if (udi->prev) {
|
||||
udict->items[udi->prev].next = udi->next;
|
||||
}
|
||||
if (udi->next) {
|
||||
udict->items[udi->next].prev = udi->prev;
|
||||
}
|
||||
if (!udi->prev && !udi->next) {
|
||||
// reset hashtable entry
|
||||
udict->hashtable[udi->djbhash % 0xffff] = 0;
|
||||
}
|
||||
udi->djbhash = 0;
|
||||
udi->prev = 0;
|
||||
udi->next = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = djb33x_hash(key, keylen);
|
||||
@@ -416,173 +279,140 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
uci->prev = last_index;
|
||||
}
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = &uwsgi.cache_items[index] ;
|
||||
if (expires) {
|
||||
expires += time(NULL);
|
||||
uci->expires = expires;
|
||||
}
|
||||
memcpy(uwsgi.cache+(index*uwsgi.cache_blocksize), val, vallen);
|
||||
uci->valsize = vallen;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
|
||||
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
|
||||
|
||||
uint64_t index = 0, last_index = 0 ;
|
||||
void *cache_thread_loop(void *fd_ptr) {
|
||||
|
||||
struct uwsgi_dict_item *udi, *udii;
|
||||
int *fd_tmp = (int *) fd_ptr;
|
||||
int fd = *fd_tmp;
|
||||
int i;
|
||||
ssize_t len;
|
||||
char uwsgi_packet[UMAX16+4];
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi_packet;
|
||||
char *val;
|
||||
uint64_t vallen;
|
||||
char *key;
|
||||
uint16_t keylen;
|
||||
struct pollfd ctl_poll;
|
||||
char *watermark;
|
||||
struct sockaddr_un ctl_sun;
|
||||
socklen_t ctl_sun_len;
|
||||
|
||||
int ret = -1;
|
||||
int slot;
|
||||
ctl_poll.events = POLLIN;
|
||||
|
||||
if (!keylen || !vallen) return -1;
|
||||
for(;;) {
|
||||
ctl_sun_len = sizeof(struct sockaddr_un);
|
||||
pthread_mutex_lock(&uwsgi.cache_server_lock);
|
||||
|
||||
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
|
||||
ctl_poll.fd = accept(fd, (struct sockaddr *) &ctl_sun, &ctl_sun_len);
|
||||
|
||||
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
|
||||
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
|
||||
goto end;
|
||||
}
|
||||
pthread_mutex_unlock(&uwsgi.cache_server_lock);
|
||||
|
||||
index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
if (!index) {
|
||||
if (udict->unused_stack_ptr) {
|
||||
index = udict->unused_stack[udict->unused_stack_ptr];
|
||||
udict->unused_stack_ptr--;
|
||||
}
|
||||
else {
|
||||
index = udict->first_available_item;
|
||||
if (udict->first_available_item < udict->max_items) {
|
||||
udict->first_available_item++;
|
||||
}
|
||||
}
|
||||
udi = &udict->items[index] ;
|
||||
udi->djbhash = djb33x_hash(key, keylen);
|
||||
udi->hits = 0;
|
||||
memcpy(udi->key, key, keylen);
|
||||
memcpy(udict->data+(index*udict->blocksize), val, vallen);
|
||||
|
||||
// set this as late as possibile (to reduce races risk)
|
||||
|
||||
udi->valsize = vallen;
|
||||
udi->keysize = keylen;
|
||||
ret = 0;
|
||||
// now put the value in the 16bit hashtable
|
||||
slot = udi->djbhash % 0xffff;
|
||||
|
||||
if (udict->hashtable[slot] == 0) {
|
||||
udict->hashtable[slot] = index;
|
||||
}
|
||||
else {
|
||||
// append to first available next
|
||||
last_index = udict->hashtable[slot];
|
||||
udii = &udict->items[ last_index ];
|
||||
while(udii->next) {
|
||||
last_index = udii->next;
|
||||
udii = &udict->items[ last_index ];
|
||||
}
|
||||
udii->next = index;
|
||||
udi->prev = last_index;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
|
||||
uint64_t tmp_vallen = 0;
|
||||
|
||||
if (vallen > 0) {
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && tmp_vallen > 0) {
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
|
||||
}
|
||||
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && vallen > 0) {
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen);
|
||||
if (ctl_poll.fd < 0) {
|
||||
uwsgi_error("cache accept()");
|
||||
continue;
|
||||
}
|
||||
i = 0;
|
||||
while(i < 4) {
|
||||
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("cache poll()");
|
||||
goto clear;
|
||||
}
|
||||
else {
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
|
||||
len = read(ctl_poll.fd, uwsgi_packet+i, 4-i);
|
||||
if (len < 0) {
|
||||
uwsgi_error("cache read()");
|
||||
goto clear;
|
||||
}
|
||||
i+=len;
|
||||
}
|
||||
|
||||
if (uh->pktsize == 0) goto clear;
|
||||
|
||||
while(i < 4+uh->pktsize) {
|
||||
len = poll(&ctl_poll, 1, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("cache poll()");
|
||||
goto clear;
|
||||
}
|
||||
len = read(ctl_poll.fd, uwsgi_packet+i, (4+uh->pktsize)-i);
|
||||
if (len < 0) {
|
||||
uwsgi_error("cache read()");
|
||||
goto clear;
|
||||
}
|
||||
i+=len;
|
||||
}
|
||||
|
||||
watermark = uwsgi_packet+4+uh->pktsize;
|
||||
|
||||
// get first parameter
|
||||
memcpy(&keylen, uwsgi_packet+4, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keylen = uwsgi_swap16(keylen);
|
||||
#endif
|
||||
if (uwsgi_packet+6+keylen > watermark) goto clear;
|
||||
key = uwsgi_packet+6+keylen+2;
|
||||
memcpy(&keylen, key-2, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keylen = uwsgi_swap16(keylen);
|
||||
#endif
|
||||
|
||||
if (key+keylen > watermark) goto clear;
|
||||
|
||||
val = uwsgi_cache_get(key, keylen, &vallen);
|
||||
if (val && vallen > 0) {
|
||||
if (write(ctl_poll.fd, val, vallen) < 0) {
|
||||
uwsgi_error("cache write()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint64_t vallen = 0;
|
||||
char *value;
|
||||
char *argv[3];
|
||||
uint8_t argc = 0;
|
||||
|
||||
switch(wsgi_req->uh.modifier2) {
|
||||
case 0:
|
||||
// get
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = vallen;
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// set
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
argc = 3;
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
|
||||
if (argc > 1) {
|
||||
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// del
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// dict
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// get (uwsgi + stream)
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += write(wsgi_req->poll.fd, value, vallen);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 0;
|
||||
wsgi_req->response_size = write(wsgi_req->poll.fd, &wsgi_req->uh, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
clear:
|
||||
close(ctl_poll.fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin uwsgi_cache_plugin = {
|
||||
int uwsgi_cache_server(char *socket, int threads) {
|
||||
|
||||
.name = "cache",
|
||||
.modifier1 = 111,
|
||||
.request = uwsgi_cache_request,
|
||||
int *fd = uwsgi_malloc(sizeof(int));
|
||||
|
||||
int i;
|
||||
pthread_t thread_id;
|
||||
char *tcp_port = strchr(socket, ':');
|
||||
if (tcp_port) {
|
||||
*fd = bind_to_tcp(socket, uwsgi.listen_queue, tcp_port);
|
||||
}
|
||||
else {
|
||||
*fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
};
|
||||
pthread_mutex_init(&uwsgi.cache_server_lock, NULL);
|
||||
|
||||
if (threads < 1) threads = 1;
|
||||
|
||||
uwsgi_log("*** cache-optimized server enabled on fd %d (%d threads) ***\n", *fd, threads);
|
||||
|
||||
for(i=0;i<threads;i++) {
|
||||
pthread_create(&thread_id, NULL, cache_thread_loop, (void *) fd);
|
||||
}
|
||||
|
||||
return *fd;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
|
||||
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
|
||||
|
||||
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
|
||||
|
||||
}
|
||||
|
||||
void cluster_setup() {
|
||||
|
||||
int rlen;
|
||||
// get cluster configuration
|
||||
if (uwsgi.cluster != NULL) {
|
||||
// get multicast socket
|
||||
|
||||
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
|
||||
|
||||
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
|
||||
|
||||
// ask for cluster options only if bot pre-existent options are set
|
||||
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
|
||||
// now wait max 60 seconds and resend multicast request every 10 seconds
|
||||
for (;;) {
|
||||
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
|
||||
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
|
||||
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
|
||||
continue;
|
||||
}
|
||||
waitfd:
|
||||
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure(-1);
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
goto waitfd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
options_parsed:
|
||||
|
||||
if (!uwsgi.cluster_nodes)
|
||||
uwsgi_cluster_add_me();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
char *tcp_port;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding node\n");
|
||||
#endif
|
||||
|
||||
tcp_port = strchr(nucn->name, ':');
|
||||
#ifndef UWSGI_ZEROMQ
|
||||
if (tcp_port == NULL) {
|
||||
#else
|
||||
char *zmq_dash = strchr(nucn->name, '-');
|
||||
if (tcp_port == NULL && zmq_dash == NULL) {
|
||||
#endif
|
||||
|
||||
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// first check for already present node
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0) {
|
||||
if (!strcmp(ucn->name, nucn->name)) {
|
||||
ucn->status = UWSGI_NODE_OK;
|
||||
ucn->last_seen = time(NULL);
|
||||
// update requests
|
||||
ucn->requests = nucn->requests;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
|
||||
if (ucn->name[0] == 0) {
|
||||
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
|
||||
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
|
||||
ucn->workers = nucn->workers;
|
||||
ucn->ucn_addr.sin_family = AF_INET;
|
||||
if (tcp_port) {
|
||||
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
|
||||
tcp_port[0] = 0;
|
||||
}
|
||||
if (nucn->name[0] == 0) {
|
||||
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", nucn->name);
|
||||
#endif
|
||||
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
|
||||
}
|
||||
|
||||
ucn->type = type;
|
||||
// here memory can be freed, as it is allocated by uwsgi_concat2n
|
||||
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
|
||||
tcp_port[0] = ':';
|
||||
}
|
||||
ucn->last_seen = time(NULL);
|
||||
ucn->requests = nucn->requests;
|
||||
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("unable to add node %s\n", nucn->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_cluster_add_me() {
|
||||
|
||||
const char *key1 = "hostname";
|
||||
const char *key2 = "address";
|
||||
const char *key3 = "workers";
|
||||
const char *key4 = "requests";
|
||||
|
||||
char *ptrbuf;
|
||||
uint16_t ustrlen;
|
||||
char numproc[6];
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
char uuid_zmq_str[37];
|
||||
uuid_t uuid_zmq;
|
||||
if (!uwsgi.sockets && !uwsgi.zeromq) {
|
||||
#else
|
||||
if (!uwsgi.sockets) {
|
||||
#endif
|
||||
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(numproc, 6, "%d", uwsgi.numproc);
|
||||
|
||||
size_t len;
|
||||
|
||||
if (uwsgi.sockets) {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uuid_zmq_str);
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
char *buf = uwsgi_malloc(len);
|
||||
|
||||
ptrbuf = buf;
|
||||
|
||||
ustrlen = strlen(key1);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key1, strlen(key1));
|
||||
ptrbuf += strlen(key1);
|
||||
|
||||
ustrlen = strlen(uwsgi.hostname);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
ptrbuf += strlen(uwsgi.hostname);
|
||||
|
||||
|
||||
if (uwsgi.sockets && uwsgi.sockets->name) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uwsgi.sockets->name);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
|
||||
ptrbuf += strlen(uwsgi.sockets->name);
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uuid_zmq_str);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
|
||||
ptrbuf += strlen(uuid_zmq_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ustrlen = strlen(key3);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key3, strlen(key3));
|
||||
ptrbuf += strlen(key3);
|
||||
|
||||
ustrlen = strlen(numproc);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, numproc, strlen(numproc));
|
||||
ptrbuf += strlen(numproc);
|
||||
|
||||
ustrlen = strlen(key4);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key4, strlen(key4));
|
||||
ptrbuf += strlen(key4);
|
||||
|
||||
ustrlen = 1;
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, "0", 1);
|
||||
ptrbuf += 1;
|
||||
|
||||
|
||||
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
|
||||
|
||||
free(buf);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("add_me() successfull\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cluster_join(char *name) {
|
||||
|
||||
int fd;
|
||||
char *cp;
|
||||
int broadcast = 0;
|
||||
|
||||
|
||||
|
||||
if (name[0] == ':') {
|
||||
fd = bind_to_udp(name, 0, 1);
|
||||
broadcast = 1;
|
||||
}
|
||||
else {
|
||||
fd = bind_to_udp(name, 1, 0);
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
cp = strchr(name, ':');
|
||||
cp[0] = 0;
|
||||
uwsgi.mc_cluster_addr.sin_family = AF_INET;
|
||||
if (broadcast) {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
|
||||
}
|
||||
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
|
||||
cp[0] = ':';
|
||||
|
||||
|
||||
// announce my presence to all the nodes
|
||||
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_cluster_best_node() {
|
||||
|
||||
int i;
|
||||
int best_node = -1;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
|
||||
if (best_node == -1) {
|
||||
best_node = i;
|
||||
}
|
||||
else {
|
||||
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
|
||||
best_node = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_node == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
|
||||
return uwsgi.shared->nodes[best_node].name;
|
||||
}
|
||||
|
||||
|
||||
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
char *tmpstr;
|
||||
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
#endif
|
||||
|
||||
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
|
||||
strncpy(ucn->nodename, val, UMIN(vallen, 255));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("address", 7, key, keylen)) {
|
||||
strncpy(ucn->name, val, UMIN(vallen, 100));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->workers = atoi(tmpstr);
|
||||
free(tmpstr);
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->requests = strtoul(tmpstr, NULL, 0);
|
||||
free(tmpstr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
require 'stringio'
|
||||
|
||||
hello = proc do |signum|
|
||||
puts "Hello i am signal #{signum}"
|
||||
end
|
||||
|
||||
file_changed = proc do |signum|
|
||||
puts "/tmp has been modified"
|
||||
end
|
||||
|
||||
UWSGI.register_signal(17, '', hello)
|
||||
UWSGI.register_signal(30, '', file_changed)
|
||||
|
||||
UWSGI.add_rb_timer(17 , 2)
|
||||
UWSGI.add_timer(17 , 1)
|
||||
UWSGI.add_file_monitor(30 , '/tmp')
|
||||
|
||||
puts UWSGI.signal_registered(1)
|
||||
puts UWSGI.signal_registered(17)
|
||||
|
||||
run lambda { |env|
|
||||
puts env.inspect
|
||||
UWSGI.signal(17)
|
||||
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World!\n")]
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
require 'stringio'
|
||||
require 'uwsgidsl'
|
||||
|
||||
|
||||
|
||||
signal 17,'mule5' do |signum|
|
||||
end
|
||||
|
||||
puts UWSGI::VERSION
|
||||
puts UWSGI::NUMPROC
|
||||
puts UWSGI::HOSTNAME
|
||||
|
||||
puts UWSGI::OPT.inspect
|
||||
|
||||
timer 2 do |signum|
|
||||
puts "ciao sono un dsl ruby: #{signum} #{UWSGI::OPT.inspect}"
|
||||
end
|
||||
|
||||
timer 1,'mule1' do |signum|
|
||||
puts "1 second elapsed (signum #{signum})"
|
||||
end
|
||||
|
||||
filemon '/tmp' do |signum|
|
||||
puts "/tmp has been modified"
|
||||
end
|
||||
|
||||
cron 5,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
cron 58,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
postfork do
|
||||
puts "fork() called"
|
||||
end
|
||||
|
||||
rpc 'pippo' do
|
||||
"i am an rpc function"
|
||||
end
|
||||
|
||||
rpc 'pluto' do |x,y|
|
||||
"i am another rpc function #{x} #{y}"
|
||||
end
|
||||
|
||||
begin
|
||||
foo_func
|
||||
rescue
|
||||
end
|
||||
|
||||
puts UWSGI.cache_exists('nilkey')
|
||||
puts UWSGI.cache_exists?('nilkey')
|
||||
|
||||
UWSGI.cache_set!('foobar_key?a=1', UWSGI::OPT.inspect)
|
||||
begin
|
||||
puts UWSGI.cache_get(nil)
|
||||
rescue
|
||||
end
|
||||
puts UWSGI.cache_get('foobar_key?a=1')
|
||||
|
||||
|
||||
run lambda { |env|
|
||||
puts env.inspect
|
||||
UWSGI.setprocname("i am the uWSGI rack plugin")
|
||||
UWSGI.signal(17)
|
||||
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World! #{UWSGI.mem.inspect}\n")]
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
# uwsgi - Use uwsgi to run python and wsgi web apps.
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
# description: Use uwsgi to run python and wsgi web apps.
|
||||
# processname: uwsgi
|
||||
|
||||
# author: Roman Vasilyev
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
PATH=/opt/uwsgi:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
prog=/usr/sbin/uwsgi
|
||||
|
||||
OWNER=nginx
|
||||
|
||||
NAME=uwsgi
|
||||
DESC=uwsgi
|
||||
|
||||
#DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/$NAME.pid --pythonpath $PYTHONPATH --module $MODULE"
|
||||
DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 16 -b 32768 -d /var/log/$NAME.log --pidfile /var/run/$NAME.pid --uid $OWNER"
|
||||
|
||||
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
|
||||
|
||||
lockfile=/var/lock/subsys/uwsgi
|
||||
|
||||
start () {
|
||||
echo -n "Starting $DESC: "
|
||||
daemon $prog $DAEMON_OPTS
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
stop () {
|
||||
echo -n "Stopping $DESC: "
|
||||
killproc $prog
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
reload () {
|
||||
echo "Reloading $NAME"
|
||||
killproc $prog -HUP
|
||||
RETVAL=$?
|
||||
echo
|
||||
}
|
||||
|
||||
force-reload () {
|
||||
echo "Reloading $NAME"
|
||||
killproc $prog -TERM
|
||||
RETVAL=$?
|
||||
echo
|
||||
}
|
||||
|
||||
restart () {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
rh_status () {
|
||||
status $prog
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status >/dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
rh_status_q && exit 0
|
||||
$1
|
||||
;;
|
||||
stop)
|
||||
rh_status_q || exit 0
|
||||
$1
|
||||
;;
|
||||
restart|force-reload)
|
||||
$1
|
||||
;;
|
||||
reload)
|
||||
rh_status_q || exit 7
|
||||
$1
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <Python.h>
|
||||
|
||||
void uwsgi_cgi_load_python() {
|
||||
|
||||
Py_Initialize();
|
||||
}
|
||||
|
||||
void uwsgi_cgi_run_python(char *filename) {
|
||||
|
||||
char **e, *p;
|
||||
PyObject *k, *env_value;
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
|
||||
PySys_SetArgv(1, &filename);
|
||||
|
||||
PyObject *os_module = PyImport_ImportModule("os");
|
||||
if (os_module) {
|
||||
PyObject *os_module_dict = PyModule_GetDict(os_module);
|
||||
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
|
||||
if (py_environ) {
|
||||
for (e = environ; *e != NULL; e++) {
|
||||
p = strchr(*e, '=');
|
||||
if (p == NULL) continue;
|
||||
|
||||
k = PyString_FromStringAndSize(*e, (int)(p-*e));
|
||||
if (k == NULL) {
|
||||
PyErr_Print();
|
||||
continue;
|
||||
}
|
||||
|
||||
env_value = PyString_FromString(p+1);
|
||||
if (env_value == NULL) {
|
||||
PyErr_Print();
|
||||
Py_DECREF(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PyObject_SetItem(py_environ, k, env_value)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
Py_DECREF(k);
|
||||
Py_DECREF(env_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyRun_AnyFileEx(fp, filename, 1);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# uwsgi --master --chdir /opt/graphite/webapp/graphite --module graphite_uwsgi ...
|
||||
#
|
||||
#
|
||||
# this module will update a carbon server (used by the graphite tool: http://graphite.wikidot.com/)
|
||||
# with requests count made by a Django app (and can track graphite itself as it is a Django app ;)
|
||||
#
|
||||
#
|
||||
|
||||
import os
|
||||
import uwsgi
|
||||
import time
|
||||
from django.core.handlers.wsgi import WSGIHandler
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||
|
||||
CARBON_SERVER = "127.0.0.1:2003"
|
||||
|
||||
def update_carbon(signum):
|
||||
# connect to the carbon server
|
||||
carbon_fd = uwsgi.connect(CARBON_SERVER)
|
||||
# send data to the carbon server
|
||||
uwsgi.send(carbon_fd, "uwsgi.%s.requests %d %d\n" % (uwsgi.hostname, uwsgi.total_requests(), int(time.time())))
|
||||
# close the connection with the carbon server
|
||||
uwsgi.close(carbon_fd)
|
||||
|
||||
# register a new uwsgi signal (signum: 17)
|
||||
uwsgi.register_signal(17, '', update_carbon)
|
||||
|
||||
# attach a timer of 10 seconds to signal 17
|
||||
uwsgi.add_timer(17, 10)
|
||||
|
||||
# the Django app
|
||||
application = WSGIHandler()
|
||||
@@ -0,0 +1,15 @@
|
||||
use IO::Socket::INET;
|
||||
|
||||
my $s = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $ARGV[0]);
|
||||
|
||||
my $mountpoint = $ARGV[1];
|
||||
my $app = $ARGV[2];
|
||||
|
||||
my $uwsgi_appid = pack('v', length('UWSGI_APPID')).'UWSGI_APPID'.pack('v', length($mountpoint)).$mountpoint;
|
||||
my $uwsgi_script = pack('v', length('UWSGI_SCRIPT')).'UWSGI_SCRIPT'.pack('v', length($app)).$app;
|
||||
|
||||
$s->send(pack('CvC', 5, length($uwsgi_appid.$uwsgi_script),0).$uwsgi_appid.$uwsgi_script);
|
||||
|
||||
while((my $cnt = $s->recv(my $buf, 4096))> 0) {
|
||||
print $buf;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import django
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
import os
|
||||
import sys
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Runs this project as a uWSGI application. Requires the uwsgi binary in system path."
|
||||
|
||||
http_port = '8000'
|
||||
socket_addr = None
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for arg in args:
|
||||
k,v = arg.split('=')
|
||||
if k == 'http':
|
||||
if self.http_port:
|
||||
self.http_port = v
|
||||
elif k == 'socket':
|
||||
self.http_port = None
|
||||
self.socket_addr = v
|
||||
|
||||
# load http and python plugin: first the specific version, otherwise try with the generic one
|
||||
if self.http_port:
|
||||
os.environ['UWSGI_PLUGINS'] = 'http,python%d%d:python' % (sys.version_info[0], sys.version_info[1])
|
||||
else:
|
||||
os.environ['UWSGI_PLUGINS'] = 'python%d%d:python' % (sys.version_info[0], sys.version_info[1])
|
||||
|
||||
# load the Django WSGI handler
|
||||
os.environ['UWSGI_MODULE'] = 'django.core.handlers.wsgi:WSGIHandler()'
|
||||
# DJANGO settings
|
||||
if options['settings']:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = options['settings']
|
||||
else:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||
|
||||
# bind the http server to the default port
|
||||
if self.http_port:
|
||||
os.environ['UWSGI_HTTP'] = ':%s' % self.http_port
|
||||
elif self.socket_addr:
|
||||
os.environ['UWSGI_SOCKET'] = self.socket_addr
|
||||
|
||||
# map admin static files
|
||||
os.environ['UWSGI_STATIC_MAP'] = '%s=%s' % (settings.ADMIN_MEDIA_PREFIX, os.path.join(django.__path__[0], 'contrib', 'admin', 'media'))
|
||||
# remove sockets/pidfile at exit
|
||||
os.environ['UWSGI_VACUUM'] = '1'
|
||||
# retrieve/set the PythonHome
|
||||
os.environ['UWSGI_PYHOME'] = sys.prefix
|
||||
# increase buffer size a bit
|
||||
os.environ['UWSGI_BUFFER_SIZE'] = '8192'
|
||||
# add threads for concurrency
|
||||
os.environ['UWSGI_THREADS'] = '8'
|
||||
# enable the master process
|
||||
os.environ['UWSGI_MASTER'] = '1'
|
||||
# use uWSGI python module aliasing to fix the PYTHONPATH
|
||||
os.environ['UWSGI_PYMODULE_ALIAS'] = '%s=./' % os.path.basename(os.getcwd())
|
||||
# exec the uwsgi binary
|
||||
os.execvp('uwsgi', ('uwsgi',))
|
||||
|
||||
def usage(self, subcomand):
|
||||
return r"""
|
||||
run this project on the uWSGI server
|
||||
|
||||
http=PORT run the embedded http server on port PORT
|
||||
socket=ADDR bind the uwsgi server on address ADDR (this will disable the http server)
|
||||
"""
|
||||
@@ -0,0 +1,11 @@
|
||||
from tasksconsumer import enqueue
|
||||
|
||||
def application(env, sr):
|
||||
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
|
||||
enqueue(queue='fast', pippo='pluto')
|
||||
|
||||
return "Task enqueued"
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from tasksconsumer import *
|
||||
|
||||
@queueconsumer('fast', 4)
|
||||
def fast_queue(arguments):
|
||||
print "fast", arguments
|
||||
|
||||
@queueconsumer('slow')
|
||||
def slow_queue(arguments):
|
||||
print "foobar", arguments
|
||||
@@ -0,0 +1,44 @@
|
||||
from uwsgidecorators import *
|
||||
import Queue
|
||||
from threading import Thread
|
||||
|
||||
queues = {}
|
||||
|
||||
class queueconsumer(object):
|
||||
|
||||
def __init__(self, name, num=1, **kwargs):
|
||||
self.name = name
|
||||
self.num = num
|
||||
self.queue = Queue.Queue()
|
||||
self.threads = []
|
||||
self.func = None
|
||||
queues[self.name] = self
|
||||
|
||||
|
||||
@staticmethod
|
||||
def consumer(self):
|
||||
while True:
|
||||
req = self.queue.get()
|
||||
print req
|
||||
self.func(req)
|
||||
self.queue.task_done()
|
||||
|
||||
def __call__(self, f):
|
||||
self.func = f
|
||||
for i in range(self.num):
|
||||
t = Thread(target=self.consumer,args=(self,))
|
||||
self.threads.append(t)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
@spool
|
||||
def spooler_enqueuer(arguments):
|
||||
if 'queue' in arguments:
|
||||
queue = arguments['queue']
|
||||
queues[queue].queue.put(arguments)
|
||||
else:
|
||||
raise Exception("You have to specify a queue name")
|
||||
|
||||
|
||||
def enqueue(*args, **kwargs):
|
||||
return spooler_enqueuer.spool(*args, **kwargs)
|
||||
@@ -12,4 +12,6 @@ env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
|
||||
# --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
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMMAND=./uwsgi
|
||||
CONFIG_FILE=
|
||||
|
||||
|
||||
FIRST=0
|
||||
|
||||
for ARG in $@;do
|
||||
if [ $FIRST -eq 0 ];then
|
||||
FIRST=1
|
||||
else
|
||||
ARGS="$ARGS $ARG"
|
||||
fi
|
||||
done
|
||||
|
||||
export UWSGI_INHERIT=CONFIG_FILE
|
||||
export UWSGI_PYRUN=$1
|
||||
export UWSGI_PYARGV=$ARGS
|
||||
|
||||
exec $COMMAND
|
||||
@@ -1,5 +1,9 @@
|
||||
require 'rubygems'
|
||||
require 'socket'
|
||||
begin
|
||||
require 'bundler/setup'
|
||||
rescue LoadError
|
||||
end
|
||||
require 'rack'
|
||||
require 'rack/content_length'
|
||||
require 'rack/rewindable_input'
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
import mmap
|
||||
import os
|
||||
import struct
|
||||
import array
|
||||
import time
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
class Cache:
|
||||
|
||||
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
|
||||
|
||||
self.block_size = block_size
|
||||
self.cache_slots = cache_slots
|
||||
|
||||
self.key_size = 2048
|
||||
self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
|
||||
self.block_size_start = self.item_size * self.cache_slots
|
||||
|
||||
fd = os.open(filename, os.O_RDONLY)
|
||||
self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
|
||||
|
||||
self.sample_sleep = sample_sleep
|
||||
self.samples = 0
|
||||
self.history = []
|
||||
self.cache_full = 0
|
||||
self.cache_empty = 0
|
||||
self.cache_items = 0
|
||||
self.block_sizes = 0
|
||||
|
||||
def store_read_item_block(self, position):
|
||||
pos = self.cache_store.tell()
|
||||
# uwsgi cache stores cache entries first and then the blocks
|
||||
self.cache_store.seek(self.block_size_start + (position * self.block_size))
|
||||
buf = self.cache_store.read(self.block_size)
|
||||
self.cache_store.seek(pos)
|
||||
return buf
|
||||
|
||||
def store_read_item(self, position):
|
||||
buf = self.cache_store.read(self.item_size)
|
||||
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
|
||||
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
|
||||
|
||||
if [x for x in key if x!= '\x00']:
|
||||
buf = self.store_read_item_block(position)
|
||||
value = array.array('c', buf).tostring().rstrip('\x00')
|
||||
else:
|
||||
value = ''
|
||||
return (position, key, value, len(value))
|
||||
|
||||
def read(self):
|
||||
data = [self.store_read_item(i) for i in range(self.cache_slots)]
|
||||
self.cache_store.seek(0)
|
||||
self.update_stats(data)
|
||||
if self.sample_sleep:
|
||||
time.sleep(self.sample_sleep)
|
||||
return data
|
||||
|
||||
def update_stats(self, data):
|
||||
# data is a list of (position, key, value, len(value)) tuples
|
||||
items = len([1 for x in data if x[3] > 0])
|
||||
self.cache_items += items
|
||||
full, empty = items == self.cache_slots, items == 0
|
||||
if full:
|
||||
self.cache_full += 1
|
||||
if empty:
|
||||
self.cache_empty += 1
|
||||
self.samples += 1
|
||||
block_sizes = sum([x[3] for x in data])
|
||||
self.block_sizes += block_sizes
|
||||
self.history.append({'full': full, 'empty': empty, 'data': data, \
|
||||
'items': items, 'block_sizes': block_sizes})
|
||||
|
||||
def dump(self):
|
||||
return {
|
||||
'samples': self.samples,
|
||||
'history': self.history,
|
||||
'cache_slots': self.cache_slots,
|
||||
'sample_sleep': self.sample_sleep,
|
||||
'cache_empty': self.cache_empty,
|
||||
'cache_full': self.cache_full,
|
||||
'cache_items': self.cache_items,
|
||||
'block_sizes': self.block_sizes,
|
||||
}
|
||||
|
||||
def show_dump(self):
|
||||
d = self.dump()
|
||||
print
|
||||
print "Recorded %d samples (%d second(s) sleep between samples)" % \
|
||||
(d['samples'], d['sample_sleep'])
|
||||
print "Cache empty %d times, full %d times, %.2f items on average" % \
|
||||
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
|
||||
print "Block size average size: %d bytes" % \
|
||||
(d['block_sizes'] / d['cache_items'] * 8)
|
||||
print "Data in cache average: %d bytes" % \
|
||||
(d['block_sizes'] / d['samples'] * 8)
|
||||
|
||||
def main(options):
|
||||
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
|
||||
options.sleep_time)
|
||||
print "Recording..."
|
||||
while True:
|
||||
try:
|
||||
data = cache.read()
|
||||
except KeyboardInterrupt:
|
||||
cache.show_dump()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser()
|
||||
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
|
||||
help="Slots available in the cache, uwsgi cache option")
|
||||
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
|
||||
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
|
||||
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
|
||||
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
|
||||
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
|
||||
help="The time to sleep between each sample. Default: 1")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if not options.cache_slots:
|
||||
parser.error('Option -s / --cache-slots is mandatory')
|
||||
main(options)
|
||||
@@ -0,0 +1,14 @@
|
||||
service uwsgi
|
||||
{
|
||||
disable = no
|
||||
id = uwsgi-000
|
||||
type = UNLISTED
|
||||
socket_type = stream
|
||||
server = /root/uwsgi/uwsgi
|
||||
server_args = --chdir /root/uwsgi/ --module welcome --logto /tmp/uwsgi.log
|
||||
port = 3031
|
||||
bind = 127.0.0.1
|
||||
user = root
|
||||
wait = yes
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#!./uwsgi --import decoratortest -s :3035 -M --spooler myspool --enable-threads -p 8 --spooler-ordered
|
||||
import uwsgi
|
||||
|
||||
from uwsgidecorators import *
|
||||
|
||||
from uwsgicc import app as application
|
||||
|
||||
import time
|
||||
|
||||
|
||||
# register rpc function helloworld
|
||||
@rpc("helloworld")
|
||||
def hello2():
|
||||
return "[RPC] Hello World"
|
||||
|
||||
# register signal 1
|
||||
@signal(1)
|
||||
def what_time_is_it(num):
|
||||
print(time.asctime())
|
||||
|
||||
# register signal 100
|
||||
@signal(100, target='workers')
|
||||
def what_time_is_it(num):
|
||||
print("*** I AM THE WORKER %d AT %s ***" % (uwsgi.worker_id(), time.asctime()))
|
||||
|
||||
|
||||
# a 3 seconds timer
|
||||
@timer(3)
|
||||
def salut(num):
|
||||
print("Salut !!! 3 seconds elapsed and signal %d raised" % num)
|
||||
|
||||
# a 10 seconds red black timer (executed by the spooler)
|
||||
@rbtimer(10, target='spooler')
|
||||
def tenseconds(num):
|
||||
print("red black timer !!! 10 seconds elapsed and signal %d raised" % num)
|
||||
|
||||
# monitor /tmp directory
|
||||
@filemon("/tmp")
|
||||
def tmpmodified(num):
|
||||
print("/tmp has been modified")
|
||||
|
||||
|
||||
# spool a long running task
|
||||
@spool
|
||||
def a_long_task(args):
|
||||
for i in xrange(1,10):
|
||||
print("%s = %d" % ( str(args), i))
|
||||
print(uwsgi.call('helloworld'))
|
||||
time.sleep(1)
|
||||
|
||||
# continuosly spool a long running task
|
||||
@spoolforever
|
||||
def an_infinite_task(args):
|
||||
for i in xrange(1,4):
|
||||
print("infinite: %d %s" % (i, str(args)))
|
||||
print(uwsgi.call('helloworld'))
|
||||
uwsgi.signal(100)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
# spool a task after 5 seconds
|
||||
@spool
|
||||
def delayed_task(args):
|
||||
print("*** I am a delayed spool job. It is %s [%s]***" % (time.asctime(), str(args)))
|
||||
# send a signal to all workers
|
||||
uwsgi.signal(100)
|
||||
|
||||
@spool
|
||||
def big_body_task(args):
|
||||
print("*** managing a task with a body of %d bytes ***" % len(args['body']))
|
||||
print(args['body'].swapcase())
|
||||
|
||||
# run a task every hour
|
||||
@cron(59, -1, -1, -1, -1)
|
||||
def one_hour_passed(num):
|
||||
print("received signal %d after 1 hour" % num)
|
||||
|
||||
@thread
|
||||
def a_running_thread():
|
||||
while True:
|
||||
time.sleep(2)
|
||||
print("i am a no-args thread")
|
||||
|
||||
@thread
|
||||
def a_running_thread_with_args(who):
|
||||
while True:
|
||||
time.sleep(2)
|
||||
print("Hello %s (from arged-thread)" % who)
|
||||
|
||||
@postfork
|
||||
@thread
|
||||
def a_post_fork_thread():
|
||||
while True:
|
||||
time.sleep(3)
|
||||
if uwsgi.i_am_the_spooler():
|
||||
print("Hello from a thread in the spooler")
|
||||
else:
|
||||
print("Hello from a thread in worker %d" % uwsgi.worker_id())
|
||||
|
||||
@postfork
|
||||
def fork_happened():
|
||||
print("fork() has been called [1]")
|
||||
|
||||
@postfork
|
||||
def fork_happened2():
|
||||
if uwsgi.i_am_the_spooler():
|
||||
return
|
||||
print("worker %d is waiting for signal 100..." % uwsgi.worker_id())
|
||||
uwsgi.signal_wait(100)
|
||||
print("worker %d received signal %d" % (uwsgi.worker_id(), uwsgi.signal_received()))
|
||||
print("fork() has been called [2] wid: %d" % uwsgi.worker_id())
|
||||
|
||||
@postfork
|
||||
@lock
|
||||
def locked_func():
|
||||
print("starting locked function on worker %d" % uwsgi.worker_id())
|
||||
for i in xrange(1, 5):
|
||||
time.sleep(1)
|
||||
print("[locked %d] waiting..." % uwsgi.worker_id())
|
||||
print("done with locked function on worker %d" % uwsgi.worker_id())
|
||||
|
||||
print(uwsgi.call('helloworld'))
|
||||
spool_filename = a_long_task.spool({'foo':'bar'}, hello='world')
|
||||
print("spool filename = %s" % spool_filename)
|
||||
an_infinite_task.spool(foo='bar', priority=3)
|
||||
when = int(time.time())+5
|
||||
print("scheduling a delayed task at %d" % when)
|
||||
delayed_task.spool(foo2='bar2', at=when)
|
||||
a_running_thread()
|
||||
a_running_thread_with_args("uWSGI")
|
||||
uwsgi_source_file = open('uwsgi.c','r')
|
||||
print(big_body_task.spool(priority=9,filename='uwsgi.c',body=uwsgi_source_file.read()))
|
||||
uwsgi_source_file.close()
|
||||
@@ -14,10 +14,11 @@ def index(request):
|
||||
w['load'] = (100 * (w['running_time']/1000))/total_load
|
||||
w['last_spawn_str'] = time.ctime(w['last_spawn'])
|
||||
|
||||
spooler_jobs = uwsgi.spooler_jobs()
|
||||
jobs = []
|
||||
for j in spooler_jobs:
|
||||
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
|
||||
if 'spooler' in uwsgi.opt:
|
||||
spooler_jobs = uwsgi.spooler_jobs()
|
||||
for j in spooler_jobs:
|
||||
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
|
||||
|
||||
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
|
||||
'started_on': time.ctime(uwsgi.started_on),
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
from django.template.base import TemplateDoesNotExist
|
||||
from django.template.loader import BaseLoader
|
||||
from django.conf import settings
|
||||
|
||||
try:
|
||||
import uwsgi
|
||||
on_uwsgi = True
|
||||
except:
|
||||
on_uwsgi = False
|
||||
|
||||
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
|
||||
is_usable = on_uwsgi
|
||||
|
||||
def symbolize(self, name):
|
||||
return name.replace('.','_').replace('/','_').replace('-','_')
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None):
|
||||
filename = 'templates_' + self.symbolize(template_name)
|
||||
for app in settings.INSTALLED_APPS:
|
||||
try:
|
||||
symbol = "%s_%s" % (self.symbolize(app), filename)
|
||||
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
|
||||
except:
|
||||
pass
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
@@ -5,29 +5,98 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern char **environ;
|
||||
|
||||
int emperor_queue;
|
||||
char *emperor_absolute_dir;
|
||||
|
||||
void emperor_send_stats(int);
|
||||
|
||||
struct uwsgi_instance {
|
||||
struct uwsgi_instance *ui_prev;
|
||||
struct uwsgi_instance *ui_next;
|
||||
struct uwsgi_instance *ui_prev;
|
||||
struct uwsgi_instance *ui_next;
|
||||
|
||||
char name[0xff];
|
||||
pid_t pid ;
|
||||
char name[0xff];
|
||||
pid_t pid;
|
||||
|
||||
int status;
|
||||
time_t born;
|
||||
time_t last_mod;
|
||||
int status;
|
||||
time_t born;
|
||||
time_t last_mod;
|
||||
time_t last_loyal;
|
||||
|
||||
uint64_t respawns;
|
||||
uint64_t respawns;
|
||||
int use_config;
|
||||
|
||||
int pipe[2];
|
||||
int pipe[2];
|
||||
int pipe_config[2];
|
||||
|
||||
char *config;
|
||||
uint32_t config_len;
|
||||
|
||||
int loyal;
|
||||
|
||||
int zerg;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
|
||||
struct uwsgi_instance *ui;
|
||||
|
||||
static void royal_death(int signum) {
|
||||
|
||||
|
||||
if (uwsgi.vassals_stop_hook) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui->ui_next;
|
||||
|
||||
while (c_ui) {
|
||||
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
|
||||
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
|
||||
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
}
|
||||
uwsgi_notify("The Emperor is buried.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void emperor_stats() {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui->ui_next;
|
||||
|
||||
while (c_ui) {
|
||||
|
||||
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n",c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
|
||||
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_instance *emperor_get_by_fd(int fd) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
if (c_ui->pipe[0] == fd) {
|
||||
return c_ui;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_instance *emperor_get(char *name) {
|
||||
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while(c_ui->ui_next) {
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
if (!strcmp(c_ui->name, name)) {
|
||||
@@ -50,8 +119,25 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
// this will destroy the whole uWSGI instance (and workers)
|
||||
close(c_ui->pipe[0]);
|
||||
|
||||
if (c_ui->use_config) {
|
||||
close(c_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
if (uwsgi.vassals_stop_hook) {
|
||||
uwsgi_log("running vassal stop-hook: %s %s\n", uwsgi.vassals_stop_hook, c_ui->name);
|
||||
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
int stop_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_stop_hook, c_ui->name);
|
||||
uwsgi_log("%s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
|
||||
}
|
||||
|
||||
uwsgi_log("removed uwsgi instance %s\n", c_ui->name);
|
||||
|
||||
if (c_ui->zerg) {
|
||||
uwsgi.emperor_broodlord_count--;
|
||||
}
|
||||
|
||||
free(c_ui);
|
||||
|
||||
}
|
||||
@@ -71,44 +157,93 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
if (c_ui->use_config) {
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
c_ui->respawns++;
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
|
||||
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(char *name, time_t born) {
|
||||
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid ;
|
||||
char *argv[4];
|
||||
char *uef ;
|
||||
pid_t pid;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
|
||||
while(c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
usleep(uwsgi.emperor_throttle*1000);
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (uid == 0 || gid == 0) {
|
||||
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
|
||||
memset(n_ui, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
if (config) {
|
||||
n_ui->use_config = 1;
|
||||
n_ui->config = config;
|
||||
n_ui->config_len = config_size;
|
||||
}
|
||||
|
||||
c_ui->ui_next = n_ui;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
|
||||
#endif
|
||||
n_ui->ui_prev = c_ui;
|
||||
|
||||
if (strchr(name,':')) {
|
||||
n_ui->zerg = 1;
|
||||
uwsgi.emperor_broodlord_count++;
|
||||
}
|
||||
|
||||
memcpy(n_ui->name, name, strlen(name));
|
||||
n_ui->born = born;
|
||||
n_ui->uid = uid;
|
||||
n_ui->gid = gid;
|
||||
n_ui->last_mod = born;
|
||||
// start without loyalty
|
||||
n_ui->last_loyal = born;
|
||||
n_ui->loyal = 0;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(emperor_queue, n_ui->pipe[0]);
|
||||
|
||||
if (n_ui->use_config) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO pre-start hook
|
||||
|
||||
// a new uWSGI instance will start
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
@@ -118,11 +253,40 @@ void emperor_add(char *name, time_t born) {
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
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_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
if (setgroups(0, NULL)) {
|
||||
uwsgi_error("setgroups()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(uid)) {
|
||||
uwsgi_error("setuid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsetenv("UWSGI_RELOADS");
|
||||
unsetenv("NOTIFY_SOCKET");
|
||||
|
||||
uef = uwsgi_num2str(n_ui->pipe[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
|
||||
@@ -131,17 +295,28 @@ void emperor_add(char *name, time_t born) {
|
||||
}
|
||||
free(uef);
|
||||
|
||||
if (n_ui->use_config) {
|
||||
uef = uwsgi_num2str(n_ui->pipe_config[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
exit(1);
|
||||
}
|
||||
free(uef);
|
||||
}
|
||||
|
||||
uenvs = environ;
|
||||
while(*uenvs) {
|
||||
while (*uenvs) {
|
||||
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs+13);
|
||||
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
|
||||
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
|
||||
if (unsetenv(oe)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
|
||||
if (putenv(ne)) {
|
||||
uwsgi_error("putenv()");
|
||||
@@ -156,24 +331,98 @@ void emperor_add(char *name, time_t born) {
|
||||
// close the left side of the pipe
|
||||
close(n_ui->pipe[0]);
|
||||
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[0]);
|
||||
}
|
||||
|
||||
counter = 4;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
argv[0] = uwsgi.binary_path;
|
||||
if (!strcmp(name+(strlen(name)-4), ".xml")) argv[1] = "--xml";
|
||||
if (!strcmp(name+(strlen(name)-4), ".ini")) argv[1] = "--ini";
|
||||
if (!strcmp(name+(strlen(name)-4), ".yml")) argv[1] = "--yaml";
|
||||
if (!strcmp(name+(strlen(name)-5), ".yaml")) argv[1] = "--yaml";
|
||||
argv[2] = name;
|
||||
argv[3] = NULL;
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
}
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
vassal_argv[2] = name;
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->value;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0)) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<(int)uwsgi.max_fd;i++) {
|
||||
if (n_ui->use_config) {
|
||||
if (i == n_ui->pipe_config[1])
|
||||
continue;
|
||||
}
|
||||
if (i != n_ui->pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.vassals_start_hook) {
|
||||
uwsgi_log("running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
|
||||
if (setenv("UWSGI_VASSALS_DIR", emperor_absolute_dir, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
|
||||
uwsgi_log("%s start-hook returned %d\n", n_ui->name, start_hook_ret);
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(argv[0], argv)) {
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
|
||||
// never here
|
||||
exit(1);
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
|
||||
clear:
|
||||
clear:
|
||||
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
@@ -196,28 +445,114 @@ void emperor_loop() {
|
||||
glob_t g;
|
||||
int i;
|
||||
struct dirent *de;
|
||||
char *amqp_port;
|
||||
int amqp_fd = -1;
|
||||
char *amqp_routing_key;
|
||||
|
||||
void *events;
|
||||
int nevents;
|
||||
int interesting_fd;
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
uwsgi_unix_signal(SIGINT, royal_death);
|
||||
uwsgi_unix_signal(SIGTERM, royal_death);
|
||||
uwsgi_unix_signal(SIGQUIT, royal_death);
|
||||
uwsgi_unix_signal(SIGUSR1, emperor_stats);
|
||||
|
||||
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
uwsgi_log("*** starting uWSGI Emperor ***\n");
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl)) {
|
||||
uwsgi_error("getrlimit()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
|
||||
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0])-1] == '/' ) {
|
||||
simple_mode = 1;
|
||||
if (chdir(uwsgi.emperor_dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi.max_fd = rl.rlim_cur;
|
||||
|
||||
|
||||
emperor_queue = event_queue_init();
|
||||
|
||||
events = event_queue_alloc(64);
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
uwsgi_log("*** starting uWSGI Emperor ***\n");
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_stats) {
|
||||
char *tcp_port = strchr(uwsgi.emperor_stats, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(emperor_queue, uwsgi.emperor_stats_fd);
|
||||
uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd);
|
||||
}
|
||||
|
||||
amqp_port = strchr(uwsgi.emperor_dir, ':');
|
||||
|
||||
if (amqp_port) {
|
||||
if (uwsgi.emperor_amqp_vhost == NULL) uwsgi.emperor_amqp_vhost = "/";
|
||||
if (uwsgi.emperor_amqp_username == NULL) uwsgi.emperor_amqp_username = "guest";
|
||||
if (uwsgi.emperor_amqp_password == NULL) uwsgi.emperor_amqp_password = "guest";
|
||||
reconnect:
|
||||
while(amqp_fd == -1) {
|
||||
uwsgi_log("connecting to AMQP server...\n");
|
||||
amqp_fd = uwsgi_connect(uwsgi.emperor_dir, -1, 0);
|
||||
if (amqp_fd < 0) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("subscribing to queue...\n");
|
||||
if (uwsgi_amqp_consume_queue(amqp_fd, uwsgi.emperor_amqp_vhost, uwsgi.emperor_amqp_username, uwsgi.emperor_amqp_password, "", "uwsgi.emperor", "fanout") < 0) {
|
||||
close(amqp_fd);
|
||||
amqp_fd = -1;
|
||||
sleep(1);
|
||||
goto reconnect;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(emperor_queue, amqp_fd);
|
||||
}
|
||||
else {
|
||||
if (!glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
|
||||
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
|
||||
simple_mode = 1;
|
||||
if (chdir(uwsgi.emperor_dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
}
|
||||
globfree(&g);
|
||||
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
|
||||
if (realpath(".", emperor_absolute_dir) == NULL) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ui = &ui_base;
|
||||
|
||||
for(;;) {
|
||||
int freq = 0 ;
|
||||
|
||||
for (;;) {
|
||||
|
||||
|
||||
if (!i_am_alone) {
|
||||
@@ -227,122 +562,369 @@ void emperor_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
nevents = event_queue_wait_multi(emperor_queue, freq, events, 64);
|
||||
freq = 3;
|
||||
|
||||
for (i = 0; i<nevents;i++) {
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
if (amqp_fd > -1 && interesting_fd == amqp_fd ) {
|
||||
uint64_t msgsize;
|
||||
char *config = uwsgi_amqp_consume(amqp_fd, &msgsize, &amqp_routing_key);
|
||||
|
||||
if (!config) {
|
||||
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
|
||||
event_queue_del_fd(emperor_queue, amqp_fd, event_queue_read());
|
||||
close(amqp_fd);
|
||||
amqp_fd = -1;
|
||||
goto reconnect;
|
||||
}
|
||||
|
||||
if (amqp_routing_key) {
|
||||
uwsgi_log("AMQP routing_key = %s\n", amqp_routing_key);
|
||||
char *config_file = uwsgi_concat2("emperor://", amqp_routing_key);
|
||||
free(amqp_routing_key);
|
||||
|
||||
ui_current = emperor_get(config_file);
|
||||
|
||||
if (ui_current) {
|
||||
// ignore event if i am not loyal
|
||||
if (!ui_current->loyal) continue;
|
||||
free(ui_current->config);
|
||||
ui_current->config = config;
|
||||
ui_current->config_len = msgsize;
|
||||
if (!msgsize) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
else {
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (msgsize > 0) {
|
||||
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(config_file);
|
||||
}
|
||||
else {
|
||||
if (msgsize) {
|
||||
if (msgsize >= 0xff) { free(config); continue; }
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%.*s\n", (int)msgsize, config);
|
||||
#endif
|
||||
char *config_file = uwsgi_concat2n(config, msgsize, "", 0);
|
||||
free(config);
|
||||
|
||||
if (strncmp(config_file, "http://", 7)) {
|
||||
if (stat(config_file, &st)) {
|
||||
free(config_file);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
free(config_file);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ui_current = emperor_get(config_file);
|
||||
|
||||
if (ui_current) {
|
||||
// ignore event if i am not loyal
|
||||
if (!ui_current->loyal) continue;
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
else {
|
||||
emperor_add(config_file, time(NULL), NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1 && interesting_fd == uwsgi.emperor_stats_fd) {
|
||||
emperor_send_stats(uwsgi.emperor_stats_fd);
|
||||
}
|
||||
else {
|
||||
ui_current = emperor_get_by_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
char byte;
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
if (!ui_current->config_len) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
ui_current->loyal = 1;
|
||||
uwsgi_log("*** vassal %s is now loyal ***\n", ui_current->name);
|
||||
|
||||
// TODO post-start hook
|
||||
}
|
||||
else if (byte == 22) {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name,":","zerg");
|
||||
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amqp_fd == -1) {
|
||||
if (simple_mode) {
|
||||
DIR *dir = opendir(".");
|
||||
while((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name+(strlen(de->d_name)-4), ".xml") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".ini") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-4), ".yml") ||
|
||||
!strcmp(de->d_name+(strlen(de->d_name)-5), ".yaml")
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name + (strlen(de->d_name) - 4), ".xml") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
|
||||
) {
|
||||
|
||||
|
||||
if (strlen(de->d_name) >= 0xff) continue;
|
||||
|
||||
if (stat(de->d_name, &st)) continue;
|
||||
if (strlen(de->d_name) >= 0xff)
|
||||
continue;
|
||||
|
||||
if (stat(de->d_name, &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode)) continue;
|
||||
|
||||
ui_current = emperor_get(de->d_name);
|
||||
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, sotp the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(de->d_name, st.st_mtime);
|
||||
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
else {
|
||||
if (glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
|
||||
if (glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("glob()");
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i=0;i<(int)g.gl_pathc;i++) {
|
||||
if (!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".xml") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".ini") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-4), ".yml") ||
|
||||
!strcmp(g.gl_pathv[i]+(strlen(g.gl_pathv[i])-5), ".yaml")
|
||||
) {
|
||||
for (i = 0; i < (int) g.gl_pathc; i++) {
|
||||
if (!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".xml") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".json") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
|
||||
) {
|
||||
|
||||
|
||||
if (strlen(g.gl_pathv[i]) >= 0xff) continue;
|
||||
if (strlen(g.gl_pathv[i]) >= 0xff)
|
||||
continue;
|
||||
|
||||
if (stat(g.gl_pathv[i], &st)) continue;
|
||||
if (stat(g.gl_pathv[i], &st))
|
||||
continue;
|
||||
|
||||
if (!S_ISREG(st.st_mode)) continue;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
if (ui_current) {
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
if (ui_current) {
|
||||
// check if uid or gid are changed, in such case, sotp the instance
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
|
||||
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n");
|
||||
emperor_stop(ui_current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime);
|
||||
}
|
||||
}
|
||||
|
||||
// check if mtime is changed and the uWSGI instance must be reloaded
|
||||
if (st.st_mtime > ui_current->last_mod) {
|
||||
emperor_respawn(ui_current, st.st_mtime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
globfree(&g);
|
||||
}
|
||||
}
|
||||
|
||||
// check for removed instances
|
||||
|
||||
ui_current = ui;
|
||||
has_children = 0;
|
||||
while(ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
has_children++;
|
||||
}
|
||||
|
||||
if (uwsgi.notify) {
|
||||
if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) {
|
||||
uwsgi_notify(notification_message);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_children) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
else {
|
||||
// vacuum
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
diedpid = 0;
|
||||
}
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
ui_current = ui;
|
||||
while(ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance
|
||||
emperor_add(ui_current->name, ui_current->last_mod);
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
// check loyalty if not in simple/glob mode
|
||||
if (amqp_fd > -1) {
|
||||
if (!ui_current->loyal && (time(NULL)-ui_current->last_loyal) > 60) {
|
||||
uwsgi_log("!!! no loyalty showed by instance %s !!!\n", ui_current->name);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ui_current->status == 1) {
|
||||
if (ui_current->config) free(ui_current->config);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (!ui_current->use_config && strncmp(ui_current->name, "http://",7) && stat(ui_current->name, &st) && !ui_current->zerg) {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (ui_current->status == 1) {
|
||||
// remove 'marked for dead' instance
|
||||
if (ui_current->config) free(ui_current->config);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_current->status == 1) {
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (stat(ui_current->name, &st)) {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sleep(3);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
|
||||
#define stats_send(x, y) fprintf(output, x, y)
|
||||
|
||||
void emperor_send_stats(int fd) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *output = fdopen(client_fd, "w");
|
||||
if (!output) {
|
||||
uwsgi_error("fdopen()");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
stats_send("\"emperor\": \"%s\",\n", uwsgi.emperor_dir);
|
||||
|
||||
fprintf(output,"\"emperor_tyrant\": %d,\n", uwsgi.emperor_tyrant);
|
||||
|
||||
|
||||
fprintf(output, "\"vassals\": [\n");
|
||||
|
||||
struct uwsgi_instance *c_ui = ui->ui_next;
|
||||
|
||||
while (c_ui) {
|
||||
fprintf(output,"\t{");
|
||||
stats_send("\"id\": \"%s\", ", c_ui->name);
|
||||
fprintf(output,"\"pid\": %d, ", (int) c_ui->pid);
|
||||
|
||||
stats_send_llu( "\"born\": %llu, ", c_ui->born);
|
||||
stats_send_llu( "\"last_mod\": %llu, ", c_ui->last_mod);
|
||||
|
||||
fprintf(output,"\"loyal\": %d, ", c_ui->loyal);
|
||||
fprintf(output,"\"zerg\": %d, ", c_ui->zerg);
|
||||
|
||||
fprintf(output,"\"uid\": %d, ", (int)c_ui->uid);
|
||||
fprintf(output,"\"gid\": %d, ", (int)c_ui->gid);
|
||||
|
||||
stats_send_llu( "\"respawns\": %llu ", c_ui->respawns);
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
if (c_ui) {
|
||||
fprintf(output,"},\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(output,"]}\n");
|
||||
fclose(output);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ void *event_queue_alloc(int nevents) {
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
|
||||
return (int) pe[id].portev_user;
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
return (int) pe[id].portev_object;
|
||||
@@ -149,7 +149,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
|
||||
|
||||
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
|
||||
*interesting_fd = (int) pe.portev_user;
|
||||
*interesting_fd = (long) pe.portev_user;
|
||||
}
|
||||
else {
|
||||
*interesting_fd = (int) pe.portev_object;
|
||||
@@ -172,6 +172,7 @@ int event_queue_init() {
|
||||
|
||||
int epfd;
|
||||
|
||||
|
||||
epfd = epoll_create(256);
|
||||
|
||||
if (epfd < 0) {
|
||||
@@ -327,11 +328,13 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
@@ -401,7 +404,8 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
if (errno != EINTR)
|
||||
uwsgi_error("kevent()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -441,7 +445,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
if (errno != EINTR)
|
||||
uwsgi_error("kevent()");
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
@@ -476,7 +481,7 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
fo.fo_ctime = st.st_ctim;
|
||||
|
||||
fmon_id++;
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) fmon_id)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *) (long) fmon_id)) {
|
||||
uwsgi_error("port_associate()");
|
||||
return -1;
|
||||
}
|
||||
@@ -506,7 +511,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
fo.fo_atime = st.st_atim;
|
||||
fo.fo_mtime = st.st_mtim;
|
||||
fo.fo_ctime = st.st_ctim;
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)id)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FILE, (uintptr_t) &fo, FILE_MODIFIED|FILE_ATTRIB, (void *)(long)id)) {
|
||||
uwsgi_error("port_associate()");
|
||||
return NULL;
|
||||
}
|
||||
@@ -565,6 +570,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
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;
|
||||
}
|
||||
#else
|
||||
#include <sys/inotify.h>
|
||||
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
@@ -591,7 +606,9 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
|
||||
*id = inotify_add_watch(ifd, filename, IN_ATTRIB|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("added watch %d for filename %s\n", *id, filename);
|
||||
#endif
|
||||
|
||||
if (add_to_queue) {
|
||||
return event_queue_add_fd_read(eq, ifd);
|
||||
@@ -630,7 +647,9 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
}
|
||||
else {
|
||||
items = isize/(sizeof(struct inotify_event));
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("inotify returned %d items\n", items);
|
||||
#endif
|
||||
for(j=0;j<items;j++) {
|
||||
iie = &bie[j];
|
||||
for(i=0;i<ushared->files_monitored_cnt;i++) {
|
||||
@@ -653,6 +672,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
|
||||
@@ -683,13 +704,23 @@ enum
|
||||
|
||||
|
||||
static int timerfd_create (clockid_t __clock_id, int __flags) {
|
||||
#ifdef __amd64__
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int timerfd_settime (int __ufd, int __flags,
|
||||
__const struct itimerspec *__utmr,
|
||||
struct itimerspec *__otmr) {
|
||||
#ifdef __amd64__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -761,7 +792,7 @@ int event_queue_add_timer(int eq, int *id, int sec) {
|
||||
timer_id++;
|
||||
|
||||
pnotif.portnfy_port = eq;
|
||||
pnotif.portnfy_user = (void *) timer_id;
|
||||
pnotif.portnfy_user = (void *) (long) timer_id;
|
||||
|
||||
sigev.sigev_notify = SIGEV_PORT;
|
||||
sigev.sigev_value.sival_ptr = &pnotif;
|
||||
@@ -816,8 +847,6 @@ int event_queue_add_timer(int eq, int *id, int sec) {
|
||||
*id = timer_id ;
|
||||
timer_id++;
|
||||
|
||||
uwsgi_log("registering timer %d\n", sec);
|
||||
|
||||
EV_SET(&kev, *id, EVFILT_TIMER, EV_ADD, 0, sec*1000, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use POSIX;
|
||||
|
||||
open CONFIG,'welcome.ini';
|
||||
|
||||
dup2(fileno(CONFIG), 17);
|
||||
|
||||
exec './uwsgi','--ini','fd://17';
|
||||
@@ -2,10 +2,36 @@ require 'fiber'
|
||||
class SuspendingBody
|
||||
|
||||
def each
|
||||
for i in 1..10
|
||||
for i in 1..3
|
||||
yield "number: #{i}\n"
|
||||
UWSGI.async_sleep(1)
|
||||
puts "sleep..."
|
||||
Fiber.yield
|
||||
end
|
||||
|
||||
fd = UWSGI.async_connect("81.174.68.52:80")
|
||||
UWSGI.wait_fd_write(fd, 3)
|
||||
Fiber.yield
|
||||
io = IO.new(fd)
|
||||
puts "connected"
|
||||
io.syswrite("GET /uwsgi/export/1081%3A362d695b2f25/plugins/fiber/fiber.c HTTP/1.0\r\n")
|
||||
io.syswrite("Host: projects.unbit.it\r\n")
|
||||
io.syswrite("\r\n")
|
||||
|
||||
UWSGI.wait_fd_read(fd, 3)
|
||||
Fiber.yield
|
||||
|
||||
puts "data available"
|
||||
|
||||
begin
|
||||
while body = io.sysread(fd)
|
||||
yield body
|
||||
Fiber.yield
|
||||
end
|
||||
rescue
|
||||
end
|
||||
|
||||
io.close
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from flask import Flask, request
|
||||
app = Flask(__name__)
|
||||
app.debug = True
|
||||
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return "<form method='POST' enctype='multipart/form-data' action='/upload'><input type='text' name='pippo'/><input type='file' name='ufile'/><input type='submit' value='upload'/></form>"
|
||||
|
||||
@app.route('/upload', methods=['GET', 'POST'])
|
||||
def upload_file():
|
||||
return str(len(request.form.get('pippo', 'boh'))) + request.form.get('pippo', 'boh')
|
||||
return request.files['ufile'].read()
|
||||
@@ -2,121 +2,155 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
|
||||
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int)) {
|
||||
|
||||
struct uwsgi_gateway *ug;
|
||||
int num=1,i;
|
||||
|
||||
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
|
||||
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
|
||||
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
if (!strcmp(name, uwsgi.gateways[i].name)) {
|
||||
for(i=0;i<ushared->gateways_cnt;i++) {
|
||||
if (!strcmp(name, ushared->gateways[i].name)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
|
||||
|
||||
ug = &ushared->gateways[ushared->gateways_cnt];
|
||||
ug->pid = 0;
|
||||
ug->name = name;
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
ug->fullname = fullname;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process)
|
||||
gateway_respawn(ushared->gateways_cnt);
|
||||
|
||||
ushared->gateways_cnt++;
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
return ug;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
|
||||
pid_t gw_pid;
|
||||
pid_t orig_pid = getpid();
|
||||
struct uwsgi_gateway *ug;
|
||||
int num=1,i;
|
||||
|
||||
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
|
||||
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.gateways_cnt;i++) {
|
||||
if (!strcmp(name, uwsgi.gateways[i].name)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
gw_pid = fork();
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!uwsgi.master_process) {
|
||||
if (gw_pid > 0) {
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
loop();
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
ug->pid = orig_pid;
|
||||
}
|
||||
else {
|
||||
if (gw_pid == 0) {
|
||||
if (uwsgi.master_as_root) uwsgi_as_root();
|
||||
loop();
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
|
||||
ug->pid = gw_pid;
|
||||
}
|
||||
|
||||
|
||||
ug->name = name;
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
|
||||
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
return ug;
|
||||
|
||||
}
|
||||
|
||||
void gateway_respawn(int id) {
|
||||
|
||||
pid_t gw_pid;
|
||||
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
|
||||
struct uwsgi_gateway *ug = &ushared->gateways[id];
|
||||
|
||||
if (uwsgi.master_process)
|
||||
uwsgi.shared->gateways_harakiri[id] = 0;
|
||||
|
||||
gw_pid = fork();
|
||||
gw_pid = uwsgi_fork(ug->fullname);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
if (uwsgi.master_as_root) uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
ug->loop();
|
||||
uwsgi.mypid = getpid();
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
ug->loop(id);
|
||||
// never here !!! (i hope)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ug->pid = gw_pid;
|
||||
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
ug->respawns++;
|
||||
if (ug->respawns == 1) {
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
||||
|
||||
if (!uwsgi_sock) {
|
||||
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock = uwsgi.gateway_sockets;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_sock) {
|
||||
old_uwsgi_sock = uwsgi_sock;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
old_uwsgi_sock->next = uwsgi_sock;
|
||||
}
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock->fd = -1;
|
||||
uwsgi_sock->shared = 0;
|
||||
uwsgi_sock->name = name;
|
||||
uwsgi_sock->owner = owner;
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
|
||||
|
||||
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
|
||||
|
||||
if (!uwsgi_sock) {
|
||||
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock = uwsgi.gateway_sockets;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_sock) {
|
||||
old_uwsgi_sock = uwsgi_sock;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
|
||||
old_uwsgi_sock->next = uwsgi_sock;
|
||||
}
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
|
||||
uwsgi_sock->fd = fd;
|
||||
uwsgi_sock->name = uwsgi_getsockname(fd);
|
||||
uwsgi_sock->owner = owner;
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
|
||||
|
||||
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_del_fd(queue, ugs->fd, event_queue_read());
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
[uwsgi]
|
||||
|
||||
master = true
|
||||
processes = 4
|
||||
threads = 8
|
||||
|
||||
; initialize 4 sockets with 4 different protocols
|
||||
socket = :3031
|
||||
socket = :3032
|
||||
socket = :3033
|
||||
socket = :3034
|
||||
|
||||
socket-protocol = 0,uwsgi
|
||||
socket-protocol = 1,http
|
||||
socket-protocol = 2,fastcgi
|
||||
socket-protocol = 3,uwsgidump
|
||||
|
||||
|
||||
; add a cache with 1000 items of 96k
|
||||
cache = 1000
|
||||
cache-blocksize = 98304
|
||||
|
||||
|
||||
log-micros = true
|
||||
|
||||
module = heavytest
|
||||
mount = /cc=uwsgicc/__init__.py
|
||||
@@ -0,0 +1,14 @@
|
||||
import uwsgi
|
||||
import werkzeug.testapp
|
||||
|
||||
uwsgi.cache_set("/cache/get", "HTTP 1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>I am the uWSGI cache</h1>")
|
||||
|
||||
def app001(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
return "PATH_INFO=%s" % env['PATH_INFO']
|
||||
|
||||
def app002(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
return "requests: %d" % uwsgi.total_requests()
|
||||
|
||||
uwsgi.applications = { '':werkzeug.testapp.test_app, '/app001':app001, '/app002':app002 }
|
||||
@@ -0,0 +1,7 @@
|
||||
import uwsgi
|
||||
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar"
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
@@ -0,0 +1,25 @@
|
||||
uWSGI version <b><?=uwsgi_version()?></b><br/>
|
||||
workerd id: <b><?=uwsgi_worker_id()?></b><br/>
|
||||
master pid: <b><?=uwsgi_masterpid()?></b><br/>
|
||||
|
||||
uri: <b><?= $_SERVER['REQUEST_URI'] ?></b><br/>
|
||||
docroot: <b><?= $_SERVER['DOCUMENT_ROOT'] ?></b><br/>
|
||||
PATH_INFO: <b><?= $_SERVER['PATH_INFO'] ?></b><br/>
|
||||
|
||||
<? uwsgi_signal(17) ?>
|
||||
|
||||
<? uwsgi_setprocname("test test test"); ?>
|
||||
|
||||
rpc result:<br/>
|
||||
<? echo uwsgi_rpc("", "hello", "one", "two", "three"); ?>
|
||||
|
||||
<?
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
uwsgi_cache_update('foobar', $_POST['cache_val']);
|
||||
}
|
||||
|
||||
?>
|
||||
<form method="POST">
|
||||
<input type="text" name="cache_val" value="<?=uwsgi_cache_get('foobar')?>"/>
|
||||
<input type="submit" value="cache set" />
|
||||
</form>
|
||||
@@ -14,7 +14,7 @@ void ini_rstrip(char *line) {
|
||||
off_t i;
|
||||
|
||||
for(i = strlen(line)-1;i>=0; i--) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
|
||||
line[i] = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ char *ini_lstrip(char *line) {
|
||||
char *ptr = line;
|
||||
|
||||
for(i=0;i< (int) strlen(line);i++) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
@@ -67,6 +67,11 @@ char *ini_get_line(char *ini, off_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
// check if it is a stupid file without \n at the end
|
||||
if (ptr > ini) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
@@ -87,7 +92,14 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
else {
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
@@ -95,7 +107,9 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
|
||||
if (file[0] != 0) {
|
||||
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
|
||||
}
|
||||
|
||||
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
@@ -136,6 +150,11 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>it.unbit.uwsgi.emperor</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/roberta/uwsgi/uwsgi</string>
|
||||
<string>--emperor</string>
|
||||
<string>/Users/*/Library/uwsgi/*.{xml,ini,yml,yaml,js}</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>it.unbit.uwsgi</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/roberta/uwsgi/uwsgi</string>
|
||||
<string>--socket</string>
|
||||
<string>:3032</string>
|
||||
<string>--module</string>
|
||||
<string>welcome</string>
|
||||
<string>--master</string>
|
||||
<string>--die-on-term</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,111 @@
|
||||
#ifdef UWSGI_JSON
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
|
||||
/*
|
||||
I really love the jansson library...
|
||||
*/
|
||||
|
||||
void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
|
||||
int len = 0;
|
||||
char *json_data;
|
||||
|
||||
|
||||
const char *key;
|
||||
|
||||
json_t *root;
|
||||
json_error_t error;
|
||||
json_t *config;
|
||||
json_t *config_value, *config_array_item;
|
||||
|
||||
void *config_iter;
|
||||
|
||||
char *object_asked = "uwsgi";
|
||||
char *colon;
|
||||
int i;
|
||||
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
else {
|
||||
colon = uwsgi_get_last_char(file, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
object_asked = colon+1;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
|
||||
|
||||
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
|
||||
|
||||
#ifdef JANSSON_MAJOR_VERSION
|
||||
root = json_loads(json_data, 0, &error);
|
||||
#else
|
||||
root = json_loads(json_data, &error);
|
||||
#endif
|
||||
|
||||
if (!root) {
|
||||
uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
config = json_object_get(root, object_asked);
|
||||
|
||||
if (!json_is_object(config)) {
|
||||
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
config_iter = json_object_iter(config);
|
||||
|
||||
while(config_iter) {
|
||||
key = json_object_iter_key(config_iter);
|
||||
config_value = json_object_iter_value(config_iter);
|
||||
|
||||
if (json_is_string(config_value)) {
|
||||
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
|
||||
}
|
||||
else if (json_is_true(config_value)) {
|
||||
add_exported_option((char *)key, strdup("1"), 0);
|
||||
}
|
||||
else if (json_is_false(config_value) || json_is_null(config_value)) {
|
||||
add_exported_option((char *)key, strdup("0"), 0);
|
||||
}
|
||||
else if (json_is_integer(config_value)) {
|
||||
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
|
||||
}
|
||||
else if (json_is_array(config_value)) {
|
||||
for(i=0;i<(int)json_array_size(config_value);i++) {
|
||||
config_array_item = json_array_get(config_value, i);
|
||||
if (json_is_string(config_array_item)) {
|
||||
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
|
||||
}
|
||||
else if (json_is_true(config_array_item)) {
|
||||
add_exported_option((char *)key, strdup("1"), 0);
|
||||
}
|
||||
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
|
||||
add_exported_option((char *)key, strdup("0"), 0);
|
||||
}
|
||||
else if (json_is_integer(config_array_item)) {
|
||||
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config_iter = json_object_iter_next(config, config_iter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -108,56 +108,37 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
|
||||
|
||||
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
|
||||
|
||||
struct option *aopt, *lopt;
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_ldap_entry *ule, *entry;
|
||||
char ldap_name[1024];
|
||||
static int counter = 30000000;
|
||||
|
||||
*count = 0;
|
||||
lopt = uwsgi.long_options;
|
||||
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
|
||||
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
while( op && op->name ) {
|
||||
|
||||
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
|
||||
uwsgi_name_to_ldap((char *)op->name, ldap_name);
|
||||
|
||||
entry = search_ldap_cache(ule, ldap_name, *count);
|
||||
|
||||
if (entry) goto next;
|
||||
|
||||
if (aopt->flag) {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = counter;
|
||||
strcpy(entry->names, ldap_name);
|
||||
counter++;
|
||||
*count = *count+1;
|
||||
}
|
||||
else {
|
||||
entry = get_ldap_by_num(ule, aopt->val, *count);
|
||||
if (entry) {
|
||||
strcat(entry->names, ldap_name);
|
||||
}
|
||||
else {
|
||||
entry = &ule[*count] ;
|
||||
entry->num = aopt->val;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count+1;
|
||||
}
|
||||
}
|
||||
entry = &ule[*count] ;
|
||||
entry->num = *count;
|
||||
strcpy(entry->names, ldap_name);
|
||||
*count = *count+1;
|
||||
|
||||
entry->has_arg = aopt->has_arg;
|
||||
entry->has_arg = op->type;
|
||||
|
||||
next:
|
||||
lopt++;
|
||||
op++;
|
||||
}
|
||||
|
||||
return ule;
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump_ldif() {
|
||||
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -210,7 +191,7 @@ void uwsgi_ldap_schema_dump_ldif() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump() {
|
||||
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
|
||||
int i;
|
||||
int items;
|
||||
@@ -258,7 +239,7 @@ void uwsgi_ldap_schema_dump() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config() {
|
||||
void uwsgi_ldap_config(char *url) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
@@ -267,7 +248,6 @@ void uwsgi_ldap_config() {
|
||||
char *attr;
|
||||
char *uwsgi_attr;
|
||||
|
||||
char *url = "ldap:///";
|
||||
char *url_slash;
|
||||
|
||||
int desired_version = LDAP_VERSION3;
|
||||
@@ -275,10 +255,6 @@ void uwsgi_ldap_config() {
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (uwsgi.ldap) {
|
||||
url = uwsgi.ldap;
|
||||
}
|
||||
|
||||
if (!ldap_is_ldap_url(url)) {
|
||||
uwsgi_log("invalid LDAP url.\n");
|
||||
exit(1);
|
||||
|
||||
+775
@@ -0,0 +1,775 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define ntohll(x) x
|
||||
#else
|
||||
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
|
||||
#endif
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
|
||||
|
||||
struct amqp_frame_header {
|
||||
|
||||
char type;
|
||||
uint16_t channel;
|
||||
uint32_t size;
|
||||
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct amqp_frame_method {
|
||||
uint16_t class_id;
|
||||
uint16_t method_id;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
|
||||
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
|
||||
|
||||
static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
|
||||
uint8_t str_size;
|
||||
|
||||
// over engeneering...
|
||||
if (ptr+1 > watermark) return NULL;
|
||||
|
||||
str_size = *ptr;
|
||||
|
||||
if (ptr+1+str_size > watermark) return NULL;
|
||||
|
||||
return ptr+1+str_size;
|
||||
}
|
||||
|
||||
|
||||
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
|
||||
|
||||
uint16_t tmp_short;
|
||||
|
||||
if (ptr+2 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_short, ptr, 2);
|
||||
|
||||
*sv = ntohs(tmp_short);
|
||||
|
||||
return ptr+2;
|
||||
}
|
||||
|
||||
static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
|
||||
|
||||
uint32_t tmp_long;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_long, ptr, 4);
|
||||
|
||||
*lv = ntohl(tmp_long);
|
||||
return ptr+4;
|
||||
}
|
||||
|
||||
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
|
||||
|
||||
uint64_t tmp_longlong;
|
||||
|
||||
if (ptr+8 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_longlong, ptr, 8);
|
||||
|
||||
*llv = ntohll(tmp_longlong);
|
||||
return ptr+8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int amqp_send_ack(int fd, uint64_t delivery_tag) {
|
||||
|
||||
uint32_t size = 4 + 8 + 1;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 80
|
||||
amqp_send(fd, "\x00\x3C\x00\x50", 4);
|
||||
|
||||
// set delivery_tag
|
||||
delivery_tag = htonll(delivery_tag);
|
||||
amqp_send(fd, &delivery_tag, 8);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
|
||||
uint32_t size;
|
||||
struct amqp_frame_header fh;
|
||||
uint64_t delivery_tag;
|
||||
uint64_t current_size = 0;
|
||||
char *ptr;
|
||||
char *watermark;
|
||||
uint16_t sv;
|
||||
|
||||
char *frame = amqp_get_method(fd, 60, 60, &size);
|
||||
if (!frame) return NULL;
|
||||
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
|
||||
// consumer_tag
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
|
||||
// delivery_tag (needed for ack)
|
||||
ptr = amqp_get_longlong(ptr, watermark, &delivery_tag); if (!ptr) goto clear;
|
||||
// redelivered
|
||||
if (ptr+1 > watermark) goto clear;
|
||||
ptr++;
|
||||
// exchange
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) goto clear;
|
||||
// routing_key
|
||||
if (ptr+1 > watermark) goto clear;
|
||||
uint8_t rk_size = (uint8_t) *ptr;
|
||||
ptr++;
|
||||
if (ptr+rk_size > watermark) goto clear;
|
||||
|
||||
if (rk_size > 0) {
|
||||
char *rkey = uwsgi_concat2n(ptr, rk_size, "", 0);
|
||||
ptr+=rk_size;
|
||||
|
||||
*routing_key = rkey;
|
||||
}
|
||||
else {
|
||||
*routing_key = NULL;
|
||||
}
|
||||
|
||||
char *header = amqp_simple_get_frame(fd, &fh);
|
||||
if (!header) goto clear;
|
||||
|
||||
if (fh.type != 2) goto clear2;
|
||||
|
||||
ptr = header;
|
||||
watermark = ptr+fh.size;
|
||||
|
||||
// header class_id
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
|
||||
// header weight
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) goto clear2;
|
||||
// message size;
|
||||
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
|
||||
|
||||
free(frame);
|
||||
frame = NULL;
|
||||
free(header);
|
||||
header = NULL;
|
||||
|
||||
char *fullbody = uwsgi_malloc(*msgsize);
|
||||
char *message;
|
||||
|
||||
while(current_size < *msgsize) {
|
||||
message = amqp_simple_get_frame(fd, &fh);
|
||||
if (!message) goto clear;
|
||||
|
||||
if (fh.type != 3) {
|
||||
free(message);
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
if (fh.size+current_size > *msgsize) {
|
||||
free(message);
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
memcpy(fullbody+current_size, message, fh.size);
|
||||
current_size+=fh.size;
|
||||
free(message);
|
||||
}
|
||||
|
||||
if (amqp_send_ack(fd, delivery_tag) < 0) {
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
return fullbody;
|
||||
|
||||
clear3:
|
||||
free(fullbody);
|
||||
return NULL;
|
||||
|
||||
clear2:
|
||||
free(header);
|
||||
clear:
|
||||
free(frame);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static int amqp_send_exchange_declare( int fd, char *exchange, char *exchange_type) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(exchange)) + (1 +strlen(exchange_type)) + 1 + 4;
|
||||
uint8_t shortsize = strlen(exchange) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 40 method 10
|
||||
amqp_send(fd, "\x00\x28\x00\x0A", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set exchange name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange, shortsize);
|
||||
|
||||
// set exchange type
|
||||
shortsize = strlen(exchange_type);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange_type, shortsize);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_bind( int fd, char *queue, char *exchange) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + (1 +strlen(exchange)) + 1 + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 50 method 20
|
||||
amqp_send(fd, "\x00\x32\x00\x14", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// set exchange name
|
||||
shortsize = strlen(exchange);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, exchange, shortsize);
|
||||
|
||||
// set empty routing-key
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_consume( int fd, char *queue) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 20
|
||||
amqp_send(fd, "\x00\x3C\x00\x14", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// set tag name
|
||||
amqp_send(fd, "\0", 1);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amqp_wait_connection_start(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 10, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int amqp_wait_exchange_declare_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 40, 11, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_basic_consume_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 60, 21, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_channel_open_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 20, 11, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int amqp_wait_queue_bind_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 50, 21, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static char *amqp_wait_queue_declare_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 50, 11, &size);
|
||||
char *queue = NULL;
|
||||
char *ptr;
|
||||
char *watermark;
|
||||
|
||||
if (frame) {
|
||||
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
|
||||
ptr = amqp_get_str(ptr, watermark); if (!ptr) { free(frame); return NULL; }
|
||||
|
||||
queue = uwsgi_concat2n(frame+5, *(frame+4), "", 0);
|
||||
|
||||
free(frame);
|
||||
return queue;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_connection_open_ok(int fd) {
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 41, &size);
|
||||
|
||||
if (frame) {
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int amqp_wait_connection_tune(int fd) {
|
||||
|
||||
uint32_t size;
|
||||
char *frame = amqp_get_method(fd, 10, 30, &size);
|
||||
|
||||
uint16_t sv;
|
||||
uint32_t lv;
|
||||
char *watermark ;
|
||||
char *ptr;
|
||||
|
||||
|
||||
if (frame) {
|
||||
ptr = frame+4;
|
||||
watermark = frame+size;
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP max channels: %d\n", sv);
|
||||
ptr = amqp_get_long(ptr, watermark, &lv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP max frame size: %d\n", lv);
|
||||
ptr = amqp_get_short(ptr, watermark, &sv); if (!ptr) { free(frame); return -1; }
|
||||
uwsgi_log("AMQP heartbeath: %d\n", sv);
|
||||
|
||||
free(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
char *ptr = (char *) fh;
|
||||
size_t len = 0, rlen;
|
||||
|
||||
while(len < 7) {
|
||||
rlen = recv(fd, ptr, 7-len, 0);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
return NULL;
|
||||
}
|
||||
len += rlen;
|
||||
ptr += rlen;
|
||||
}
|
||||
|
||||
fh->channel = ntohs(fh->channel);
|
||||
fh->size = ntohl(fh->size);
|
||||
|
||||
len = 0;
|
||||
|
||||
char *frame = uwsgi_malloc(fh->size+1);
|
||||
ptr = frame;
|
||||
|
||||
while(len < fh->size+1) {
|
||||
rlen = recv(fd, ptr, (fh->size+1)-len, 0);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
return NULL;
|
||||
}
|
||||
len += rlen;
|
||||
ptr += rlen;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static char *amqp_get_method(int fd, uint16_t class_id, uint16_t method_id, uint32_t *size) {
|
||||
|
||||
struct amqp_frame_header fh;
|
||||
struct amqp_frame_method *fm;
|
||||
|
||||
char *frame = amqp_simple_get_frame(fd, &fh);
|
||||
if (!frame) return NULL;
|
||||
|
||||
if (fh.type != 1) goto clear;
|
||||
|
||||
fm = (struct amqp_frame_method *) frame;
|
||||
fm->class_id = ntohs(fm->class_id);
|
||||
fm->method_id = ntohs(fm->method_id);
|
||||
|
||||
if (fm->class_id != class_id) goto clear;
|
||||
if (fm->method_id != method_id) goto clear;
|
||||
|
||||
*size = fh.size;
|
||||
return frame;
|
||||
|
||||
clear:
|
||||
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int amqp_send_channel_open(int fd, uint16_t id) {
|
||||
|
||||
uint32_t size = 4 + 1;
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 20 method 10
|
||||
amqp_send(fd, "\x00\x14\x00\x0A", 4);
|
||||
|
||||
amqp_send(fd, "\0", 1);
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amqp_send_connection_open(int fd, char *vhost) {
|
||||
|
||||
uint8_t shortsize = strlen(vhost);
|
||||
uint32_t size = 4 + 1 +strlen(vhost) + 2;
|
||||
size = htonl(size);
|
||||
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 28
|
||||
amqp_send(fd, "\x00\x0A\x00\x28", 4);
|
||||
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, vhost, strlen(vhost));
|
||||
|
||||
shortsize = 0;
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int amqp_send_connection_tune_ok(int fd, uint16_t max_chan, uint32_t max_frame_size, uint16_t heartbeat) {
|
||||
|
||||
uint32_t size = 4 + 2 + 4 + 2;
|
||||
size = htonl(size);
|
||||
|
||||
max_chan = htons(max_chan);
|
||||
max_frame_size = htonl(max_frame_size);
|
||||
heartbeat = htons(heartbeat);
|
||||
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 15
|
||||
amqp_send(fd, "\x00\x0A\x00\x1F", 4);
|
||||
|
||||
amqp_send(fd, &max_chan, 2);
|
||||
amqp_send(fd, &max_frame_size, 4);
|
||||
amqp_send(fd, &heartbeat, 2);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_queue_declare(int fd, char *queue) {
|
||||
|
||||
uint32_t size = 4 + 2 + (1 +strlen(queue)) + 1 + 4;
|
||||
uint8_t shortsize = strlen(queue) ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 50 method 10
|
||||
amqp_send(fd, "\x00\x32\x00\x0A", 4);
|
||||
|
||||
// send empty reserved
|
||||
amqp_send(fd, "\0\0", 2);
|
||||
|
||||
// set queue name
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, queue, shortsize);
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// empty table
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *amqp_get_queue(int fd, char *queue) {
|
||||
|
||||
if (amqp_send_queue_declare(fd, queue) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return amqp_wait_queue_declare_ok(fd);
|
||||
}
|
||||
|
||||
|
||||
static int amqp_send_connection_start_ok(int fd, char *mech, char *sasl_response, int sasl_response_size, char *locale) {
|
||||
|
||||
uint32_t size = 4 + 4 + (1 +strlen(mech)) + (4 + sasl_response_size) + (1 + strlen(locale));
|
||||
uint8_t shortsize ;
|
||||
|
||||
size = htonl(size);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\0", 3);
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 10 method 11
|
||||
amqp_send(fd, "\x00\x0A\x00\x0B", 4);
|
||||
|
||||
// send empty client properties
|
||||
amqp_send(fd, "\0\0\0\0", 4);
|
||||
|
||||
// send mechanism short string
|
||||
shortsize = strlen(mech);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, mech, strlen(mech));
|
||||
|
||||
// send sasl response
|
||||
size = htonl(sasl_response_size);
|
||||
amqp_send(fd, &size, 4);
|
||||
amqp_send(fd, sasl_response, sasl_response_size);
|
||||
|
||||
// send locale
|
||||
shortsize = strlen(locale);
|
||||
amqp_send(fd, &shortsize, 1);
|
||||
amqp_send(fd, locale, strlen(locale));
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_amqp_consume_queue(int fd, char *vhost, char *username, char *password, char *queue, char *exchange, char *exchange_type) {
|
||||
|
||||
char *auth = uwsgi_concat4n("\0",1, username, strlen(username), "\0",1, password, strlen(password));
|
||||
|
||||
if (send(fd, AMQP_CONNECTION_HEADER, 8, 0) < 0) {
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_connection_start(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.start\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.start-ok\n");
|
||||
if (amqp_send_connection_start_ok(fd, "PLAIN", auth, strlen(username)+strlen(password)+2, "en_US") < 0) {
|
||||
free(auth);
|
||||
uwsgi_log("AMQP error sending Connection.start-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(auth);
|
||||
|
||||
if (amqp_wait_connection_tune(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.tune\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.tune-ok\n");
|
||||
if (amqp_send_connection_tune_ok(fd, 0, 0xffff, 0) < 0) {
|
||||
uwsgi_log("AMQP error sending Connection.tune-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Connection.open\n");
|
||||
if (amqp_send_connection_open(fd, vhost) < 0) {
|
||||
uwsgi_log("AMQP error sending Connection.open\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_connection_open_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Connection.open-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_log("sending Channel.open\n");
|
||||
if (amqp_send_channel_open(fd, 1) < 0) {
|
||||
uwsgi_log("AMQP error sending Channel.open\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_channel_open_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Channel.open-ok\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
queue = amqp_get_queue(fd, queue);
|
||||
if (!queue) {
|
||||
uwsgi_log("AMQP error sending Queue.declare\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (exchange) {
|
||||
if (amqp_send_exchange_declare(fd, exchange, exchange_type) < 0) {
|
||||
uwsgi_log("AMQP error sending Exchange.declare\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_exchange_declare_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Exchange.declare-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_send_queue_bind(fd, queue, exchange) < 0) {
|
||||
uwsgi_log("AMQP error sending Queue.bind\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_queue_bind_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Queue.bind-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (amqp_send_queue_consume(fd, queue) < 0) {
|
||||
uwsgi_log("AMQP error sending Basic.consume\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (amqp_wait_basic_consume_ok(fd) < 0) {
|
||||
uwsgi_log("AMQP error waiting for Basic.consume-ok\n");
|
||||
free(queue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(queue);
|
||||
|
||||
uwsgi_log("AMQP subscription done, waiting for events...\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
|
||||
common functions for various routers (fastrouter, http...)
|
||||
|
||||
*/
|
||||
static void uwsgi_corerouter_setup_sockets(char *gw_id) {
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(gw_id, ugs->owner)) {
|
||||
#ifdef UWSGI_SCTP
|
||||
if (!ugs->subscription && !ugs->sctp) {
|
||||
#else
|
||||
if (!ugs->subscription) {
|
||||
#endif
|
||||
if (ugs->name[0] == '=') {
|
||||
int shared_socket = atoi(ugs->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
ugs->shared = 1;
|
||||
if (ugs->fd == -1) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
exit(1);
|
||||
}
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
|
||||
int fd_socket = atoi(ugs->name+5);
|
||||
if (fd_socket >= 0) {
|
||||
ugs->fd = fd_socket;
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
if (!ugs->name) {
|
||||
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ugs->port = strchr(ugs->name, ':');
|
||||
if (ugs->fd == -1) {
|
||||
if (ugs->port) {
|
||||
ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port);
|
||||
ugs->port++;
|
||||
ugs->port_len = strlen(ugs->port);
|
||||
}
|
||||
else {
|
||||
ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
// put socket in non-blocking mode
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
uwsgi_log("%s bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
else if (ugs->subscription) {
|
||||
if (ugs->fd == -1) {
|
||||
ugs->fd = bind_to_udp(ugs->name, 0, 0);
|
||||
uwsgi_socket_nb(ugs->fd);
|
||||
}
|
||||
uwsgi_log("%s subscription server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
#ifdef UWSGI_SCTP
|
||||
else if (ugs->sctp) {
|
||||
if (ugs->fd == -1) {
|
||||
ugs->fd = bind_to_sctp(ugs->name);
|
||||
}
|
||||
uwsgi_log("%s SCTP server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void *uwsgi_corerouter_setup_event_queue(char *gw_id, int id, int nevents, int *efd, int cheap) {
|
||||
|
||||
*efd = event_queue_init();
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(gw_id, ugs->owner)) {
|
||||
if (!cheap || ugs->subscription) {
|
||||
event_queue_add_fd_read(*efd, ugs->fd);
|
||||
}
|
||||
ugs->gateway = &ushared->gateways[id];
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
|
||||
return event_queue_alloc(nevents);
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused)) uwsgi_corerouter_manage_subscription(char *gw_id, int id, struct uwsgi_gateway_socket *ugs, int queue, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 0;
|
||||
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
|
||||
}
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (node->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(subscriptions, node);
|
||||
}
|
||||
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
|
||||
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// propagate the subscription to other nodes
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (i == id)
|
||||
continue;
|
||||
if (!strcmp(ushared->gateways[i].name, gw_id)) {
|
||||
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
|
||||
uwsgi_error("send()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused)) uwsgi_corerouter_manage_internal_subscription(char *gw_id, int queue, int fd, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
|
||||
|
||||
|
||||
struct uwsgi_subscribe_req usr;
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(queue, fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
|
||||
event_queue_add_fd_read(queue, ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
*i_am_cheap = 0;
|
||||
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
|
||||
}
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (node->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(subscriptions, node);
|
||||
}
|
||||
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
|
||||
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifndef CLONE_NEWUTS
|
||||
#define CLONE_NEWUTS 0x04000000
|
||||
#endif
|
||||
|
||||
#ifndef CLONE_NEWPID
|
||||
#define CLONE_NEWPID 0x20000000
|
||||
#endif
|
||||
|
||||
#ifndef CLONE_NEWIPC
|
||||
#define CLONE_NEWIPC 0x08000000
|
||||
#endif
|
||||
|
||||
#ifndef CLONE_NEWNET
|
||||
#define CLONE_NEWNET 0x40000000
|
||||
#endif
|
||||
|
||||
void linux_namespace_start(void *argv) {
|
||||
for (;;) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
int waitpid_status;
|
||||
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
|
||||
int clone_flags = SIGCHLD | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;
|
||||
if (uwsgi.ns_net) {
|
||||
clone_flags |= CLONE_NEWNET;
|
||||
}
|
||||
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
|
||||
if (pid == -1) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
uwsgi_log("running \"%s\" (post-jail)...\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;
|
||||
}
|
||||
|
||||
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
|
||||
pid = waitpid(pid, &waitpid_status, 0);
|
||||
if (pid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// in Linux this is reliable
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == 1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("pid %d ended. Respawning...\n", (int) pid);
|
||||
}
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
|
||||
|
||||
void linux_namespace_jail() {
|
||||
|
||||
char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;
|
||||
|
||||
if (getpid() != 1) {
|
||||
uwsgi_log("your kernel does not support linux pid namespace\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *ns_hostname = strchr(uwsgi.ns, ':');
|
||||
if (ns_hostname) {
|
||||
ns_hostname[0] = 0;
|
||||
ns_hostname++;
|
||||
if (sethostname(ns_hostname, strlen(ns_hostname))) {
|
||||
uwsgi_error("sethostname()");
|
||||
}
|
||||
}
|
||||
|
||||
FILE *procmounts;
|
||||
char line[1024];
|
||||
int unmounted = 1;
|
||||
char *delim0, *delim1;
|
||||
|
||||
if (chdir(uwsgi.ns)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(uwsgi.ns, "/")) {
|
||||
ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
|
||||
mkdir(ns_tmp_mountpoint, S_IRWXU);
|
||||
|
||||
ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
|
||||
mkdir(ns_tmp_mountpoint2, S_IRWXU);
|
||||
|
||||
if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
}
|
||||
if (chdir(ns_tmp_mountpoint)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
|
||||
if (pivot_root(".", ns_tmp_mountpoint2)) {
|
||||
uwsgi_error("pivot_root()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (chdir("/")) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log("remounting /proc\n");
|
||||
if (mount("proc", "/proc", "proc", 0, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
}
|
||||
|
||||
while (unmounted) {
|
||||
|
||||
unmounted = 0;
|
||||
procmounts = fopen("/proc/self/mounts", "r");
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
delim0 = strchr(line, ' ');
|
||||
delim0++;
|
||||
delim1 = strchr(delim0, ' ');
|
||||
*delim1 = 0;
|
||||
if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
|
||||
continue;
|
||||
if (!umount(delim0)) {
|
||||
unmounted++;
|
||||
}
|
||||
}
|
||||
fclose(procmounts);
|
||||
}
|
||||
|
||||
if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
|
||||
uwsgi_error("rmdir()");
|
||||
}
|
||||
if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
|
||||
uwsgi_error("rmdir()");
|
||||
}
|
||||
|
||||
if (strcmp(uwsgi.ns, "/")) {
|
||||
free(ns_tmp_mountpoint2);
|
||||
free(ns_tmp_mountpoint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#ifndef __u16
|
||||
#define __u16 u_int16_t
|
||||
#endif
|
||||
#ifndef __u32
|
||||
#define __u32 u_int32_t
|
||||
#endif
|
||||
#ifndef __s32
|
||||
#define __s32 int32_t
|
||||
#endif
|
||||
#ifndef __u8
|
||||
#define __u8 u_int8_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#ifdef CLONE_NEWNET
|
||||
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
#ifndef VETH_INFO_PEER
|
||||
# define VETH_INFO_PEER 1
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_nl_req {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct ifinfomsg ifinfomsg;
|
||||
};
|
||||
|
||||
struct uwsgi_nl_ipreq {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct ifaddrmsg ifaddrmsg;
|
||||
};
|
||||
|
||||
struct uwsgi_nl_rtreq {
|
||||
struct nlmsghdr nlmsg;
|
||||
struct rtmsg rtmsg;
|
||||
};
|
||||
|
||||
int uwsgi_nl_send(struct nlmsghdr *);
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
unr->ifinfomsg.ifi_family = AF_UNSPEC;
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWLINK;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_ip_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
|
||||
uni->ifaddrmsg.ifa_family = AF_INET;
|
||||
uni->ifaddrmsg.ifa_scope = 0;
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWADDR;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
struct nlmsghdr *uwsgi_netlink_rt_alloc() {
|
||||
|
||||
size_t len = NLMSG_ALIGN(8192) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
|
||||
|
||||
struct nlmsghdr *nlmsg = (struct nlmsghdr *) uwsgi_malloc(len);
|
||||
|
||||
memset(nlmsg, 0, len);
|
||||
|
||||
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
|
||||
unr->rtmsg.rtm_family = AF_INET;
|
||||
unr->rtmsg.rtm_table = RT_TABLE_MAIN;
|
||||
unr->rtmsg.rtm_protocol = RTPROT_STATIC;
|
||||
unr->rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
unr->rtmsg.rtm_type = RTN_UNICAST;
|
||||
|
||||
|
||||
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
nlmsg->nlmsg_type = RTM_NEWROUTE;
|
||||
nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
|
||||
return nlmsg;
|
||||
}
|
||||
|
||||
int uwsgi_netlink_rt(char *src, char *dst, int dst_prefix, char *gw) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
struct in_addr oa;
|
||||
struct in_addr ga;
|
||||
struct uwsgi_nl_rtreq *unr = (struct uwsgi_nl_rtreq *)nlmsg;
|
||||
|
||||
if (inet_pton(AF_INET, src, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, dst, &oa) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, gw, &ga) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_PREFSRC;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_DST;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &oa.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_GATEWAY;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ga.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
unr->rtmsg.rtm_src_len = 0;
|
||||
unr->rtmsg.rtm_dst_len = dst_prefix;
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_netlink_gw(char *iface, char *ip) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_rt_alloc();
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
uint32_t zero = 0;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
if (inet_pton(AF_INET, ip, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_GATEWAY;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &ia.s_addr, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_DST;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &zero, 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = RTA_OIF;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(int));
|
||||
memcpy(RTA_DATA(rta), &index, sizeof(int));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_netlink_ip(char *iface, char *ip, int prefix) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_ip_alloc();
|
||||
struct uwsgi_nl_ipreq *uni = (struct uwsgi_nl_ipreq *)nlmsg;
|
||||
struct rtattr *rta;
|
||||
struct in_addr ia;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
uni->ifaddrmsg.ifa_index = index;
|
||||
uni->ifaddrmsg.ifa_prefixlen = prefix;
|
||||
|
||||
if (inet_pton(AF_INET, ip, &ia) <= 0) {
|
||||
uwsgi_error("inet_pton()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFA_LOCAL;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
|
||||
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFA_ADDRESS;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
|
||||
memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_netlink_veth_attach(char *veth1, pid_t pid) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
struct rtattr *rta;
|
||||
|
||||
int index = if_nametoindex(veth1);
|
||||
if (!index) return -1;
|
||||
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_NET_NS_PID;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(pid_t));
|
||||
memcpy(RTA_DATA(rta), &pid, sizeof(pid_t));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_netlink_ifup(char *iface) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
unr->ifinfomsg.ifi_change |= IFF_UP;
|
||||
unr->ifinfomsg.ifi_flags |= IFF_UP;
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_netlink_del(char *iface) {
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
struct uwsgi_nl_req *unr = (struct uwsgi_nl_req *)nlmsg;
|
||||
|
||||
int index = if_nametoindex(iface);
|
||||
if (!index) return -1;
|
||||
|
||||
nlmsg->nlmsg_type = RTM_DELLINK;
|
||||
unr->ifinfomsg.ifi_index = index;
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_netlink_veth(char *veth0, char *veth1) {
|
||||
|
||||
struct rtattr *rta, *rta0, *rta1, *rta2;
|
||||
|
||||
struct nlmsghdr *nlmsg = uwsgi_netlink_alloc();
|
||||
|
||||
nlmsg->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
|
||||
|
||||
// IFLA_LINKINFO
|
||||
rta0 = NLMSG_TAIL(nlmsg);
|
||||
rta0->rta_type = IFLA_LINKINFO;
|
||||
rta0->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta0->rta_len);
|
||||
|
||||
// IFLA_INFO_KIND
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_INFO_KIND;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), "veth", 4);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
// IFLA_INFO_DATA
|
||||
rta1 = NLMSG_TAIL(nlmsg);
|
||||
rta1->rta_type = IFLA_INFO_DATA;
|
||||
rta1->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta1->rta_len);
|
||||
|
||||
// VETH_INFO_PEER
|
||||
rta2 = NLMSG_TAIL(nlmsg);
|
||||
rta2->rta_type = VETH_INFO_PEER;
|
||||
rta2->rta_len = RTA_LENGTH(0);
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta2->rta_len);
|
||||
|
||||
nlmsg->nlmsg_len += sizeof(struct ifinfomsg);
|
||||
|
||||
// IFLA_IFNAME
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_IFNAME;
|
||||
rta->rta_len = RTA_LENGTH(strlen(veth1));
|
||||
memcpy(RTA_DATA(rta), veth1, strlen(veth1));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
rta2->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta2;
|
||||
rta1->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta1;
|
||||
rta0->rta_len = (void *)NLMSG_TAIL(nlmsg) - (void *)rta0;
|
||||
|
||||
// IFLA_IFNAME
|
||||
rta = NLMSG_TAIL(nlmsg);
|
||||
rta->rta_type = IFLA_IFNAME;
|
||||
rta->rta_len = RTA_LENGTH(strlen(veth0));
|
||||
memcpy(RTA_DATA(rta), veth0, strlen(veth0));
|
||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len);
|
||||
|
||||
return uwsgi_nl_send(nlmsg);
|
||||
}
|
||||
|
||||
int uwsgi_nl_send(struct nlmsghdr *nlmsg) {
|
||||
|
||||
struct sockaddr_nl nladdr;
|
||||
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*)nlmsg,
|
||||
.iov_len = nlmsg->nlmsg_len,
|
||||
};
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
int ret;
|
||||
int nlfd;
|
||||
|
||||
memset(&nladdr, 0, sizeof(struct sockaddr_nl));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
|
||||
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (nlfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
free(nlmsg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sendmsg(nlfd, &msg, 0);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return -1;
|
||||
}
|
||||
ret = recvmsg(nlfd, &msg, 0);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("recvmsg()");
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlmsg);
|
||||
ret = err->error;
|
||||
}
|
||||
|
||||
free(nlmsg);
|
||||
close(nlfd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
+26
-1
@@ -19,12 +19,22 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../uwsgi.h"
|
||||
|
||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
|
||||
}
|
||||
static inline void rb_set_color(struct rb_node *rb, int color)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
||||
}
|
||||
|
||||
|
||||
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
||||
{
|
||||
struct rb_node *right = node->rb_right;
|
||||
@@ -282,3 +292,18 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
|
||||
if (color == RB_BLACK)
|
||||
__rb_erase_color(child, parent, root);
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
#else
|
||||
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
#endif
|
||||
{
|
||||
node->rb_parent_color = (unsigned long )parent;
|
||||
node->rb_left = node->rb_right = NULL;
|
||||
|
||||
*rb_link = node;
|
||||
}
|
||||
|
||||
|
||||
+8
-20
@@ -18,7 +18,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,6 @@ struct rb_root
|
||||
struct rb_node *rb_node;
|
||||
};
|
||||
|
||||
|
||||
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
|
||||
#define rb_color(r) ((r)->rb_parent_color & 1)
|
||||
#define rb_is_red(r) (!rb_color(r))
|
||||
@@ -45,24 +44,13 @@ struct rb_root
|
||||
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
|
||||
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
|
||||
|
||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
|
||||
}
|
||||
static inline void rb_set_color(struct rb_node *rb, int color)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
||||
}
|
||||
|
||||
void rb_insert_color(struct rb_node *, struct rb_root *);
|
||||
void rb_erase(struct rb_node *, struct rb_root *);
|
||||
|
||||
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
{
|
||||
node->rb_parent_color = (unsigned long )parent;
|
||||
node->rb_left = node->rb_right = NULL;
|
||||
|
||||
*rb_link = node;
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
void rb_link_node(struct rb_node *, struct rb_node *,
|
||||
struct rb_node **);
|
||||
#else
|
||||
inline void rb_link_node(struct rb_node *, struct rb_node *,
|
||||
struct rb_node **);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/* function written by Ben Taylor (found in the qemu-devel list) */
|
||||
|
||||
#include "../uwsgi.h"
|
||||
|
||||
time_t timegm(struct tm *t) {
|
||||
time_t tl, tb;
|
||||
struct tm *tg;
|
||||
|
||||
tl = mktime (t);
|
||||
if (tl == -1) {
|
||||
t->tm_hour--;
|
||||
tl = mktime (t);
|
||||
if (tl == -1)
|
||||
return -1; /* can't deal with output from strptime */
|
||||
|
||||
tl += 3600;
|
||||
}
|
||||
tg = gmtime (&tl);
|
||||
tg->tm_isdst = 0;
|
||||
tb = mktime (tg);
|
||||
if (tb == -1) {
|
||||
tg->tm_hour--;
|
||||
tb = mktime (tg);
|
||||
if (tb == -1)
|
||||
return -1; /* can't deal with output from gmtime */
|
||||
tb += 3600;
|
||||
}
|
||||
return (tl - (tb - tl));
|
||||
}
|
||||
@@ -1,199 +1,487 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
if (!uli) {
|
||||
uwsgi.registered_locks = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
|
||||
uwsgi.registered_locks->id = id;
|
||||
uwsgi.registered_locks->pid = 0;
|
||||
if (rw) {
|
||||
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
}
|
||||
else {
|
||||
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
|
||||
}
|
||||
uwsgi.registered_locks->rw = rw;
|
||||
uwsgi.registered_locks->next = NULL;
|
||||
return uwsgi.registered_locks;
|
||||
}
|
||||
|
||||
while(uli) {
|
||||
if (!uli->next) {
|
||||
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
|
||||
if (rw) {
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
|
||||
}
|
||||
else {
|
||||
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
|
||||
}
|
||||
uli->next->id = id;
|
||||
uli->next->pid = 0;
|
||||
uli->next->rw = rw;
|
||||
uli->next->next = NULL;
|
||||
return uli->next;
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
uwsgi_log("*** DANGER: unable to allocate lock %s ***\n", id);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_MUTEX
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
|
||||
#else
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
|
||||
#endif
|
||||
|
||||
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
|
||||
if (pthread_mutexattr_init(&attr)) {
|
||||
uwsgi_log("unable to allocate mutexattr structure\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
|
||||
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||||
uwsgi_log("unable to share mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
|
||||
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
uli->can_deadlock = 1;
|
||||
|
||||
return uli;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
#else
|
||||
|
||||
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_unlock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rlock(void *lock) {
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
}
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
|
||||
void uwsgi_wlock(void *lock) {
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
}
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
return uwsgi_lock_fast_init(uli);
|
||||
#else
|
||||
|
||||
void uwsgi_rwunlock(void *lock) {
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
}
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) {
|
||||
|
||||
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
|
||||
if (pthread_rwlockattr_init(&attr)) {
|
||||
uwsgi_log("unable to allocate rwlock structure\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
|
||||
|
||||
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
|
||||
uwsgi_log("unable to share rwlock\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
|
||||
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize rwlock\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_rwlockattr_destroy(&attr);
|
||||
|
||||
uli->can_deadlock = 1;
|
||||
|
||||
return uli;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#elif defined(UWSGI_LOCK_USE_UMTX)
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_UMTX
|
||||
/* Warning: FreeBSD is still not ready for process-shared UMTX */
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/umtx.h>
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
umtx_init((struct umtx*) lock);
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
umtx_init((struct umtx*) uli->lock_ptr);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
umtx_lock(lock, 1);
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
umtx_unlock(lock, 1);
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
|
||||
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
|
||||
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
|
||||
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
|
||||
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
memset(lock, 0, sizeof(OSSpinLock));
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
OSSpinLockLock((OSSpinLock *) lock);
|
||||
OSSpinLockLock((OSSpinLock *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
OSSpinLockUnlock((OSSpinLock *) lock);
|
||||
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (OSSpinLockTry((OSSpinLock *) uli->lock_ptr)) {
|
||||
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
#define uwsgi_lock_fast_check uwsgi_lock_ipcsem_check
|
||||
#define uwsgi_lock_fast uwsgi_lock_ipcsem
|
||||
#define uwsgi_unlock_fast uwsgi_unlock_ipcsem
|
||||
|
||||
#define uwsgi_rwlock_fast_init uwsgi_rwlock_ipcsem_init
|
||||
#define uwsgi_rwlock_fast_check uwsgi_rwlock_ipcsem_check
|
||||
|
||||
#define uwsgi_rlock_fast uwsgi_rlock_ipcsem
|
||||
#define uwsgi_wlock_fast uwsgi_wlock_ipcsem
|
||||
#define uwsgi_rwunlock_fast uwsgi_rwunlock_ipcsem
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(int)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(int)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
|
||||
|
||||
#define UWSGI_IPCSEM_ATEXIT 1
|
||||
|
||||
#endif
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_FLOCK
|
||||
// used by ftok
|
||||
static int counter = 1;
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
ushort *array;
|
||||
} semu ;
|
||||
int semid;
|
||||
key_t myKey;
|
||||
|
||||
#define UWSGI_LOCK_SIZE 8
|
||||
#define UWSGI_RWLOCK_SIZE 8
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
|
||||
static int lock_counter = 0;
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
semid = semget(myKey, 1, IPC_CREAT|0666);
|
||||
}
|
||||
else {
|
||||
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
|
||||
}
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
memcpy(uli->lock_ptr, &semid, sizeof(int));
|
||||
|
||||
char filename[17];
|
||||
|
||||
if (snprintf(filename, 17, ".uwsgiflock%d", lock_counter) < 0) {
|
||||
uwsgi_log("unable to create lock %d\n", lock_counter);
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(lock, &fd, sizeof(int));
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
int fd;
|
||||
memcpy(&fd, lock, sizeof(int));
|
||||
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
|
||||
int semid;
|
||||
struct sembuf sb;
|
||||
sb.sem_num = 0;
|
||||
sb.sem_op = -1;
|
||||
sb.sem_flg = SEM_UNDO;
|
||||
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
|
||||
if (semop(semid, &sb, 1)) {
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
int fd;
|
||||
memcpy(&fd, lock, sizeof(int));
|
||||
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
|
||||
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
|
||||
int semid;
|
||||
struct sembuf sb;
|
||||
sb.sem_num = 0;
|
||||
sb.sem_op = 1;
|
||||
sb.sem_flg = SEM_UNDO;
|
||||
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
|
||||
if (semop(semid, &sb, 1)) {
|
||||
uwsgi_error("semop()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
|
||||
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
|
||||
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
|
||||
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
|
||||
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
|
||||
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
|
||||
|
||||
// ipc cannot deadlock
|
||||
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers) goto clear;
|
||||
|
||||
if (uwsgi.mywid == 0) goto clear;
|
||||
|
||||
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
|
||||
|
||||
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
|
||||
|
||||
return;
|
||||
|
||||
clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
|
||||
|
||||
void *uwsgi_mmap_shared_lock() {
|
||||
void *addr = NULL;
|
||||
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
|
||||
if (addr == NULL) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
while(uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void *uwsgi_mmap_shared_rwlock() {
|
||||
void *addr = NULL;
|
||||
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
|
||||
if (addr == NULL) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
|
||||
|
||||
|
||||
void uwsgi_setup_locking() {
|
||||
|
||||
// use the fastest avaikable locking
|
||||
if (uwsgi.lock_engine) {
|
||||
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_log("lock engine: ipcsem\n");
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
|
||||
uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
|
||||
uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
|
||||
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
|
||||
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
|
||||
uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
|
||||
uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
|
||||
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
|
||||
uwsgi.lock_size = 8;
|
||||
uwsgi.rwlock_size = 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
#ifdef UWSGI_IPCSEM_ATEXIT
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
#endif
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
|
||||
uwsgi.lock_ops.lock = uwsgi_lock_fast;
|
||||
uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
|
||||
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
|
||||
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
|
||||
uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
|
||||
uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
|
||||
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
|
||||
uwsgi.lock_size = UWSGI_LOCK_SIZE;
|
||||
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fcntl_lock(int fd) {
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
int ret = fcntl(fd, F_SETLKW, &fl);
|
||||
if (ret < 0)
|
||||
uwsgi_error("fcntl()");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_fcntl_is_locked(int fd) {
|
||||
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_CUR;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
if (fcntl(fd, F_SETLK, &fl)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,97 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_check_logrotate(void) {
|
||||
|
||||
char message[1024];
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
|
||||
need_reopen = 1;
|
||||
}
|
||||
|
||||
if (need_rotation) {
|
||||
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) time(NULL));
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
else if (need_reopen) {
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) time(NULL), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// optimize this (please)
|
||||
@@ -44,22 +135,31 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
if (wsgi_req->do_not_log)
|
||||
return;
|
||||
|
||||
if (wsgi_req->app_id >= 0) {
|
||||
wi = &uwsgi.apps[wsgi_req->app_id];
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
if (wi->requests > 0) {
|
||||
app_req = wi->requests;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
via = msg1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
@@ -85,12 +185,9 @@ void log_request(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);
|
||||
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);
|
||||
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
|
||||
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
@@ -99,59 +196,40 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
|
||||
(int) uwsgi.mypid,
|
||||
wsgi_req->app_id,
|
||||
app_req,
|
||||
(unsigned long long ) uwsgi.workers[0].requests,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
|
||||
wsgi_req->remote_user_len, wsgi_req->remote_user,
|
||||
wsgi_req->var_cnt,
|
||||
wsgi_req->uh.pktsize,
|
||||
24, time_request,
|
||||
wsgi_req->method_len, wsgi_req->method,
|
||||
wsgi_req->uri_len, wsgi_req->uri,
|
||||
(unsigned long long) wsgi_req->response_size,
|
||||
rt, tsize,
|
||||
via,
|
||||
wsgi_req->protocol_len, wsgi_req->protocol,
|
||||
wsgi_req->status,
|
||||
wsgi_req->header_cnt,
|
||||
(unsigned long long) wsgi_req->headers_size,
|
||||
wsgi_req->switches, wsgi_req->async_id);
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
|
||||
logvec[logvecpos].iov_base = logpkt;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
|
||||
// do not check for errors
|
||||
rlen = writev(2, logvec, logvecpos+1);
|
||||
rlen = writev(2, logvec, logvecpos + 1);
|
||||
}
|
||||
|
||||
void get_memusage() {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
|
||||
*vsz = syscall(356);
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
|
||||
uwsgi_log("warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
|
||||
procfd = open("/proc/self/psinfo", O_RDONLY);
|
||||
if (procfd >= 0) {
|
||||
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
|
||||
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
*rss = (uint64_t) info.pr_rssize * 1024;
|
||||
*vsz = (uint64_t) info.pr_size * 1024;
|
||||
}
|
||||
close(procfd);
|
||||
}
|
||||
@@ -162,22 +240,28 @@ void get_memusage() {
|
||||
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
|
||||
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
|
||||
*rss = t_info.resident_size;
|
||||
*vsz = t_info.virtual_size;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
kvm_t *kv;
|
||||
int cnt;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
#else
|
||||
kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
|
||||
#endif
|
||||
if (kv) {
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kinfo_proc2 *kproc2;
|
||||
@@ -185,11 +269,11 @@ void get_memusage() {
|
||||
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
|
||||
if (kproc2 && cnt > 0) {
|
||||
#ifdef __OpenBSD__
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
#else
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
#endif
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -199,13 +283,58 @@ void get_memusage() {
|
||||
area_info ai;
|
||||
int32 cookie;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
|
||||
*vsz = 0;
|
||||
*rss = 0;
|
||||
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
*vsz += ai.ram_size;
|
||||
if ((ai.protection & B_WRITE_AREA) != 0) {
|
||||
*rss += ai.ram_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
|
||||
|
||||
if (!ul) {
|
||||
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
ul = uwsgi.loggers;
|
||||
}
|
||||
else {
|
||||
while (ul) {
|
||||
old_ul = ul;
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
old_ul->next = ul;
|
||||
}
|
||||
|
||||
ul->name = name;
|
||||
ul->func = func;
|
||||
ul->next = NULL;
|
||||
ul->configured = 0;
|
||||
ul->fd = -1;
|
||||
ul->data = NULL;
|
||||
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-logger] registered \"%s\"\n", ul->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_logger *uwsgi_get_logger(char *name) {
|
||||
struct uwsgi_logger *ul = uwsgi.loggers;
|
||||
|
||||
while (ul) {
|
||||
if (!strcmp(ul->name, name)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
[uwsgi]
|
||||
|
||||
for = 4031 14032 4033 14034 24035
|
||||
socket = /tmp/%(_)/uwsgi.sock
|
||||
socket = 192.*:%(_)
|
||||
print = ciao %(_) hello %(_) bye %(_)
|
||||
endfor =
|
||||
|
||||
|
||||
socket = :4045
|
||||
socket = :4046
|
||||
socket = :4047
|
||||
socket = :4048
|
||||
|
||||
|
||||
socket = :4049
|
||||
socket = :4050
|
||||
socket = :4051
|
||||
|
||||
show-config =
|
||||
|
||||
if-env = PIPPO
|
||||
print =
|
||||
print = PIPPO e' definita e il suo valore e' %(_) boh
|
||||
endif =
|
||||
|
||||
socket = :5051
|
||||
socket = :5052
|
||||
socket = :5053
|
||||
socket = :5054
|
||||
|
||||
if-exists = /etc/services
|
||||
print = il file %(_) esiste $(PATH)
|
||||
endif =
|
||||
|
||||
if-exists = /etc/foobar
|
||||
print = il file %(_) esiste $(PATH)
|
||||
endif =
|
||||
|
||||
socket = :6060
|
||||
if-file = /etc/fstab
|
||||
socket = :7171
|
||||
endif =
|
||||
|
||||
ifdir = /tmp
|
||||
print = %(_) is a directory
|
||||
endif=
|
||||
@@ -2,12 +2,16 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct wsgi_request* threaded_current_wsgi_req() { return pthread_getspecific(uwsgi.tur_key); }
|
||||
struct wsgi_request* simple_current_wsgi_req() { return uwsgi.wsgi_req; }
|
||||
struct wsgi_request *threaded_current_wsgi_req() {
|
||||
return pthread_getspecific(uwsgi.tur_key);
|
||||
}
|
||||
struct wsgi_request *simple_current_wsgi_req() {
|
||||
return uwsgi.wsgi_req;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_register_loop(char *name, void *loop) {
|
||||
|
||||
|
||||
if (uwsgi.loops_cnt >= MAX_LOOPS) {
|
||||
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
|
||||
exit(1);
|
||||
@@ -21,8 +25,8 @@ void uwsgi_register_loop(char *name, void *loop) {
|
||||
void *uwsgi_get_loop(char *name) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.loops_cnt;i++) {
|
||||
|
||||
for (i = 0; i < uwsgi.loops_cnt; i++) {
|
||||
if (!strcmp(name, uwsgi.loops[i].name)) {
|
||||
return uwsgi.loops[i].loop;
|
||||
}
|
||||
@@ -36,54 +40,208 @@ void *simple_loop(void *arg1) {
|
||||
long core_id = (long) arg1;
|
||||
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
|
||||
int i;
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
int i;
|
||||
//PyThreadState *pts;
|
||||
sigset_t smask;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
|
||||
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
|
||||
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for(i=0;i<0xFF;i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
}
|
||||
/*
|
||||
pts = PyThreadState_New(uwsgi.main_thread->interp);
|
||||
pthread_setspecific(uwsgi.ut_save_key, (void *) pts);
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize the main event queue to monitor sockets
|
||||
int main_queue = event_queue_init();
|
||||
|
||||
uwsgi_add_sockets_to_queue(main_queue);
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
|
||||
event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
|
||||
}
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
wsgi_req_setup(wsgi_req, core_id, NULL);
|
||||
|
||||
UWSGI_CLEAR_STATUS;
|
||||
|
||||
|
||||
wsgi_req_setup(wsgi_req, core_id);
|
||||
|
||||
if (wsgi_req_accept(wsgi_req)) {
|
||||
if (wsgi_req_accept(main_queue, wsgi_req)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wsgi_req_recv(wsgi_req)) {
|
||||
uwsgi_destroy_request(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
|
||||
uwsgi_close_request(wsgi_req);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
|
||||
//never here
|
||||
// end of the loop
|
||||
if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
|
||||
#ifdef __APPLE__
|
||||
kill(uwsgi.workers[0].pid, SIGTERM);
|
||||
#else
|
||||
if (uwsgi.propagate_touch) {
|
||||
kill(uwsgi.workers[0].pid, SIGHUP);
|
||||
}
|
||||
else {
|
||||
gracefully_kill(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
void *zeromq_loop(void *arg1) {
|
||||
sigset_t smask;
|
||||
int i;
|
||||
|
||||
long core_id = (long) arg1;
|
||||
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
|
||||
uwsgi.zeromq_recv_flag = 0;
|
||||
zmq_pollitem_t zmq_poll_items[3];
|
||||
char uwsgi_signal;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
|
||||
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
|
||||
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
zmq_poll_items[0].socket = pthread_getspecific(uwsgi.zmq_pull);
|
||||
zmq_poll_items[0].fd = -1;
|
||||
zmq_poll_items[0].events = ZMQ_POLLIN;
|
||||
|
||||
zmq_poll_items[1].socket = NULL;
|
||||
zmq_poll_items[1].fd = uwsgi.signal_socket;
|
||||
zmq_poll_items[1].events = ZMQ_POLLIN;
|
||||
|
||||
zmq_poll_items[2].socket = NULL;
|
||||
zmq_poll_items[2].fd = uwsgi.my_signal_socket;
|
||||
zmq_poll_items[2].events = ZMQ_POLLIN;
|
||||
}
|
||||
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
wsgi_req_setup(wsgi_req, core_id, NULL);
|
||||
|
||||
uwsgi.edge_triggered = 1;
|
||||
wsgi_req->socket = uwsgi.zmq_socket;
|
||||
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
|
||||
uwsgi_error("zmq_poll()");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (zmq_poll_items[0].revents & ZMQ_POLLIN) {
|
||||
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
|
||||
}
|
||||
|
||||
if (wsgi_req->poll.fd >= 0) {
|
||||
wsgi_req_recv(wsgi_req);
|
||||
}
|
||||
|
||||
uwsgi_close_request(wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
// end of the loop
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
+829
@@ -0,0 +1,829 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void worker_wakeup() {
|
||||
}
|
||||
|
||||
int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
needed_workers--;
|
||||
}
|
||||
if (needed_workers == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (needed_workers < 0) {
|
||||
int oldest_worker = 0;
|
||||
time_t oldest_worker_spawn = INT_MAX;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
|
||||
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
|
||||
oldest_worker = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldest_worker > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("worker %d should die...\n", oldest_worker);
|
||||
#endif
|
||||
uwsgi.workers[oldest_worker].cheaped = 1;
|
||||
uwsgi.workers[oldest_worker].manage_next_request = 0;
|
||||
// wakeup task in case of wait
|
||||
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
|
||||
|
||||
when all of the workers are busy, the overload_count is incremented.
|
||||
as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
|
||||
at most cheaper_step (default to 1) new workers are spawned.
|
||||
|
||||
when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
|
||||
If overload_count reaches 0, the system will count active workers (the ones uncheaped) and busy workers (the ones running a request)
|
||||
if there is exacly 1 free worker we are in "stable state" (1 spare worker available). no worker will be touched.
|
||||
if the number of active workers is higher than uwsgi.cheaper_count and at least uwsgi.cheaper_overload cycles are passed from the last
|
||||
"cheap it" procedure, then cheap a worker.
|
||||
|
||||
Example:
|
||||
10 processes
|
||||
2 cheaper
|
||||
2 cheaper step
|
||||
3 cheaper_overload
|
||||
1 second master cycle
|
||||
|
||||
there are 7 workers running (triggered by some kind of spike activity).
|
||||
Of this, 6 are busy, 1 is free. We are in stable state.
|
||||
After a bit the spike disappear and idle_count start to increase.
|
||||
|
||||
After 3 seconds (uwsgi.cheaper_overload cycles) the oldest worker will be cheaped. This will happens
|
||||
every seconds (uwsgi.cheaper_overload cycles) til the number of workers is == uwsgi.cheaper_count.
|
||||
|
||||
If during the "cheap them all" procedure, an overload condition come again (another spike) the "cheap them all"
|
||||
will be interrupted.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int uwsgi_cheaper_algo_spare(void) {
|
||||
|
||||
int i;
|
||||
static uint64_t overload_count = 0;
|
||||
static uint64_t idle_count = 0;
|
||||
|
||||
// step 1 -> count the number of busy workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
|
||||
if (uwsgi.workers[i].busy == 0) {
|
||||
if (overload_count > 0)
|
||||
overload_count--;
|
||||
goto healthy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overload_count++;
|
||||
idle_count = 0;
|
||||
|
||||
healthy:
|
||||
|
||||
// are we overloaded ?
|
||||
if (overload_count > uwsgi.cheaper_overload) {
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("overloaded !!!\n");
|
||||
#endif
|
||||
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// reset overload
|
||||
overload_count = 0;
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
}
|
||||
// we are no more overloaded
|
||||
else if (overload_count == 0) {
|
||||
// how many active workers ?
|
||||
int active_workers = 0;
|
||||
int busy_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
if (uwsgi.workers[i].busy == 1)
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("active workers %d busy_workers %d\n", active_workers, busy_workers);
|
||||
#endif
|
||||
|
||||
// special condition: uwsgi.cheaper running workers and 1 free
|
||||
if (active_workers > busy_workers && active_workers - busy_workers == 1) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("stable status: 1 spare worker\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
idle_count++;
|
||||
|
||||
if (active_workers > uwsgi.cheaper_count && idle_count % uwsgi.cheaper_overload == 0) {
|
||||
// we are in "cheap them all"
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, backlog algorithm (supported only on Linux) --
|
||||
|
||||
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
|
||||
Decrese when lower.
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_cheaper_algo_backlog(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->ti.tcpi_unacked;
|
||||
#else
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int)uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
|
||||
}
|
||||
else if (backlog < (int) uwsgi.cheaper_overload) {
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_workers > uwsgi.cheaper_count) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// reload uWSGI, close unneded file descriptor, restore the original environment and re-exec the binary
|
||||
|
||||
void uwsgi_reload(char **argv) {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
int found = 0;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (i == uwsgi_sock->fd) {
|
||||
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (uwsgi.has_emperor) {
|
||||
if (i == uwsgi.emperor_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (i == uwsgi.original_log_fd) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[0]) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_log_pipe[1] > -1) {
|
||||
if (i == uwsgi.shared->worker_log_pipe[1]) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
#ifdef __APPLE__
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
#else
|
||||
close(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
return;
|
||||
#else
|
||||
uwsgi_log("running %s\n", uwsgi.binary_path);
|
||||
uwsgi_flush_logs();
|
||||
argv[0] = uwsgi.binary_path;
|
||||
//strcpy (argv[0], uwsgi.binary_path);
|
||||
if (uwsgi.log_master) {
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
dup2(uwsgi.original_log_fd, 1);
|
||||
dup2(1, 2);
|
||||
}
|
||||
if (uwsgi.shared->worker_log_pipe[0] > -1) {
|
||||
close(uwsgi.shared->worker_log_pipe[0]);
|
||||
}
|
||||
if (uwsgi.shared->worker_log_pipe[1] > -1) {
|
||||
close(uwsgi.shared->worker_log_pipe[1]);
|
||||
}
|
||||
}
|
||||
execvp(uwsgi.binary_path, argv);
|
||||
uwsgi_error("execvp()");
|
||||
// never here
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void master_check_cluster_nodes() {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
|
||||
|
||||
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
|
||||
// should i retry ?
|
||||
if (uwsgi.master_cycles % ucn->errors == 0) {
|
||||
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
|
||||
ucn->status = UWSGI_NODE_OK;
|
||||
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
|
||||
}
|
||||
else {
|
||||
ucn->errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
|
||||
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
|
||||
if ((uwsgi.current_time - ucn->last_seen) > 30) {
|
||||
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
|
||||
ucn->name[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
|
||||
int i;
|
||||
|
||||
// close the cache server
|
||||
if (uwsgi.cache_server_fd != -1) {
|
||||
close(uwsgi.cache_server_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.master_queue > -1)
|
||||
close(uwsgi.master_queue);
|
||||
// close gateways
|
||||
if (!ug) {
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
close(ushared->gateways[i].internal_subscription_pipe[0]);
|
||||
close(ushared->gateways[i].internal_subscription_pipe[1]);
|
||||
}
|
||||
}
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (ug && !strcmp(ug->name, ugs->owner)) {
|
||||
ugs = ugs->next;
|
||||
continue;
|
||||
}
|
||||
// do not close shared sockets !!!
|
||||
if (!ugs->shared) {
|
||||
close(ugs->fd);
|
||||
}
|
||||
ugs = ugs->next;
|
||||
}
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.workers[i].signal_pipe[0]);
|
||||
if (i != wid) {
|
||||
if (uwsgi.workers[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.workers[i].signal_pipe[1]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[0]);
|
||||
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->spooler_signal_pipe[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1)
|
||||
close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.shared->mule_signal_pipe[1] != -1)
|
||||
close(uwsgi.shared->mule_signal_pipe[1]);
|
||||
if (uwsgi.shared->mule_queue_pipe[1] != -1)
|
||||
close(uwsgi.shared->mule_queue_pipe[1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.mules[i].signal_pipe[0]);
|
||||
if (muleid != i + 1) {
|
||||
if (uwsgi.mules[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.mules[i].signal_pipe[1]);
|
||||
if (uwsgi.mules[i].queue_pipe[1] != -1)
|
||||
close(uwsgi.mules[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.farms_cnt; i++) {
|
||||
if (uwsgi.farms[i].signal_pipe[0] != -1)
|
||||
close(uwsgi.farms[i].signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.farms[i].signal_pipe[1] != -1)
|
||||
close(uwsgi.farms[i].signal_pipe[1]);
|
||||
if (uwsgi.farms[i].queue_pipe[1] != -1)
|
||||
close(uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
int i;
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
|
||||
|
||||
if (pid == 0) {
|
||||
signal(SIGWINCH, worker_wakeup);
|
||||
signal(SIGTSTP, worker_wakeup);
|
||||
uwsgi.mywid = wid;
|
||||
uwsgi.mypid = getpid();
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
// do not reset worker counters on reload !!!
|
||||
//uwsgi.workers[uwsgi.mywid].requests = 0;
|
||||
// ...but maintain a delta counter (yes this is racy in multithread)
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
|
||||
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
|
||||
uwsgi.workers[uwsgi.mywid].respawn_count++;
|
||||
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
|
||||
uwsgi.workers[uwsgi.mywid].cheaped = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].suspended = 0;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
|
||||
// reset the apps count with a copy from the master
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
|
||||
uwsgi_fixup_fds(wid, 0, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (pid < 1) {
|
||||
uwsgi_error("fork()");
|
||||
}
|
||||
else {
|
||||
if (respawns > 0) {
|
||||
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_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 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;
|
||||
|
||||
if (ucron->minute == -1)
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
if (ucron->hour == -1)
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (ucron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (ucron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day != -1 && ucron->week != -1) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (current_cron->minute == -1)
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
if (current_cron->hour == -1)
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (current_cron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (current_cron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day != -1 && current_cron->week != -1) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
|
||||
#define stats_send(x, y) fprintf(output, x, y)
|
||||
|
||||
void uwsgi_send_stats(int fd) {
|
||||
|
||||
int i, j;
|
||||
struct sockaddr_un client_src;
|
||||
struct uwsgi_app *ua;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *output = fdopen(client_fd, "w");
|
||||
if (!output) {
|
||||
uwsgi_error("fdopen()");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
#ifdef __linux__
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
|
||||
#endif
|
||||
|
||||
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
|
||||
|
||||
fprintf(output, "\"pid\": %d,\n", (int) (getpid()));
|
||||
fprintf(output, "\"uid\": %d,\n", (int) (getuid()));
|
||||
fprintf(output, "\"gid\": %d,\n", (int) (getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
if (uwsgi.daemons) {
|
||||
fprintf(output, "\"daemons\": [\n");
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }", ud->command, (int) ud->pid, (unsigned long long) ud->respawns - 1);
|
||||
if (ud->next)
|
||||
fprintf(output, ",\n");
|
||||
else {
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
fprintf(output, "],\n");
|
||||
}
|
||||
|
||||
fprintf(output, "\"locks\": [\n");
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
while (uli) {
|
||||
if (uli->next) {
|
||||
fprintf(output, "\t{ \"%s\": %d },\n", uli->id, (int) uli->pid);
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\t{ \"%s\": %d }\n", uli->id, (int) uli->pid);
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
fprintf(output, "],\n");
|
||||
|
||||
fprintf(output, "\"workers\": [\n");
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
fprintf(output, "\t{");
|
||||
|
||||
fprintf(output, "\"id\": %d, ", uwsgi.workers[i + 1].id);
|
||||
fprintf(output, "\"pid\": %d, ", (int) uwsgi.workers[i + 1].pid);
|
||||
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i + 1].requests);
|
||||
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
|
||||
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output, "\"status\": \"cheap\", ");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output, "\"status\": \"pause\", ");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
fprintf(output, "\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
fprintf(output, "\"status\": \"busy\", ");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\"status\": \"idle\", ");
|
||||
}
|
||||
}
|
||||
|
||||
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i + 1].rss_size);
|
||||
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i + 1].vsz_size);
|
||||
|
||||
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i + 1].running_time);
|
||||
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i + 1].last_spawn);
|
||||
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i + 1].respawn_count);
|
||||
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i + 1].tx);
|
||||
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i + 1].avg_response_time);
|
||||
|
||||
fprintf(output, "\"apps\": [\n");
|
||||
|
||||
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
|
||||
ua = &uwsgi.workers[i + 1].apps[j];
|
||||
fprintf(output, "\t\t{ ");
|
||||
|
||||
fprintf(output, "\"id\": %d, ", j);
|
||||
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
|
||||
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
|
||||
|
||||
|
||||
stats_send_llu("\"startup_time\": %llu, ", ua->startup_time);
|
||||
|
||||
stats_send_llu("\"requests\": %llu, ", ua->requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", ua->exceptions);
|
||||
|
||||
if (ua->chdir) {
|
||||
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\"chdir\": \"\" ");
|
||||
}
|
||||
|
||||
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output, "\t\t]");
|
||||
|
||||
if (i == uwsgi.numproc - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output, "]}\n");
|
||||
fclose(output);
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int(*func) (void)) {
|
||||
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
|
||||
if (!uca) {
|
||||
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
|
||||
uca = uwsgi.cheaper_algos;
|
||||
}
|
||||
else {
|
||||
while (uca) {
|
||||
if (!uca->next) {
|
||||
uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
|
||||
uca = uca->next;
|
||||
break;
|
||||
}
|
||||
uca = uca->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uca->name = name;
|
||||
uca->func = func;
|
||||
uca->next = NULL;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -19,4 +19,8 @@
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
</uwsgi>
|
||||
|
||||
<uwsgi>
|
||||
<socket>:3031</socket>
|
||||
</uwsgi>
|
||||
|
||||
</unbit>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
main = Server(
|
||||
uuid="f400bf85-4538-4f7a-8908-67e313d515c2",
|
||||
access_log="/logs/access.log",
|
||||
error_log="/logs/error.log",
|
||||
chroot="./",
|
||||
default_host="192.168.173.18",
|
||||
name="test",
|
||||
pid_file="/run/mongrel2.pid",
|
||||
port=6767,
|
||||
hosts = [
|
||||
Host(name="192.168.173.18", routes={
|
||||
'/': Handler(send_spec='tcp://192.168.173.18:9999',
|
||||
send_ident='54c6755b-9628-40a4-9a2d-cc82a816345e',
|
||||
recv_spec='tcp://192.168.173.18:9998', recv_ident='')
|
||||
})
|
||||
]
|
||||
)
|
||||
|
||||
settings = {'upload.temp_store':'tmp/mongrel2.upload.XXXXXX'}
|
||||
servers = [main]
|
||||
|
||||
|
||||
uwsgi = { 'socket':':3031', 'master':'true'}
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
|
||||
uWSGI mules are very simple workers only managing signals or running custom code in background.
|
||||
|
||||
By default they born in signal-only mode, but if you patch them (passing the script/code to run) they will became fully customized daemons.
|
||||
|
||||
*/
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_mule_handler(void);
|
||||
|
||||
void mule_send_msg(int fd, char *message, size_t len) {
|
||||
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
int so_bufsize = 0;
|
||||
|
||||
if (write(fd, message, len) != (ssize_t) len) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("getsockopt()");
|
||||
}
|
||||
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("mule_send_msg()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
|
||||
if (pid == 0) {
|
||||
uwsgi.muleid = id;
|
||||
// avoid race conditions
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = getpid();
|
||||
|
||||
uwsgi_fixup_fds(0, id, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
|
||||
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
|
||||
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_mule_handler();
|
||||
}
|
||||
else if (pid > 0) {
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = pid;
|
||||
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
|
||||
while(umf) {
|
||||
if (umf->mule->id == muleid) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_signaled(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_msg(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_mule_add_farm_to_queue(int queue) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_handler() {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t uwsgi_signal;
|
||||
int rlen;
|
||||
int interesting_fd;
|
||||
|
||||
// this must be configurable
|
||||
char message[65536];
|
||||
|
||||
int mule_queue = event_queue_init();
|
||||
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
|
||||
|
||||
uwsgi_mule_add_farm_to_queue(mule_queue);
|
||||
|
||||
for(;;) {
|
||||
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
|
||||
if (rlen <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
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.muleid);
|
||||
}
|
||||
}
|
||||
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()");
|
||||
}
|
||||
else {
|
||||
int i,found = 0;
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->mule_msg) {
|
||||
if (uwsgi.p[i]->mule_msg(message, len)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_mule *get_mule_by_id(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].id == id) {
|
||||
return &uwsgi.mules[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_farm *get_farm_by_name(char *name) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (!strcmp(uwsgi.farms[i].name, name)) {
|
||||
return &uwsgi.farms[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
|
||||
|
||||
if (!uwsgi_mf) {
|
||||
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
uwsgi_mf = *umf;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_mf) {
|
||||
old_umf = uwsgi_mf;
|
||||
uwsgi_mf = uwsgi_mf->next;
|
||||
}
|
||||
|
||||
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
old_umf->next = uwsgi_mf;
|
||||
}
|
||||
|
||||
uwsgi_mf->mule = um;
|
||||
uwsgi_mf->next = NULL;
|
||||
|
||||
return uwsgi_mf;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
|
||||
|
||||
ssize_t len = 0;
|
||||
struct pollfd *mulepoll;
|
||||
int count = 4;
|
||||
int farms_count = 0;
|
||||
uint8_t uwsgi_signal;
|
||||
int i;
|
||||
|
||||
if (uwsgi.muleid == 0) return -1;
|
||||
|
||||
if (manage_signals) count = 2;
|
||||
|
||||
if (!manage_farms) goto next;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
|
||||
}
|
||||
next:
|
||||
|
||||
if (timeout > -1) timeout = timeout*1000;
|
||||
|
||||
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
|
||||
|
||||
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
|
||||
mulepoll[0].events = POLLIN;
|
||||
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
|
||||
mulepoll[1].events = POLLIN;
|
||||
if (count > 2) {
|
||||
mulepoll[2].fd = uwsgi.signal_socket;
|
||||
mulepoll[2].events = POLLIN;
|
||||
mulepoll[3].fd = uwsgi.my_signal_socket;
|
||||
mulepoll[3].events = POLLIN;
|
||||
}
|
||||
|
||||
if (farms_count > 0) {
|
||||
int tmp_cnt = 0;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
|
||||
mulepoll[count+tmp_cnt].events = POLLIN;
|
||||
tmp_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count+farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
}
|
||||
else {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else if (mulepoll[1].revents & POLLIN) {
|
||||
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else {
|
||||
if (count > 2) {
|
||||
int interesting_fd = -1;
|
||||
if (mulepoll[2].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[2].fd;
|
||||
}
|
||||
else if (mulepoll[3].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[3].fd;
|
||||
}
|
||||
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
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);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
// read messages in the farm
|
||||
for(i=0;i<farms_count;i++) {
|
||||
if (mulepoll[count+i].revents & POLLIN) {
|
||||
len = read(mulepoll[count+i].fd, message, buffer_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
clear:
|
||||
free(mulepoll);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.mules_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.mules_patches, value);
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
|
||||
int i;
|
||||
|
||||
for(i=0;i<atoi(value);i++) {
|
||||
uwsgi.mules_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
|
||||
uwsgi.farms_cnt++;
|
||||
uwsgi_string_new_list(&uwsgi.farms_list, value);
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from uwsgidecorators import *
|
||||
|
||||
@timer(3, target='mule1')
|
||||
def hello_timer(signum):
|
||||
print "3 seconds elapsed"
|
||||
|
||||
|
||||
@mulefunc
|
||||
def conto_fino_a_dieci(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_dieci" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc(2)
|
||||
def conto_fino_a_venti(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_venti" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc('topogigio')
|
||||
def conto_fino_a_trenta(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_trenta" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
|
||||
|
||||
def application(e, sr):
|
||||
conto_fino_a_dieci(1,2,3)
|
||||
conto_fino_a_venti(4,5,6)
|
||||
conto_fino_a_trenta(7,8,9)
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
return "MULE !!!"
|
||||
@@ -1,5 +1,14 @@
|
||||
<uwsgi>
|
||||
|
||||
<!--
|
||||
|
||||
DO NOT USE <app> TAG !!!
|
||||
|
||||
It is deprecated and will be removed from 1.2
|
||||
|
||||
-->
|
||||
|
||||
<plugins>psgi</plugins>
|
||||
<plugins>rack</plugins>
|
||||
|
||||
<http>:9090</http>
|
||||
@@ -24,6 +33,8 @@
|
||||
<module>werkzeug.testapp:test_app</module>
|
||||
</app>
|
||||
|
||||
<app mountpoint="/foobar">werkzeug.testapp:test_app</app>
|
||||
|
||||
<app mountpoint="/trac">
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
</app>
|
||||
@@ -32,11 +43,12 @@
|
||||
<module>werkzeug.testapp:test_app</module>
|
||||
</app>
|
||||
|
||||
<!-- eval is broken -->
|
||||
<app mountpoint="/bzr">
|
||||
<eval>
|
||||
<eval>
|
||||
from bzrlib.transport.http import wsgi
|
||||
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
|
||||
</eval>
|
||||
</eval>
|
||||
</app>
|
||||
|
||||
<app domain="sirius002:9090">
|
||||
@@ -47,4 +59,8 @@ application = wsgi.make_app("mybzr", "/bzr", readonly=False)
|
||||
<rack>config2.ru</rack>
|
||||
</app>
|
||||
|
||||
<app mountpoint="precise64.local">
|
||||
<psgi>test.psgi</psgi>
|
||||
</app>
|
||||
|
||||
</uwsgi>
|
||||
|
||||
+3
-8
@@ -1,14 +1,9 @@
|
||||
import werkzeug
|
||||
|
||||
def web3_app(environ):
|
||||
status = b'200 OK'
|
||||
headers = [(b'Content-type', b'text/plain')]
|
||||
body = [b'I am a Web3 app\n']
|
||||
return body, status, headers
|
||||
import uwsgi
|
||||
|
||||
def zero_app(e,s):
|
||||
s('200 OK', [ ('Content-Type', 'text/plain') ])
|
||||
return ""
|
||||
return "0"
|
||||
|
||||
def not_found(e,s):
|
||||
s('404 Not Found', [ ('Content-Type', 'text/plain') ])
|
||||
@@ -24,4 +19,4 @@ def internal_server_error(e, s):
|
||||
s('500 Internal Server Error', [ ('Content-Type', 'text/plain') ])
|
||||
return ""
|
||||
|
||||
applications = {'':web3_app, '/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
|
||||
uwsgi.applications = {'/wsgi':wsgi_app, '/test':werkzeug.test_app, '/zero':zero_app, '/notfound':not_found, '/ise':internal_server_error}
|
||||
|
||||
+11
-1
@@ -2,6 +2,16 @@ import uwsgi
|
||||
import struct
|
||||
import sys
|
||||
|
||||
print sys.argv
|
||||
if len(sys.argv) == 3:
|
||||
chunks = uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), '')
|
||||
|
||||
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
|
||||
pkt = ''
|
||||
|
||||
for chunk in chunks:
|
||||
pkt += chunk
|
||||
|
||||
print "%d = %d" % (int(sys.argv[2]), struct.unpack("I", pkt)[0])
|
||||
elif len(sys.argv) == 4:
|
||||
uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), struct.pack("I", int(sys.argv[3])))
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
|
||||
void uwsgi_systemd_notify(char *message) {
|
||||
|
||||
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
|
||||
struct iovec *iovec = msghdr->msg_iov;
|
||||
|
||||
iovec[0].iov_base = "STATUS=";
|
||||
iovec[0].iov_len = 7;
|
||||
|
||||
iovec[1].iov_base = message;
|
||||
iovec[1].iov_len = strlen(message);
|
||||
|
||||
iovec[2].iov_base = "\n";
|
||||
iovec[2].iov_len = 1;
|
||||
|
||||
msghdr->msg_iovlen = 3;
|
||||
|
||||
sendmsg(uwsgi.notification_fd, msghdr, 0);
|
||||
}
|
||||
|
||||
void uwsgi_systemd_notify_ready(void) {
|
||||
|
||||
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
|
||||
struct iovec *iovec = msghdr->msg_iov;
|
||||
|
||||
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
|
||||
iovec[0].iov_len = 30;
|
||||
|
||||
msghdr->msg_iovlen = 1;
|
||||
|
||||
sendmsg(uwsgi.notification_fd, msghdr, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_systemd_init(char *systemd_socket) {
|
||||
|
||||
struct sockaddr_un *sd_sun;
|
||||
struct msghdr *msghdr;
|
||||
|
||||
uwsgi.notification_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (uwsgi.notification_fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
|
||||
memset(sd_sun, 0, sizeof(struct sockaddr_un));
|
||||
sd_sun->sun_family = AF_UNIX;
|
||||
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
|
||||
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
|
||||
|
||||
msghdr = uwsgi_malloc(sizeof(struct msghdr));
|
||||
memset(msghdr, 0, sizeof(struct msghdr));
|
||||
|
||||
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
|
||||
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
|
||||
|
||||
msghdr->msg_name = sd_sun;
|
||||
msghdr->msg_namelen = sizeof(struct sockaddr_un);
|
||||
|
||||
uwsgi.notification_object = msghdr;
|
||||
|
||||
uwsgi.notify = uwsgi_systemd_notify;
|
||||
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
|
||||
|
||||
}
|
||||
@@ -2,63 +2,202 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void embed_plugins() {
|
||||
static int plugin_already_loaded(const char *plugin) {
|
||||
int i;
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_PSGI
|
||||
if (uwsgi.plugin_arg_psgi)
|
||||
uwsgi_load_plugin(5, "psgi_plugin.so", uwsgi.plugin_arg_psgi, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_LUA
|
||||
if (uwsgi.plugin_arg_lua)
|
||||
uwsgi_load_plugin(6, "lua_plugin.so", uwsgi.plugin_arg_lua, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_RACK
|
||||
if (uwsgi.plugin_arg_rack)
|
||||
uwsgi_load_plugin(7, "rack_plugin.so", uwsgi.plugin_arg_rack, 0);
|
||||
for(i=0;i<uwsgi.gp_cnt;i++) {
|
||||
|
||||
if (uwsgi.gp[i]->name) {
|
||||
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) {
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
|
||||
int need_free = 0;
|
||||
char *plugin_name = plugin;
|
||||
char *plugin_symbol_name_start = plugin;
|
||||
|
||||
void *plugin_handle;
|
||||
|
||||
char *plugin_name;
|
||||
char *plugin_entry_symbol;
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
|
||||
if (absolute) {
|
||||
plugin_name = malloc(strlen(plugin) + 1);
|
||||
memcpy(plugin_name, plugin, strlen(plugin) + 1);
|
||||
}
|
||||
else {
|
||||
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
|
||||
char *colon = strchr(plugin_name, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
modifier = atoi(plugin_name);
|
||||
plugin_name = colon+1;
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
|
||||
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
|
||||
need_free = 1;
|
||||
}
|
||||
|
||||
plugin_symbol_name_start = plugin_name;
|
||||
|
||||
// step 1: check for absolute plugin (stop if it fails)
|
||||
if (strchr(plugin_name, '/')) {
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
goto end;
|
||||
}
|
||||
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
|
||||
plugin_symbol_name_start++;
|
||||
}
|
||||
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
char *plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (plugin_handle) {
|
||||
free(plugin_filename);
|
||||
break;
|
||||
}
|
||||
free(plugin_filename);
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
if (!plugin_handle) {
|
||||
char *plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
free(plugin_filename);
|
||||
}
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
free(plugin_name);
|
||||
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
|
||||
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
if (!up) {
|
||||
// is it a link ?
|
||||
memset(linkpath_buf, 0, 1024);
|
||||
memset(linkpath, 0, 1024);
|
||||
if ((linkpath_size = readlink(plugin_name, linkpath_buf, 1023)) > 0) {
|
||||
do {
|
||||
linkpath_buf[linkpath_size] = '\0';
|
||||
strncpy(linkpath, linkpath_buf, linkpath_size+1);
|
||||
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", linkpath);
|
||||
#endif
|
||||
free(plugin_entry_symbol);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
char *slash = uwsgi_get_last_char(linkpath, '/');
|
||||
if (!slash) {
|
||||
slash = linkpath;
|
||||
}
|
||||
else {
|
||||
slash++;
|
||||
}
|
||||
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
}
|
||||
}
|
||||
if (up) {
|
||||
if (!up->name) {
|
||||
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (plugin_already_loaded(up->name)) {
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (has_option) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
int found = 0;
|
||||
while (op && op->name) {
|
||||
if (!strcmp(has_option, op->name)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
if (!found) {
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
if (modifier != -1) {
|
||||
fill_plugin_table(modifier, up);
|
||||
}
|
||||
else {
|
||||
fill_plugin_table(up->modifier1, up);
|
||||
}
|
||||
return 1;
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
|
||||
if (up->on_load)
|
||||
up->on_load();
|
||||
return plugin_handle;
|
||||
}
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
|
||||
return 0;
|
||||
end:
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,58 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* uwsgi ADMIN|10 */
|
||||
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint32_t opt_value = 0;
|
||||
int i;
|
||||
ssize_t len;
|
||||
|
||||
if (wsgi_req->uh.pktsize >= 4) {
|
||||
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
|
||||
return UWSGI_OK;
|
||||
|
||||
// write request
|
||||
if (wsgi_req->uh.pktsize == 4) {
|
||||
memcpy(&opt_value, wsgi_req->buffer, 4);
|
||||
// TODO: check endianess ?
|
||||
}
|
||||
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
|
||||
i = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (i != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
// get request
|
||||
else {
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
|
||||
|
||||
wsgi_req->uh.modifier1 = 10;
|
||||
wsgi_req->uh.pktsize = 4;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin admin_plugin = {
|
||||
|
||||
.name = "admin",
|
||||
.modifier1 = 10,
|
||||
.request = uwsgi_request_admin,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='admin'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['admin_plugin']
|
||||
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
|
||||
uint64_t tmp_vallen = 0;
|
||||
|
||||
if (vallen > 0) {
|
||||
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && tmp_vallen > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cache value size: %llu\n", tmp_vallen);
|
||||
#endif
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
|
||||
}
|
||||
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
|
||||
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
|
||||
if (val && vallen > 0) {
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
|
||||
}
|
||||
else {
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint64_t vallen = 0;
|
||||
char *value;
|
||||
char *argv[3];
|
||||
uint16_t argvs[3];
|
||||
uint8_t argc = 0;
|
||||
|
||||
switch(wsgi_req->uh.modifier2) {
|
||||
case 0:
|
||||
// get
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = vallen;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// set
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
argc = 3;
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
|
||||
if (argc > 1) {
|
||||
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// del
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// dict
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// get (uwsgi + stream)
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh.pktsize, &vallen);
|
||||
if (value && vallen > 0) {
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, vallen);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 0;
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cache_plugin = {
|
||||
|
||||
.name = "cache",
|
||||
.modifier1 = 111,
|
||||
.request = uwsgi_cache_request,
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
NAME='proxy'
|
||||
NAME='cache'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['proxy']
|
||||
GCC_LIST = ['cache']
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_carbon {
|
||||
struct uwsgi_string_list *servers;
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
} u_carbon;
|
||||
|
||||
struct uwsgi_option carbon_options[] = {
|
||||
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
|
||||
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
|
||||
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
|
||||
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
void carbon_post_init() {
|
||||
|
||||
int i;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
if (!uwsgi.sockets) return;
|
||||
if (!u_carbon.servers) return;
|
||||
|
||||
while(usl) {
|
||||
uwsgi_log("added carbon server %s\n", usl->value);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (u_carbon.freq < 1) u_carbon.freq = 60;
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
if (u_carbon.id[i] == '.') u_carbon.id[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void carbon_master_cycle() {
|
||||
|
||||
static time_t last_update = 0;
|
||||
char ptr[4096];
|
||||
int rlen, i;
|
||||
int fd;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
|
||||
if (!u_carbon.servers) return ;
|
||||
|
||||
if (last_update == 0) last_update = time(NULL);
|
||||
|
||||
// update
|
||||
if (uwsgi.current_time - last_update >= u_carbon.freq) {
|
||||
while(usl) {
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
if (fd < 0) goto nxt;
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
unsigned long long total_rss = 0;
|
||||
unsigned long long total_vsz = 0;
|
||||
unsigned long long total_tx = 0;
|
||||
unsigned long long total_avg_rt = 0; // total avg_rt
|
||||
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
|
||||
unsigned long long avg_rt_workers = 0; // number of workers used to calculate total avg_rt
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
total_vsz += uwsgi.workers[i].vsz_size;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
if (uwsgi.workers[i].cheaped) {
|
||||
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
|
||||
avg_rt = 0;
|
||||
}
|
||||
else {
|
||||
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
|
||||
avg_rt = uwsgi.workers[i].avg_response_time;
|
||||
avg_rt_workers++;
|
||||
total_avg_rt += uwsgi.workers[i].avg_response_time;
|
||||
}
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
total_tx += uwsgi.workers[i].tx;
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (avg_rt_workers ? total_avg_rt / avg_rt_workers : 0), (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
usl = usl->next;
|
||||
}
|
||||
last_update = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin carbon_plugin = {
|
||||
|
||||
.name = "carbon",
|
||||
|
||||
.options = carbon_options,
|
||||
.master_cycle = carbon_master_cycle,
|
||||
.post_init = carbon_post_init,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='carbon'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['carbon']
|
||||
+888
-45
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user